diff --git a/package.json b/package.json index bd17e6d..ca2c315 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,17 @@ ], "contributes": { "languages": [ + { + "id": "tcl", + "aliases": [ + "NX TCL", + "tcl" + ], + "extensions": [ + ".tcl" + ], + "configuration": "./language-configuration.json" + }, { "id": "cdl", "aliases": [ @@ -46,6 +57,11 @@ } ], "grammars": [ + { + "language": "tcl", + "scopeName": "source.tcl", + "path": "./syntaxes/tcl.tmLanguage.json" + }, { "language": "cdl", "scopeName": "source.cdl", diff --git a/syntaxes/tcl.tmLanguage.json b/syntaxes/tcl.tmLanguage.json new file mode 100644 index 0000000..2d7bc5f --- /dev/null +++ b/syntaxes/tcl.tmLanguage.json @@ -0,0 +1,424 @@ +{ + "fileTypes": [ + "tcl" + ], + "name": "tcl", + "patterns": [ + { + "include": "#main" + } + ], + "scopeName": "source.tcl", + "repository": { + "main": { + "patterns": [ + { + "include": "#command" + } + ] + }, + "args": { + "patterns": [ + { + "include": "#quoted_args" + }, + { + "include": "#numeric" + }, + { + "match": "((?<=;)\\s*#.*$)", + "name": "comment.tcl", + "comment": "Inline comments." + } + ] + }, + "braced": { + "patterns": [ + { + "begin": "((?(?:\\\\{|\\\\}|[^\\x{007b}\\x{007d}])*)*)})", + "name": "none.tcl", + "comment": "Handle braced literal." + } + ] + }, + "braced_lit_re": { + "patterns": [ + { + "match": "((?:(?(?:\\\\{|\\\\}|[^\\x{007b}\\x{007d}])*)*)})", + "name": "string.regexp.tcl", + "comment": "Handle braced regex pattern." + } + ] + }, + "command": { + "patterns": [ + { + "begin": "(\\\\\\s*$)", + "beginCaptures": { + "1": { + "name": "constant.character.escape.tcl" + } + }, + "patterns": [ + { + "include": "#command__1" + } + ], + "end": "((?(?:\\\\{|\\\\}|[^\\x{007b}\\x{007d}])*)*)})", + "captures": { + "1": { + "name": "keyword.tcl" + }, + "2": { + "name": "entity.name.function.tcl" + }, + "3": { + "name": "none.tcl" + } + }, + "comment": "Proc command." + }, + { + "include": "#regexp" + }, + { + "include": "#keywords" + }, + { + "match": "(^\\s*\\S+|(?:(?<=[^\\x{005c}]\\[)[^\\s\\]]++(?!\\])))", + "name": "keyword.tcl", + "comment": "All other commands. (NOTE: Iro doesn't support possessive quantifiers, but the grammar does; be sure to replace the second + with ++ after regenerating!)" + }, + { + "include": "#args" + } + ] + }, + "command__1": { + "patterns": [ + { + "include": "#keywords" + }, + { + "include": "#args" + } + ] + }, + "embedded": { + "patterns": [ + { + "begin": "((? + + + + fileTypes + + tcl + + name + tcl + patterns + + + include + #main + + + scopeName + source.tcl + uuid + c7017136-2ff2-48e9-bdb0-570cf238b4a2 + repository + + main + + patterns + + + include + #command + + + + args + + patterns + + + include + #quoted_args + + + include + #numeric + + + match + ((?<=;)\s*#.*$) + name + comment.tcl + comment + Inline comments. + + + + braced + + patterns + + + begin + ((?<!\\)\{) + beginCaptures + + 1 + + name + punctuation.tcl + + + patterns + + + include + #braced__1 + + + end + (\}([^\s\]]*)) + endCaptures + + 1 + + name + punctuation.tcl + + + + + + braced__1 + + patterns + + + match + (\\(?:\d{1,3}|x[a-fA-F0-9]{1,2}|u[a-fA-F0-9]{1,4}|U[a-fA-F0-9]{1,8}|.)) + name + constant.character.escape.tcl + + + include + #keywords + + + match + ((?<={)\s*(?:after|append|apply|array|auto_execok|auto_import|auto_load|auto_mkindex|auto_qualify|auto_reset|bgerror|binary|break|catch|cd|chan|clock|close|concat|continue|coroutine|dde|dict|encoding|eof|error|eval|exec|exit|expr|fblocked|fconfigure|fcopy|fileevent|file|flush|foreach|for|format|gets|global|glob|history|http|if|incr|info|interp|join|lappend|lassign|lindex|linsert|list|llength|lmap|load|lrange|lrepeat|lreplace|lreverse|lsearch|lset|lsort|memory|my|namespace|nextto|next|oo::class|oo::copy|oo::define|oo::objdefine|oo::object|open|package|parray|pid|pkg::create|pkg_mkIndex|platform::shell|proc|puts|pwd|read|regexp|registry|regsub|rename|return|scan|seek|self|set|socket|source|split|string|subst|switch|tailcall|tcl::prefix|tcl_endOfWord|tcl_findLibrary|tcl_startOfNextWord|tcl_startOfPreviousWord|tcl_wordBreakAfter|tcl_wordBreakBefore|tell|throw|time|trace|try|unknown|unload|unset|update|uplevel|upvar|variable|vwait|while|yieldto|yield)\s+) + name + keyword.tcl + comment + Special handling for known commands. + + + include + #braced_inner + + + include + #args + + + + braced_inner + + patterns + + + begin + (\{) + beginCaptures + + 1 + + name + punctuation.tcl + + + patterns + + + include + #braced_inner__1 + + + end + (\}) + endCaptures + + 1 + + name + punctuation.tcl + + + + + + braced_inner__1 + + patterns + + + match + (\\[\x{007b}\x{007d}]) + name + constant.character.escape.tcl + + + include + #numeric + + + include + #braced_inner + + + include + #args + + + + braced_lit + + patterns + + + match + ((?:(?<!\\){)(?:[^\x{007b}\x{007d}\n]*(?:\g<1>(?:\\{|\\}|[^\x{007b}\x{007d}])*)*)}) + name + none.tcl + comment + Handle braced literal. + + + + braced_lit_re + + patterns + + + match + ((?:(?<!\\){)(?:[^\x{007b}\x{007d}\n]*(?:\g<1>(?:\\{|\\}|[^\x{007b}\x{007d}])*)*)}) + name + string.regexp.tcl + comment + Handle braced regex pattern. + + + + command + + patterns + + + begin + (\\\s*$) + beginCaptures + + 1 + + name + constant.character.escape.tcl + + + patterns + + + include + #command__1 + + + end + ((?<!\\\s)$) + endCaptures + + 1 + + name + none.tcl + + + + + match + (^\s*#.*) + name + comment.tcl + comment + Line comments. + + + match + (\{\s*$|^\s*\}) + name + punctuation.tcl + comment + Leading/trailing curly braces. + + + match + (?<=^|{)(\s*proc\s+)(\S+\s+)((?:(?<!\\){)(?:[^\x{007b}\x{007d}\n]*(?:\g<1>(?:\\{|\\}|[^\x{007b}\x{007d}])*)*)}) + captures + + 1 + + name + keyword.tcl + + 2 + + name + entity.name.function.tcl + + 3 + + name + none.tcl + + + comment + Proc command. + + + include + #regexp + + + include + #keywords + + + match + (^\s*\S+|(?:(?<=[^\x{005c}]\[)[^\s\]]++(?!\]))) + name + keyword.tcl + comment + All other commands. (NOTE: Iro doesn't support possessive quantifiers, but the grammar does; be sure to replace the second + with ++ after regenerating!) + + + include + #args + + + + command__1 + + patterns + + + include + #keywords + + + include + #args + + + + embedded + + patterns + + + begin + ((?<!\\)\[) + beginCaptures + + 1 + + name + punctuation.tcl + + + patterns + + + include + #embedded__1 + + + end + ((?<!\\)\]) + endCaptures + + 1 + + name + punctuation.tcl + + + + + + embedded__1 + + patterns + + + include + #command + + + + keywords + + patterns + + + match + ((?<=^|[\[\x{007b}\x{003b}])\s*(break|catch|continue|default|error|exit|foreach|for|if|return|switch|throw|try|while)\b) + name + keyword.control.tcl + comment + Keywords. + + + match + ((?<=^|})\s*(then|elseif|else)\b) + name + keyword.control.tcl + comment + Inline keywords. + + + + numeric + + patterns + + + match + ((?:\b|[\+\-\.])(?:0b[01]+|0o[0-7]+|0x[0-9a-fA-F]+|(?:\d*\.\d+(?:[Ee][-\x{002b}]?\d+)?)|(?:\d+\.?[Ee][-\x{002b}]?\d+)|\d+|[Ii][Nn][Ff]|[Nn][Aa][Nn])\b) + name + constant.numeric.tcl + + + + quoted + + patterns + + + begin + ((?<!\\)") + beginCaptures + + 1 + + name + string.tcl + + + patterns + + + include + #quoted__1 + + + end + (") + endCaptures + + 1 + + name + string.tcl + + + + + + quoted__1 + + patterns + + + include + #quoted_args + + + match + ([^\x{0024}\x{005b}\x{0022}\x{005c}]+) + name + string.tcl + + + + quoted_args + + patterns + + + include + #braced + + + include + #quoted + + + include + #embedded + + + match + (\\(?:\d{1,3}|x[a-fA-F0-9]{1,2}|u[a-fA-F0-9]{1,4}|U[a-fA-F0-9]{1,8}|.)) + name + constant.character.escape.tcl + + + include + #variable + + + + regexp + + patterns + + + begin + ((?<=^|[\[\x{007b}\x{003b}])\s*(?:regexp|regsub)\s+)((?:(?:(?:-about|-all|-expanded|-indices|-inline|-lineanchor|-linestop|-line|-nocase|(?:-index\s+(?:end|\d+)(?:[\+\-]-?\d+)?))\s+)*(?:--\s+)?)?) + beginCaptures + + 1 + + name + keyword.tcl + + 2 + + name + none.tcl + + + patterns + + + include + #regexp__1 + + + end + (\s+) + endCaptures + + 1 + + name + none.tcl + + + + + include + #args + + + + regexp__1 + + patterns + + + include + #braced_lit_re + + + begin + ((?:(?<!\\)")) + beginCaptures + + 1 + + name + string.regexp.tcl + + + patterns + + + include + #regexp__2 + + + end + ((?:(?<!\\)")) + endCaptures + + 1 + + name + string.regexp.tcl + + + + + include + #variable + + + match + (\S+) + name + string.regexp.tcl + comment + Handle bare regex pattern. + + + + regexp__2 + + patterns + + + include + #braced_lit_re + + + include + #embedded + + + include + #variable + + + match + (\\"|[^\x{0022}]) + name + string.regexp.tcl + comment + All other quoted text. + + + + variable + + patterns + + + match + (\$(?:(?:[a-zA-Z0-9_]|::)+(?:\([^\)]+\))?|\{(?:[^\}]*|[^\}\x{0028}]+\([^\}\x{0029}]+\))\})) + name + variable.tcl + + + + word_lit__1 + + patterns + + + include + #braced_lit + + + include + #embedded + + + include + #variable + + + match + (\\"|[^\x{0022}]) + name + string.tcl + comment + All other quoted text. + + + + + + \ No newline at end of file diff --git a/test/test.tcl b/test/test.tcl new file mode 100644 index 0000000..0163f2d --- /dev/null +++ b/test/test.tcl @@ -0,0 +1,3 @@ +proc myProc {arg {opt 1}} { + +} \ No newline at end of file