form Highlighter test
  # This is a regular comment
  sentence Blank
  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 discarded
  boolean Binary 1
  boolean Text no
  boolean Quoted "yes"
  comment This should be a string
  optionmenu Drop-down: 1
    option Foo
    option 100
  choice Radio: 1
    option Foo
    option 100
  real left_Range -123.6
  positive right_Range_max 3.3
  integer Int 4
  natural Nat 4
endform

beginPause: "Highlighter test"
  sentence: "Blank", ""
  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 discarded"
  boolean: "Binary", 1
  comment: "This should be a string"
  optionMenu: "Drop-down", 1
    option: "Foo"
    option: "100"
  choice: "Choice", 1
    option: "Foo"
    option: "100"
  real: "left Range", -123.6
  positive: "right Range max", 3.3
  integer: "Int", 4
  natural: "Nat", 4
button = endPause("Cancel", "OK", 1, 2)

# Periods do not establish boundaries for keywords
form.var = 10
# Or operators
not.an.operator$ = "Bad variable name"
bad.or.not = 1

# External scripts
include /path/to/file
runScript: "/path/to/file"
execute /path/to/file

# Predefined variables
a  = praatVersion
a  = e + pi * ( all+right) / left mod average + (mono - stereo)
a$ = homeDirectory$ + tab$ + newline$
a$ = temporaryDirectory$
a$ = praatVersion$
a$ = shellDirectory$
a$ = homeDirectory$
a$ = preferencesDirectory$
a$ = defaultDirectory$
nocheck selectObject: undefined
# Not predefined variables
a$ = e$
a$ = pi$

# Arrays are not comments
a# = zero#(5)
a [3], 5 = 7
printline 'a[3,5]', 'a[3]'
a [1] = 2
b [a [1]] = 3
assert b [a [1]] = 3
printline 'b[2]'

# Matrices
m## = zero##(5, 6)
m## = {{1, 2}, {3, 4}}
m##[1, 2] = 3

# String vectors
strVec$# = empty$#(10)
strVec$# = {"foo", "bar"}
strVec$#[1] = "baz"

# 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

# Interpolation with precision digits
echo unquoted 'a:3'
echo unquoted 'a.a:3'
echo unquoted 'a[1]:3'
echo unquoted 'a1:3'

appendInfoLine: "quoted 'a:3'"
appendInfoLine: "quoted 'a.a:3'"
appendInfoLine: "quoted 'a[1]:3'"
appendInfoLine: "quoted 'a1:3'"

# Interpolations are not recursive
echo unquoted 'a'1':3'
appendInfoLine: "quoted 'a'1':3'"

# Interpolation without precision digits
echo unquoted 'var' numeric
echo unquoted 'var$' string
echo unquoted 'var["a"]' numeric hash
echo unquoted 'var$["a"]' string hash
echo unquoted 'var[1]' numeric indexed variable
echo unquoted 'var$[1]' string indexed variable

appendInfoLine: "quoted 'var' numeric"
appendInfoLine: "quoted 'var$' string"
appendInfoLine: "quoted 'var["a"]' numeric hash"
appendInfoLine: "quoted 'var$["a"]' string hash"
appendInfoLine: "quoted 'var[1]' numeric indexed variable"
appendInfoLine: "quoted 'var$[1]' string indexed variable"

# Indeces in interpolations must be literal
echo 'var[a]'
echo 'var[a$]'

string$ = "But don't interpolate everything!"
string$ = "interpolatin' " + "across" + " strings ain't cool either"
string$(10) ; This is a function

repeat
  string$ = string$ - right$(string$)
until !length(string$)

Text... 1 Right 0.2 Half many----hyphens
Text... 1 Right -0.4 Bottom aحبيبa
Text... 1 Right -0.6 Bottom 日本
Draw circle (mm)... 0.5 0.5 i

rows   = Object_'table'.nrow
value$ = Table_'table'$[25, "f0"]
fixed  = Sound_10.xmin
fixed  = Object_foo.xmin
fixed  = Procrustes_foo.nx
var["vaa"] = 1 ; Hash

# Special two-word keyword
select all
# Keyword with a predefined variable
select  all

# old-style procedure call
call oldStyle "quoted" 2 unquoted string
assert oldStyle.local = 1

# Interpolated procedure names
procname$ = "newStyle"
@'procname$':    "quoted", 2, "quoted string"
call 'procname$' "quoted" "2" unquoted string

# Funky procedure names!
@@%^&()
@#.!: "a"
call # 2
call # "string" 2 unquoted

procedure @#@#!
endproc

procedure 'not_expansion$': .var
endproc

procedure 'not_expansion$' (.var)
endproc

# 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

# inline if with inline comment
var = if macintosh = 1 then 0 else 1 fi ; This is an inline comment

Remove ; Not 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
  name = selected$(extractWord$(selected$(), " "))
  sound'i' = selected("Sound", i+(a*b))
  sound[i] = sound'i'
endfor

i = 1
while i < n
  i += 1
  # 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 Sound 'editor_name$'
    nocheck Close
  nocheck endeditor
  editor_id = editor: editor_name$
    Close
  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
  # Formulas are strings
  Formula: "if col = 1 then row * Object_'pitch'.dx + 'first' else self fi"

  # 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 f" + string$(3) + " " +
    ..."duration response"

  # Function call with trailing space
  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"
endwhile

switch$ = if switch == 1 then "a" else
  ...     if switch == 2 then "b" else
  ...     if switch == 3 then "c" else
  ...     if switch == 4 then "d" else
  ...     "default" fi fi fi fi

# An old-style sendpraat block
# All these lines should be a string!
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"

# Number types
a =   10%
a =  -10
a =  +10
a =   10.4
a =  294e12
a =    2.94e12

# Operators
a = 2 ^ -6
a = -(1+1)^6
a = 4^3 ^ 2
a = 54 div 5.1
a = 54.3 mod 5
a = 3 ** 8 - 7
a = 3 / (8 + 7)
a = (7 * (3 + 5)) / ((2 + 3) - 1)

# Logical operators
assert (a =   b) and c
assert  a == (b  or  c)
assert  a <=  b  not c
assert  a >=  b     !c
assert  a !=  b  &   c
assert  a !=  b  &&  c
assert  a <>  b  ||  c
assert  a <   b  |   c
assert  a >   b

assert (a)or (b)
assert (a) or(b)
assert (a)and(b)

assert "hello" =  "he" + "llo"
assert "hello" == "hello world" - " world"

stopwatch
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 with parentheses
procedure newStyle (.str1$, .num, .str2$)
  # Command with "local" variable
  .local = Get total duration
  .local = Get 'some' duration
  .local = Get 'some[1]' value... hello 10 p[i]
  .local = Get 'some[1,3]' value: "hello", 10, p[i]
  .local = Get 'some$' duration
  .local = Get 'some$[1]' duration
endproc

# New-style procedure declaration with colon
procedure _new_style: .str1$, .num, .str2$
  # Command with "local" variable
  # Initial underscores in variables not allowed (unless interpolated)
  _new_style.local = Get total duration
endproc

asserterror Unknown symbol:'newline$'« _
assert '_new_style.local'

@proc: a, selected("string"), b
# Comment

for i to saveSelection.n
  selectObject: saveSelection.id[i]
  appendInfoLine: selected$()
endfor

@ok(if selected$("Sound") = "tone" then 1 else 0 fi,
  ... "selected sound is tone")

@ok_formula("selected$(""Sound"") = ""tone""", "selected sound is tone")

call try
  ... 'newline$' # This is really all a string, but it is undetectable
  ... 'newline$' # without knowing the arguments for the procedure
  ... 'newline$' assert "hello" =  "he" + "llo"
  ... 'newline$' assert "hello" == "hello world" - " world"
