diff --git a/demo/kitchen-sink/docs/praat.praat b/demo/kitchen-sink/docs/praat.praat new file mode 100644 index 00000000..3700ae6f --- /dev/null +++ b/demo/kitchen-sink/docs/praat.praat @@ -0,0 +1,148 @@ +form Highlighter test + sentence My_sentence This should all be a string + text My_text This should also all be a string + word My_word Only the first word is a string, the rest is invalid + boolean Binary 1 + boolean Text no + boolean Quoted "yes" + comment This should be a string + real left_Range -123.6 + positive right_Range_max 3.3 + integer Int 4 + natural Nat 4 +endform + +# External scripts +include /path/to/file +runScript: "/path/to/file" +execute /path/to/file + +stopwatch + +# old-style procedure call +call oldStyle "quoted" 2 unquoted string +assert oldStyle.local = 1 + +# New-style procedure call with parens +@newStyle("quoted", 2, "quoted string") +if praatVersion >= 5364 + # New-style procedure call with colon + @newStyle: "quoted", 2, "quoted string" +endif + +# if-block with built-in variables +if windows + # We are on Windows +elsif unix = 1 or !macintosh + exitScript: "We are on Linux" +else macintosh == 1 + exit We are on Mac +endif + +# inline if with inline comment +var = if macintosh = 1 then 0 else 1 fi ; This is an inline comment + +# for-loop with explicit from using local variable +# and paren-style function calls and variable interpolation +n = numberOfSelected("Sound") +for i from newStyle.local to n + sound'i' = selected("Sound", i) + sound[i] = sound'i' +endfor + +for i from 1 to n + # Different styles of object selection + select sound'i' + sound = selected() + sound$ = selected$("Sound") + select Sound 'sound$' + selectObject(sound[i]) + selectObject: sound + + # Pause commands + beginPause("Viewing " + sound$) + if i > 1 + button = endPause("Stop", "Previous", + ...if i = total_sounds then "Finish" else "Next" fi, + ...3, 1) + else + button = endPause("Stop", + ...if i = total_sounds then "Finish" else "Next" fi, + ...2, 1) + endif + editor_name$ = if total_textgrids then "TextGrid " else "Sound " fi + name$ + nocheck editor 'editor_name$' + nocheck Close + nocheck endeditor + + # New-style standalone command call + Rename: "SomeName" + + # Command call with assignment + duration = Get total duration + + # Multi-line command with modifier + pitch = noprogress To Pitch (ac): 0, 75, 15, "no", + ...0.03, 0.45, 0.01, 0.35, 0.14, 600 + + # do-style command with assignment + minimum = do("Get minimum...", 0, 0, "Hertz", "Parabolic") + + # New-style multi-line command call with broken strings + table = Create Table with column names: "table", 0, + ..."file subject speaker + ...f0 f1 f2 f3 " + + ..."duration response" + + removeObject: pitch, table + + # Picture window commands + selectObject: sound + # do-style command + do("Select inner viewport...", 1, 6, 0.5, 1.5) + Black + Draw... 0 0 0 0 "no" Curve + Draw inner box + Text bottom: "yes", sound$ + Erase all + + # Demo window commands + demo Erase all + demo Select inner viewport... 0 100 0 100 + demo Axes... 0 100 0 100 + demo Paint rectangle... white 0 100 0 100 + demo Text... 50 centre 50 half Click to finish + demoWaitForInput ( ) + demo Erase all + demo Text: 50, "centre", 50, "half", "Finished" +endfor + +# An old-style sendpraat block +sendpraat Praat + ...'newline$' Create Sound as pure tone... "tone" 1 0 0.4 44100 440 0.2 0.01 0.01 + ...'newline$' Play + ...'newline$' Remove + +# A new-style sendpraat block +beginSendPraat: "Praat" + Create Sound as pure tone: "tone", 1, 0, 0.4, 44100, 440, 0.2, 0.01, 0.01 + duration = Get total duration + Remove +endSendPraat: "duration" +appendInfoLine: "The generated sound lasted for ", duration, "seconds" + +time = stopwatch +clearinfo +echo This script took +print 'time' seconds to +printline execute. + +# Old-style procedure declaration +procedure oldStyle .str1$ .num .str2$ + .local = 1 +endproc + +# New-style procedure declaration +procedure newStyle (.str1$, .num, .str2$) + .local = 1 +endproc diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index 15a31610..2028386e 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -114,6 +114,7 @@ var supportedModes = { pgSQL: ["pgsql"], PHP: ["php|phtml"], Powershell: ["ps1"], + Praat: ["praat|praatscript|psc|proc"], Prolog: ["plg|prolog"], Properties: ["properties"], Protobuf: ["proto"], diff --git a/lib/ace/mode/praat.js b/lib/ace/mode/praat.js new file mode 100644 index 00000000..7b100ef0 --- /dev/null +++ b/lib/ace/mode/praat.js @@ -0,0 +1,84 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var PraatHighlightRules = require("./praat_highlight_rules").PraatHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var Range = require("../range").Range; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + this.HighlightRules = PraatHighlightRules; + + this.$outdent = new MatchingBraceOutdent(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.lineCommentStart = "#"; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + var tokenizedLine = this.getTokenizer().getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start") { + var match = line.match(/^.*[\{\(\[\:]\s*$/); + if (match) { + indent += tab; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.$id = "ace/mode/praat"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); diff --git a/lib/ace/mode/praat_highlight_rules.js b/lib/ace/mode/praat_highlight_rules.js new file mode 100644 index 00000000..8b826487 --- /dev/null +++ b/lib/ace/mode/praat_highlight_rules.js @@ -0,0 +1,262 @@ +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var PraatHighlightRules = function() { + + var keywords = ( + "if|then|else|elsif|elif|endif|fi|" + + "endfor|endproc|" + // related keywords specified below + "while|endwhile|" + + "repeat|until|" + + "select|plus|minus|" + + "assert" + ); + + var predefinedVariables = ( + "macintosh|windows|unix|" + + "praatVersion|praatVersion\\$" + + "pi|undefined|" + + "newline\\$|tab\\$|" + + "shellDirectory\\$|homeDirectory\\$|preferencesDirectory\\$|" + + "temporaryDirectory\\$|defaultDirectory\\$" + ); + + // What is "endSendPraat"? Function? Directive? + var directives = ( + "clearinfo|endSendPraat" + ); + + var functions = ( +// Info functions + "writeInfo|writeInfoLine|appendInfo|appendInfoLine|" + + "writeFile|writeFileLine|appendFile|appendFileLine|" + +// Math functions + "abs|round|floor|ceiling|min|max|imin|imax|" + + "sqrt|sin|cos|tan|arcsin|arccos|arctan|arctan2|sinc|sincpi|" + + "exp|ln|log10|log2|" + + "sinh|cosh|tanh|arcsinh|arccosh|actanh|" + + "sigmoid|invSigmoid|erf|erfc|" + + "randomUniform|randomInteger|randomGauss|randomPoisson|" + + "lnGamma|gaussP|gaussQ|invGaussQ|" + + "chiSquareP|chiSquareQ|invChiSquareQ|studentP|studentQ|invStudentQ|" + + "fisherP|fisherQ|invFisherQ|" + + "binomialP|binomialQ|invBinomialP|invBinomialQ|" + + "hertzToBark|barkToHerz|" + + "hertzToMel|melToHertz|" + + "hertzToSemitones|semitonesToHerz|" + + "erb|hertzToErb|erbToHertz|" + + "phonToDifferenceLimens|differenceLimensToPhon|" + + "beta|besselI|besselK|" + +// String functions + "selected|selected\\$|numberOfSelected|variableExists|"+ + "index|rindex|startsWith|endsWith|"+ + "index_regex|rindex_regex|replace_regex\\$|"+ + "length|extractWord\\$|extractLine\\$|extractNumber|" + + "left\\$|right\\$|mid\\$|replace\\$|" + +// Pause functions + "beginPause|endPause|" + +// Demo functions + "demoShow|demoWindowTitle|demoInput|demoWaitForInput|" + + "demoClicked|demoClickedIn|demoX|demoY|" + + "demoKeyPressed|demoKey\\$|" + + "demoExtraControlKeyPressed|demoShiftKeyPressed|"+ + "demoCommandKeyPressed|demoOptionKeyPressed|" + +// File functions + "environment\\$|chooseReadFile\\$|" + + "chooseDirectory\\$|createDirectory|fileReadable|deleteFile|" + + "selectObject|removeObject|plusObject|minusObject|" + + "runScript|exitScript|" + +// sendpraat functions + "beginSendPraat|endSendPraat" + ); + + var objectTypes = ( + "Activation|AffineTransform|AmplitudeTier|Art|Artword|Autosegment|" + + "BarkFilter|CCA|Categories|Cepstrum|Cepstrumc|ChebyshevSeries|" + + "ClassificationTable|Cochleagram|Collection|Configuration|" + + "Confusion|ContingencyTable|Corpus|Correlation|Covariance|" + + "CrossCorrelationTable|CrossCorrelationTables|DTW|Diagonalizer|" + + "Discriminant|Dissimilarity|Distance|Distributions|DurationTier|" + + "EEG|ERP|ERPTier|Eigen|Excitation|Excitations|ExperimentMFC|FFNet|" + + "FeatureWeights|Formant|FormantFilter|FormantGrid|FormantPoint|" + + "FormantTier|GaussianMixture|HMM|HMM_Observation|" + + "HMM_ObservationSequence|HMM_State|HMM_StateSequence|Harmonicity|" + + "ISpline|Index|Intensity|IntensityTier|IntervalTier|KNN|KlattGrid|" + + "KlattTable|LFCC|LPC|Label|LegendreSeries|LinearRegression|" + + "LogisticRegression|LongSound|Ltas|MFCC|MSpline|ManPages|" + + "Manipulation|Matrix|MelFilter|MixingMatrix|Movie|Network|" + + "OTGrammar|OTHistory|OTMulti|PCA|PairDistribution|ParamCurve|" + + "Pattern|Permutation|Pitch|PitchTier|PointProcess|Polygon|" + + "Polynomial|Procrustes|RealPoint|RealTier|ResultsMFC|Roots|SPINET|" + + "SSCP|SVD|Salience|ScalarProduct|Similarity|SimpleString|" + + "SortedSetOfString|Sound|Speaker|Spectrogram|Spectrum|SpectrumTier|" + + "SpeechSynthesizer|SpellingChecker|Strings|StringsIndex|Table|" + + "TableOfReal|TextGrid|TextInterval|TextPoint|TextTier|Tier|" + + "Transition|VocalTract|Weight|WordList" + ); + + // regexp must not have capturing parentheses. Use (?:) instead. + // regexps are ordered -> the first match is used + + this.$rules = { + "start" : [ + { + // Interpolated strings + token : "string.interpolated", + regex : /'((?:[a-z][a-zA-Z0-9_]*)(?:\$|#|:[0-9]+)?)'/ + }, { + // stopwatch + token : ["text", "text", "keyword.operator", "text", "keyword"], + regex : /(^\s*)(?:([a-z][a-zA-Z0-9_]*\$?\s+)(=)(\s+))?(stopwatch)/ + }, { + // Directives which introduce unquoted strings + token : ["text", "keyword", "text", "string"], + regex : /(^\s*)(print(?:line)?|echo|exit|pause|sendpraat|include|execute)(\s+)(.*)/ + }, { + // Directives with no arguments + token : ["text", "keyword"], + regex : "(^\\s*)(" + directives + ")$" + }, { + // Operators + token : ["text", "keyword.operator", "text"], + regex : /(\s+)((?:\+|-|\/|\*|<|>)=?|==?|!=|%|\^|\||and|or|not)(\s+)/ + }, { + // Commands + token : ["text", "text", "keyword.operator", "text", "keyword", "text", "keyword"], + regex : /(^\s*)(?:([a-z][a-zA-Z0-9_]*\$?\s+)(=)(\s+))?(?:((?:no)?warn|nocheck|noprogress)(\s+))?((?:[A-Z][^.:"]+)(?:$|(?:\.{3}|:)))/ + }, { + // Demo commands + token : ["text", "keyword", "text", "keyword"], + regex : /(^\s*)(?:(demo)?(\s+))((?:[A-Z][^.:"]+)(?:$|(?:\.{3}|:)))/ + }, { + // Font-sizing commands + token : ["text", "keyword", "text", "keyword"], + regex : /^(\s*)(?:(demo)(\s+))?(10|12|14|16|24)$/ + }, { + // do-style command calls + token : ["text", "support.function", "text"], + regex : /(\s*)(do\$?)(\s*:\s*|\s*\(\s*)/ + }, { + // Object types + token : "entity.name.type", + regex : "(" + objectTypes + ")" + }, { + // Predefined variables + token : "variable.language", + regex : "(" + predefinedVariables + ")" + }, { + // Functions + token : ["support.function", "text"], + regex : "((?:" + functions + ")\\$?)(\\s*(?::|\\())" + }, { + // For-loop declarations + token : "keyword", + regex : /(\bfor\b)/, + next : "for" + }, { + // Generic keywords + token : "keyword", + regex : "(\\b(?:" + keywords + ")\\b)" + }, { + // Generic strings + token : "string", + regex : /"[^"]*"/ + }, { + // Multiline quoted strings + token : "string", + regex : /"[^"]*$/, + next : "brokenstring" + }, { + // Form declarations + token : ["text", "keyword", "text", "entity.name.section"], + regex : /(^\s*)(\bform\b)(\s+)(.*)/, + next : "form" + }, { + // Numeric constants + token : "constant.numeric", + regex : /\b[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/ + }, { + // Procedure declarations + token : ["keyword", "text", "entity.name.function"], + regex : /(procedure)(\s+)(\S+)/ + }, { + // New-style procedure calls + token : ["entity.name.function", "text"], + regex : /(@\S+)(:|\s*\()/ + }, { + // Old-style procedure calls + token : ["text", "keyword", "text", "entity.name.function"], + regex : /(^\s*)(call)(\s+)(\S+)/ + }, { + // Comments + token : "comment", + regex : /(^\s*#|;).*$/ + }, { + token : "text", + regex : /\s+/ + } + ], + "form" : [ + { + token : ["keyword", "text", "constant.numeric"], + regex : /((?:optionmenu|choice)\s+)(\S+:\s+)([0-9]+)/ + }, { + token : ["keyword", "constant.numeric"], + regex : /((?:option|button)\s+)([+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b)/ + }, { + token : ["keyword", "string"], + regex : /((?:option|button)\s+)(.*)/ + }, { + token : ["keyword", "text", "string"], + regex : /((?:sentence|text)\s+)(\S+\s*)(.*)/ + }, { + token : ["keyword", "text", "string", "invalid.illegal"], + regex : /(word\s+)(\S+\s*)(\S+)?(\s.*)?/ + }, { + token : ["keyword", "text", "constant.language"], + regex : /(boolean\s+)(\S+\s*)(0|1|"?(?:yes|no)"?)/ + }, { + token : ["keyword", "text", "constant.numeric"], + regex : /((?:real|natural|positive|integer)\s+)(\S+\s*)([+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b)/ + }, { + token : ["keyword", "string"], + regex : /(comment\s+)(.*)/ + }, { + token : "keyword", + regex : 'endform', + next : "start" + } + ], + "for" : [ + { + token : ["keyword", "text", "constant.numeric", "text"], + regex : /(from|to)(\s+)([+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?)(\s*)/ + }, { + token : ["keyword", "text"], + regex : /(from|to)(\s+\S+\s*)/ + }, { + token : "text", + regex : /$/, + next : "start" + } + ], + "brokenstring" : [ + { + token : ["text", "string"], + regex : /(\s*\.{3})([^"]*)/ + }, { + token : "string", + regex : /"/, + next : "start" + } + ], + }; +}; + +oop.inherits(PraatHighlightRules, TextHighlightRules); + +exports.PraatHighlightRules = PraatHighlightRules; +}); diff --git a/lib/ace/snippets/praat.js b/lib/ace/snippets/praat.js new file mode 100644 index 00000000..18afa87f --- /dev/null +++ b/lib/ace/snippets/praat.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./praat.snippets"); +exports.scope = "praat"; + +}); diff --git a/lib/ace/snippets/praat.snippets b/lib/ace/snippets/praat.snippets new file mode 100644 index 00000000..e69de29b