From 660878eb8cde290ff49e7f41c2bd7432ee284f6e Mon Sep 17 00:00:00 2001 From: Raoul Wols Date: Thu, 8 Jun 2017 23:12:42 +0200 Subject: [PATCH] [ShellScript] Rewrite Issue links ----------- Intends to close https://github.com/sublimehq/Packages/issues/434 Fixes https://github.com/sublimehq/Packages/issues/626 Fixes https://github.com/sublimehq/Packages/issues/190 Fixes https://github.com/sublimehq/Packages/issues/46 Goodies ------- * Proper context sensitive command invocations * Variable expansion as from ShellScriptImproved * Backtick handling as from ShellScriptImproved * No with_prototype contexts * Generic options handling * Builtin-commands know their valid options * Renamed Shell-Unix-Generic to bash, as it's really just bash (and dash) About 1300 syntax tests, tested out in the wild with various bash scripts. Deficiencies ------------ The heredocs handling is still not perfect, but it gets the job done if you don't have a function definition, inline if-block or compound command on the same line as the start of the heredoc token. * It's easy to bring back the embedded language highlighting for particular heredoc tokens, but this is omitted for now. * It's easy to embed the regex language for regex matching in if-blocks at this point. Acknowledgements ---------------- * @jfcherng for starting ShellScriptImproved and the huge amount of syntax tests, * @okdana for creating syntax tests, * @fichtefoll for pointing me to the Ruby syntax for heredoc handling, * @keith-hall, @wbond for their suggestions about scope names. --- ...mPreferences => Indentation.tmPreferences} | 2 +- ShellScript/Makefile | 15 + ShellScript/Shell-Unix-Generic.sublime-syntax | 567 -------- ShellScript/ShellScript.py | 36 + ShellScript/ShellScript.sublime-build | 4 + .../Symbol List - Functions.tmPreferences | 18 + .../Symbol List - Variables.tmPreferences | 18 + ShellScript/bash.sublime-syntax | 946 ++++++++++++++ ...commands-builtin-shell-bash.sublime-syntax | 1000 ++++++++++++++ ShellScript/commands-builtin-shell-bash.yml | 127 ++ ShellScript/test/syntax_test_bash.sh | 1160 +++++++++++++++++ ShellScript/tools/update-commands.py | 135 ++ 12 files changed, 3460 insertions(+), 568 deletions(-) rename ShellScript/{Miscellaneous.tmPreferences => Indentation.tmPreferences} (93%) create mode 100644 ShellScript/Makefile delete mode 100644 ShellScript/Shell-Unix-Generic.sublime-syntax create mode 100644 ShellScript/ShellScript.py create mode 100644 ShellScript/ShellScript.sublime-build create mode 100644 ShellScript/Symbol List - Functions.tmPreferences create mode 100644 ShellScript/Symbol List - Variables.tmPreferences create mode 100644 ShellScript/bash.sublime-syntax create mode 100644 ShellScript/commands-builtin-shell-bash.sublime-syntax create mode 100644 ShellScript/commands-builtin-shell-bash.yml create mode 100644 ShellScript/test/syntax_test_bash.sh create mode 100644 ShellScript/tools/update-commands.py diff --git a/ShellScript/Miscellaneous.tmPreferences b/ShellScript/Indentation.tmPreferences similarity index 93% rename from ShellScript/Miscellaneous.tmPreferences rename to ShellScript/Indentation.tmPreferences index 99a016ba82..869b47e6ea 100644 --- a/ShellScript/Miscellaneous.tmPreferences +++ b/ShellScript/Indentation.tmPreferences @@ -2,7 +2,7 @@ name - Miscellaneous + Indentation scope source.shell settings diff --git a/ShellScript/Makefile b/ShellScript/Makefile new file mode 100644 index 0000000000..7450965c08 --- /dev/null +++ b/ShellScript/Makefile @@ -0,0 +1,15 @@ +# The update script is located in the tools subdirectory because otherwise +# Sublime will read the file during start-up. No need for that. + +all: $(addsuffix .sublime-syntax, $(basename $(wildcard *.yml))) + +%.sublime-syntax: %.yml tools/update-commands.py + @printf "$< ==> $@ ... " + @python tools/update-commands.py $< $@ + @echo "Done." + +test: + @-/usr/bin/env bash test/syntax_test_bash.sh 2>&1 \ + | sed -nE "/^test\/syntax_test_bash.sh: line [[:digit:]]+: syntax .*/p" + +.PHONY: test diff --git a/ShellScript/Shell-Unix-Generic.sublime-syntax b/ShellScript/Shell-Unix-Generic.sublime-syntax deleted file mode 100644 index 19e9bbce58..0000000000 --- a/ShellScript/Shell-Unix-Generic.sublime-syntax +++ /dev/null @@ -1,567 +0,0 @@ -%YAML 1.2 ---- -# http://www.sublimetext.com/docs/3/syntax.html -name: Shell Script (Bash) -file_extensions: - - sh - - bash - - zsh - - .bash_aliases - - .bash_functions - - .bash_login - - .bash_logout - - .bash_profile - - .bash_variables - - .bashrc - - .profile - - .textmate_init -first_line_match: '^#!.*\b(bash|zsh|sh|tcsh)|^#\s*-\*-[^*]*mode:\s*shell-script[^*]*-\*-' -scope: source.shell -contexts: - main: - - include: comment - - include: pipeline - - include: list - - include: compound-command - - include: loop - - include: function-definition - - include: string - - include: variable - - include: interpolation - - include: heredoc - - include: herestring - - include: redirection - - include: pathname - - include: keyword - - include: support - comment: - - match: '(?|&&|\|\|' - comment: do we want a special rule for ( expr )? - scope: keyword.operator.logical.shell - - match: '(?[>=]?|==|!=|^|\|{1,2}|&{1,2}|\?|\:|,|=|[*/%+\-&^|]=|<<=|>>=' - scope: keyword.operator.arithmetic.shell - - match: '0[xX]\h+' - scope: constant.numeric.hex.shell - - match: '0\d+' - scope: constant.numeric.octal.shell - - match: '\d{1,2}#[0-9a-zA-Z@_]+' - scope: constant.numeric.other.shell - - match: \d+ - scope: constant.numeric.integer.shell - pathname: - - match: '(?<=[a-zA-Z0-9_])=(?=\s*$|[^\s])' - scope: keyword.operator.assign.shell - - match: (?<=\s|:|=|^)~ - scope: keyword.operator.tilde.shell - - match: \*|\? - scope: keyword.operator.glob.shell - - match: '([?*+@!])(\()' - captures: - 1: keyword.operator.extglob.shell - 2: punctuation.definition.extglob.shell - push: - - meta_scope: meta.structure.extglob.shell - - match: (\)) - captures: - 1: punctuation.definition.extglob.shell - pop: true - - include: main - pipeline: - - match: '\b(clang\+\+|g\+\+)' - scope: keyword.other.shell - - match: '\b(7za|alias|apropos|apt-get|aptitude|ar|aspell|autoconf|awk|base64|basename|bash|bc|bg|bind|brew|builtin|bzip2|cal|cat|cc|cd|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clang|clear|cmake|cmp|comm|command|cp|cron|crontab|crontab|csh|lua|csplit|cut|date|dc|dd|ddrescue|declare|depmod|df|diff3?|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|thtool|eval|exec|exit|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|function|fuser|gawk|gcc|getopts|git|grep|groupadd|groupdel|groupmd|groups|gzip|hash|head|help|hg|history|hostname|iconv|id|ifconfig|ifdown|ifup|import|insmod|install|jar|java|jobs|join|kill|killall|kmod|less|let|link|llvm|ln|local|locate|logname|loout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsod|lsof|mail|make|man|md5sum|mkdir|mkfifo|mkisofs|mknod|mmv|modinfo|modprobe|more|most|mount|mtools|mtr|mutt|mv|mysql|netstat|nice|nl|nohup|notify-se|nslookup|nstat|op|open|openssl|paswd|paste|pathchk|perl|php|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|py|python[\d.]*|quota|quotachec|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|remsync|renae|renice|return|rev|rm|rmdir|rmmod|rsync|ruby|scp|screen|sdiff|sed|select|seq|set|sftp|sh|shift|shopt|shutdown|sleep|slocate|sort|source|split|sqlite3?|ssh|stat|strace|su|sudo|sum|susend|svn|sync|tail|tar|tcsh|tee|test|time|timeout|times|top|touch|tput|tr|tracerout|trap|true|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unset|unshar|unil|updatedb|uptime|useradd|userdel|usermod|users|uudecode|uuencode|vmstat|wait|watch|wc|wget|whatis|whereis|which|while|who|whoami|write|xargs|xdg-open|xz|yum|zip|zsh)\b' - scope: keyword.other.shell - - match: "[|!]" - scope: keyword.operator.pipe.shell - redirection: - - match: '[><]\(' - captures: - 0: punctuation.definition.string.begin.shell - push: - - meta_scope: string.interpolated.process-substitution.shell - - match: \) - captures: - 0: punctuation.definition.string.end.shell - pop: true - - include: main - - match: '&>|\d*>&\d*|\d*(>>|>|<)|\d*<&|\d*<>' - comment: "valid: &>word >&word >word [n]>&[n] [n]word [n]>>word [n]<&word (last one is duplicate)" - scope: keyword.operator.redirect.shell - string: - - match: \\. - scope: constant.character.escape.shell - - match: "'" - captures: - 0: punctuation.definition.string.begin.shell - push: - - meta_scope: string.quoted.single.shell - - match: "'" - captures: - 0: punctuation.definition.string.end.shell - pop: true - - match: \$?" - captures: - 0: punctuation.definition.string.begin.shell - push: - - meta_scope: string.quoted.double.shell - - match: '"' - captures: - 0: punctuation.definition.string.end.shell - pop: true - - match: '\\[\$`"\\\n]' - scope: constant.character.escape.shell - - include: variable - - include: interpolation - - match: \$' - captures: - 0: punctuation.definition.string.begin.shell - push: - - meta_scope: string.quoted.single.dollar.shell - - match: "'" - captures: - 0: punctuation.definition.string.end.shell - pop: true - - match: \\(a|b|e|f|n|r|t|v|\\|') - scope: constant.character.escape.ansi-c.shell - - match: '\\[0-9]{3}' - scope: constant.character.escape.octal.shell - - match: '\\x[0-9a-fA-F]{2}' - scope: constant.character.escape.hex.shell - - match: \\c. - scope: constant.character.escape.control-char.shell - support: - - match: (?<=^|\s)(?::|\.)(?=\s|;|&|$) - scope: support.function.builtin.shell - - match: '(? + + + name + Symbol List - Functions + scope + entity.name.function.shell + settings + + showInSymbolList + 1 + showInIndexedSymbolList + 1 + symbolTransformation + s/.+/function\: $0/ + + + diff --git a/ShellScript/Symbol List - Variables.tmPreferences b/ShellScript/Symbol List - Variables.tmPreferences new file mode 100644 index 0000000000..b61fa617dc --- /dev/null +++ b/ShellScript/Symbol List - Variables.tmPreferences @@ -0,0 +1,18 @@ + + + + name + Symbol List - Variables + scope + variable.other.readwrite.assignment.shell + settings + + showInSymbolList + 1 + showInIndexedSymbolList + 0 + symbolTransformation + s/.+/variable\: $0/ + + + diff --git a/ShellScript/bash.sublime-syntax b/ShellScript/bash.sublime-syntax new file mode 100644 index 0000000000..b24bde67fd --- /dev/null +++ b/ShellScript/bash.sublime-syntax @@ -0,0 +1,946 @@ +%YAML 1.2 +# [Sublime]: https://www.sublimetext.com/docs/3/syntax.html +# [Bash]: https://www.gnu.org/software/bash/manual/bash.html +--- #--------------------------------------------------------------------------- + +name: Bourne Again Shell (bash) + +# The suffix is bash, but we still use .shell as a suffix anyway. This is to +# promote reusability of foreign scopes. +scope: source.shell.bash + +file_extensions: + - sh + - bash + - zsh + - fish + - .bash_aliases + - .bash_functions + - .bash_login + - .bash_logout + - .bash_profile + - .bash_variables + - .bashrc + - .profile + - .textmate_init + +first_line_match: '^#!.*\b(bash|zsh|sh|tcsh)\b|^#\s*-\*-[^*]*mode:\s*shell-script[^*]*-\*-' + +#------------------------------------------------------------------------------- +variables: + identifier: '[[:alpha:]_][[:alnum:]_]*' + + is_start_of_arguments: \s|; + is_variable: (?=\s*[^=\s]+=) + is_function: \b(function)\s+|(?=\s*{{identifier}}\s*\(\s*\)) + is_command: \s*(?=\S) + is_end_of_option: '[^\w$-]|$' + is_end_of_interpolation: \) + is_path_component: (?=[^\s/]*/) + extension: \.sh + call_token: \./ + + varassign: '[+\-?]?=' + # varassign: = + start_of_option: (?<=\s|^)--?(?=[\w$]) + cmd_boundary: (?=\s|;|$) + + reset_semicolon: \s*(;)(?!;) + reset_or: \s*(\|\|) + reset_and: \s*(&&) + reset_pipe: \s*(\|) +#------------------------------------------------------------------------------- +contexts: + + line-continuation-or-pop-at-end: + - match: $ + pop: true + - match: \\\n + scope: punctuation.separator.continuation.line.shell + push: + - match: ^ + pop: true + + prototype: + - match: (?<=^|\s)\# + scope: punctuation.definition.comment.begin.shell + push: + - meta_scope: comment.line.number-sign.shell + - match: $ + pop: true + - match: \\(\s+)\n + captures: + 1: invalid.illegal.extraneous-spaces-after-line-continuation.shell + - match: \\. + scope: constant.character.escape.shell + + main: + - include: funcdef + - include: vardef + - match: '{{is_command}}' + push: cmd + + # NOTE: Contexts with a "-bt" suffix are the "backtick" contexts. They mirror + # the ordinary contexts, except that when a backtick is encountered while in + # a "-bt" context, we pop. + # Normally, we are in a non-bt context. When we encounter a backtick character + # (the ` character), we enter the main-bt context. Popping when encountering + # another ` character then ensures that we don't enter yet another backtick + # context. + # The "expansion" context is the **only** place where this main-bt context is + # used. If you, the reader, knows of a more elegant way to handle backticks, + # don't hesitate to change it. + main-bt: + - include: funcdef-bt + - include: vardef-bt + - match: '{{is_command}}' + push: cmd-bt + + control: + - match: \b(if)\b(?:\s*(!))? + captures: + 1: keyword.control.if.begin.shell + 2: keyword.operator.logical.shell + - match: \bthen\b + scope: keyword.control.if.then.shell + pop: true + - match: \b(elif)\b(?:\s*(!))? + captures: + 1: keyword.control.if.elif.shell + 2: keyword.operator.logical.shell + - match: \bfi\b + scope: keyword.control.if.end.shell + set: [cmd-post, cmd-args] + - match: \belse\b + scope: keyword.control.if.else.shell + pop: true + - match: \bfor\b + scope: keyword.control.for.shell + set: [cmd-post, for-args] + - match: \bdo\b + scope: keyword.control.do.shell + pop: true + - match: \bdone\b + scope: keyword.control.done.shell + set: [cmd-post, cmd-args] + - match: \bwhile\b + scope: keyword.control.while.shell + - match: \buntil\b + scope: keyword.control.until.shell + - match: \bcase\b + scope: keyword.control.case.begin.shell + set: [case-body, case-item, case-preamble] + - match: \bcontinue\b + scope: keyword.control.continue.shell + + case-preamble: + - match: \bin\b + scope: keyword.control.case.in.shell + pop: true + - include: expansion-and-string + + case-item-highlights: + - include: expansion-and-string + - match: \* + scope: variable.language.shell + - match: \| + scope: keyword.operator.logical.shell + - match: \( + scope: punctuation.section.parens.begin.shell + push: case-item-inside + + case-item-inside: + - match: \) + scope: punctuation.section.parens.end.shell + pop: true + - include: case-item-highlights + + case-item: + - match: \) + scope: keyword.control.case.item.shell + pop: true + - include: case-item-highlights + + case-body: + - match: \s*(;;) + captures: + 1: punctuation.terminator.case.shell + set: + - match: \besac\b + scope: keyword.control.case.end.shell + pop: true + - match: \) + scope: keyword.control.case.item.shell + set: case-body + - include: case-item-highlights + - include: main + + # I don't think anybody will write a for-loop inside backticks. Hence no + # for-args-bt context. + for-args: + - match: "" + set: + - meta_scope: meta.group.for.shell + - include: cmd-args-boilerplate + - include: compound + - match: \bin\b + scope: keyword.control.in.shell + + expansion-and-string: + - include: string + - include: expansion + + funcdef: + - match: '{{is_function}}' + captures: + 1: storage.type.function.shell + push: [funcdef-body, funcdef-parens, funcdef-name] + + funcdef-bt: + - match: '{{is_function}}' + captures: + 1: storage.type.function.shell + push: [funcdef-body-bt, funcdef-parens, funcdef-name] + + funcdef-name: + - match: \s* + set: + - meta_content_scope: entity.name.function.shell + - match: (?=\s*[({]) + pop: true + + funcdef-parens: + - match: \( + scope: punctuation.section.parens.begin.shell + push: + - match: \) + scope: punctuation.section.parens.end.shell + pop: true + - match: \{ + scope: punctuation.section.braces.begin.shell + pop: true + + funcdef-body: + - meta_scope: meta.function.shell + - match: \} + scope: punctuation.section.braces.end.shell + pop: true + - include: main + + funcdef-body-bt: + - meta_scope: meta.function.shell + - match: \} + scope: punctuation.section.braces.end.shell + pop: true + - include: main-bt + + vardef: + - match: \s*\b(alias)\b + captures: + 1: support.function.alias.shell + push: + - vardef-export-maybe-more + - vardef-value + - vardef-assign + - vardef-name + - vardef-alias-options + - match: \s*\b(declare)\b + captures: + 1: storage.modifier.shell + push: + - vardef-export-maybe-more + - vardef-value + - vardef-assign + - vardef-name + - vardef-declare-options + - match: \s*\b(export|local|readonly|typeset)\b + captures: + 1: storage.modifier.shell + push: + - vardef-export-maybe-more + - vardef-value + - vardef-assign + - vardef-name + - vardef-eat-whitespace + - match: '{{is_variable}}' + push: + - cmd-or-vardef-junction + - vardef-value + - vardef-assign + - vardef-name + - vardef-eat-whitespace + + vardef-bt: + - match: \s*\b(alias)\b + captures: + 1: support.function.alias.shell + push: + - vardef-export-maybe-more + - vardef-value + - vardef-assign + - vardef-name + - vardef-alias-options + - match: \s*\b(declare)\b + captures: + 1: storage.modifier.shell + push: + - vardef-export-maybe-more + - vardef-value + - vardef-assign + - vardef-name + - vardef-declare-options + - match: ^\s*\b(export|local|readonly|typeset)\b + captures: + 1: storage.modifier.shell + push: + - vardef-export-maybe-more + - vardef-value + - vardef-assign + - vardef-name + - vardef-eat-whitespace + - match: '{{is_variable}}' + push: + - cmd-or-vardef-junction-bt + - vardef-value + - vardef-assign + - vardef-name + - vardef-eat-whitespace + + vardef-export-maybe-more: + - match: (?=\s*#) + pop: true + - include: cmd-args-boilerplate + - match: (?=\S) + set: + - vardef-export-maybe-more + - vardef-value + - vardef-assign + - vardef-name + - vardef-eat-whitespace + + vardef-alias-options: + - match: \s*((-)p) + captures: + 2: punctuation.definition.parameter.shell + 1: variable.parameter.shell + - match: \s* + pop: true + + vardef-declare-options: + - match: \s*((-)[aAfFgilnrtux]+|p) + captures: + 2: punctuation.definition.parameter.shell + 1: variable.parameter.shell + - match: \s* + pop: true + + vardef-eat-whitespace: + - match: (?=\S) + pop: true + + vardef-name: + - match: "" + set: + - meta_scope: variable.other.readwrite.assignment.shell + - match: (?={{varassign}}|\s)|$ + pop: true + - include: array + - match: \s*$ + pop: true + + + vardef-assign: + - match: '{{varassign}}' + scope: keyword.operator.assignment.shell + pop: true + - match: "" + pop: true + + vardef-value: + - match: \( + scope: punctuation.section.parens.begin.shell + set: + - match: \) + scope: punctuation.section.parens.end.shell + pop: true + - match: \[ + scope: punctuation.section.brackets.begin.shell + push: + - match: \] + scope: punctuation.section.brackets.end.shell + set: + - match: = + scope: keyword.operator.assignment.shell + pop: true + - match: "" + pop: true + - include: expansion-and-string + - include: expansion-and-string + - match: "" + set: + - meta_scope: string.unquoted.shell + - include: expansion-and-string + - include: line-continuation-or-pop-at-end + - match: (?=\s|;) + pop: true + + cmd-or-vardef-junction: + - match: '{{is_variable}}' + set: + - cmd-or-vardef-junction + - vardef-value + - vardef-assign + - vardef-name + - vardef-eat-whitespace + - match: "" + set: cmd + + cmd-or-vardef-junction-bt: + - match: '{{is_variable}}' + set: + - cmd-or-vardef-junction-bt + - vardef-value + - vardef-assign + - vardef-name + - vardef-eat-whitespace + - match: "" + set: cmd-bt + + redirection: + - include: redirection-here-string + - include: redirection-here-document + - include: redirection-input + - include: redirection-output + - include: redirection-inout + + redirection-output: + - match: (\d*)(>>!?|>&?|&>|&?>(\||>))(\d*)\s* + captures: + 1: constant.numeric.file-descriptor.shell + 2: keyword.operator.assignment.redirection.shell + 4: constant.numeric.file-descriptor.shell + + redirection-input: + - match: (\d*)(<&?)((-)|(\d+))?\s* + captures: + 1: constant.numeric.file-descriptor.shell + 2: keyword.operator.assignment.redirection.shell + 4: punctuation.terminator.shell + 5: constant.numeric.file-descriptor.shell + + redirection-inout: + - match: (\d*)(<>) + captures: + 1: constant.numeric.file-descriptor.shell + 2: keyword.operator.assignment.redirection.shell + + redirection-here-string: + - match: (\d+)?(<<<)\s + captures: + 1: constant.numeric.file-descriptor.shell + 2: keyword.operator.herestring.shell + + redirection-here-document: + - match: (\d+)?(<<-?)\s*(')?({{identifier}})(')? + captures: + 1: constant.numeric.file-descriptor.shell + 2: keyword.operator.assignment.redirection.shell + 3: punctuation.definition.string.begin.shell + 4: keyword.control.heredoc-token.shell + 5: punctuation.definition.string.end.shell + push: [heredocs-body, heredocs-preamble] + + heredocs-body: + - meta_include_prototype: false + - meta_scope: string.unquoted.heredoc.shell + - match: \\` + scope: constant.character.escape.backtick.shell + - match: ^\4(\s+)\n # the fourth capture from redirection-here-document + captures: + 1: invalid.illegal.no-spaces-allowed-after-heredoc-token.shell + # rather not pop, but sublime throws an error otherwise. + pop: true + - match: ^(\4)$ # the fourth capture from redirection-here-document + captures: + 1: keyword.control.heredoc-token.shell + 2: invalid.illegal.no-spaces-allowed-after-heredoc-token.shell + pop: true + - include: expansion + + heredocs-preamble: + - match: "" + set: + # This enables us to keep parsing on the line where the start token of + # the heredoc is. Once the first line has ended, we enter the body of + # the heredoc, where everything is just an unquoted string. + # One clear_scope for the string.unquoted, and one clear_scope for the + # meta.function-call.arguments. + # The problem with this is that when we also end a function definition + # on the same line (with the "}" token), we cannot do that. + - clear_scopes: 2 + - match: $ + pop: true + - match: \s*(?=\S) + push: [main-with-pop-at-end, cmd-post, cmd-args] + + main-with-pop-at-end: + - include: line-continuation-or-pop-at-end + - include: main + + cmd-args-common: + - match: (?=}) + pop: true + - match: (?=\s+#) + pop: true + - include: redirection + - match: (?=\s*([|;]|&&)) + pop: true + - include: expansion-and-string + - include: line-continuation-or-pop-at-end + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: redirection + - match: (?=[)};&|]) + pop: true + - include: expansion-and-string + - include: line-continuation-or-pop-at-end + + cmd-post: # looks like [main, cmd-post] at this point + - match: "" + set: + - meta_content_scope: meta.post-cmd.shell + - match: '{{reset_semicolon}}' + captures: + 1: keyword.operator.logical.continue.shell + pop: true + - match: '{{reset_or}}' + captures: + 1: keyword.operator.logical.or.shell + pop: true + - match: '{{reset_pipe}}' + captures: + 1: keyword.operator.logical.pipe.shell + pop: true + - match: '{{reset_and}}' + captures: + 1: keyword.operator.logical.and.shell + pop: true + - match: "" + pop: true + + cmd-post-bt: # looks like [main, cmd-post] at this point + - match: "" + set: + - meta_content_scope: meta.post-cmd.shell + - match: '{{reset_semicolon}}' + captures: + 1: keyword.operator.logical.continue.shell + set: cmd-bt + - match: '{{reset_or}}' + captures: + 1: keyword.operator.logical.or.shell + set: cmd-bt + - match: '{{reset_pipe}}' + captures: + 1: keyword.operator.logical.pipe.shell + set: cmd-bt + - match: '{{reset_and}}' + captures: + 1: keyword.operator.logical.and.shell + set: cmd-bt + - match: "" + pop: true + + cmd-args-boilerplate: + - match: (?={{is_end_of_interpolation}}) + pop: true + - include: cmd-args-common + + cmd-args-boilerplate-bt: + - match: (?={{is_end_of_interpolation}}|`) # <-------------- extra backtick + pop: true + - include: cmd-args-common + + cmd-args: + - match: "" + set: + - meta_scope: meta.function-call.arguments.shell + - include: cmd-args-boilerplate + - match: '{{start_of_option}}' + scope: punctuation.definition.parameter.shell + push: + - meta_scope: variable.parameter.shell + - match: (?={{is_end_of_option}}) + pop: true + - include: expansion-and-string + + cmd-args-bt: + - match: "" + set: + - meta_scope: meta.function-call.arguments.shell + - include: cmd-args-boilerplate-bt + - match: '{{start_of_option}}' + scope: punctuation.definition.parameter.shell + push: + - meta_scope: variable.parameter.shell + - match: (?={{is_end_of_option}}|`) # <------------- extra backtick + pop: true + - include: expansion-and-string + + cmd: + - include: cmd-common + - include: scope:commands.builtin.shell.bash#main + - match: \blet\b + scope: support.function.let.bash + push: + - match: $ + pop: true + - include: expression + - match: (\[\[)(?=\s) + captures: + 1: support.function.test.begin.shell + set: [cmd-post, cmd-test-double-brace-args] + - match: (\[)(?=\s) + captures: + 1: support.function.test.begin.shell + set: [cmd-post, cmd-test-brace-args] + - match: (\{)(?=\s) + captures: + 1: punctuation.definition.compound.braces.begin.shell + push: + - match: \} + scope: punctuation.definition.compound.braces.end.shell + set: cmd-post + - include: main + - match: (?=\S) + set: [cmd-post, cmd-args, cmd-name] + + cmd-bt: + - include: cmd-common + - include: scope:commands.builtin.shell.bash#main-bt + - match: \blet\b + scope: support.function.let.bash + push: + - match: $|(?=\`) + pop: true + - include: expression + - match: (\[\[)(?=\s) + captures: + 1: meta.function-call.shell support.function.test.begin.shell + set: [cmd-post, cmd-test-double-brace-args-bt] + - match: (\[)(?=\s) + captures: + 1: meta.function-call.shell support.function.test.begin.shell + set: [cmd-post-bt, cmd-test-brace-args-bt] + - match: (\{)(?=\s) + captures: + 1: punctuation.definition.compound.braces.begin.shell + push: + - match: \} + scope: punctuation.definition.compound.braces.end.shell + set: cmd-post-bt + - include: main-bt + - match: (?=\S) + set: [cmd-post-bt, cmd-args-bt, cmd-name-bt] + + cmd-test-brace-args: + - match: "" + set: + - meta_scope: meta.function-call.arguments.shell + - include: cmd-args-boilerplate + - match: (?<=\s)(\]) + captures: + 1: support.function.test.end.shell + pop: true + - include: expression-test + + cmd-test-brace-args-bt: + - match: "" + set: + - meta_scope: meta.function-call.arguments.shell + - include: cmd-args-boilerplate-bt + - match: (?<=\s)(\]) + captures: + 1: support.function.test.end.shell + pop: true + - include: expression-test + + cmd-test-double-brace-args: + - match: "" + set: + - meta_scope: meta.function-call.arguments.shell + - include: cmd-args-boilerplate + - match: (?<=\s)(\]\]) + captures: + 1: support.function.test.end.shell + pop: true + - include: expression-test + + cmd-test-double-brace-args-bt: + - match: "" + set: + - meta_scope: meta.function-call.arguments.shell + - include: cmd-args-boilerplate-bt + - match: (?<=\s)(\]\]) + captures: + 1: support.function.test.end.shell + pop: true + - include: expression-test + + cmd-qualified-path: + - meta_scope: meta.function-call.shell + - match: \./ + scope: punctuation.definition.call.shell + - match: /|\.\. + scope: punctuation.separator.path.shell + - include: cmd-args-common + # - match: '{{is_path_component}}' + # set: cmd-qualified-path + - match: "" + pop: true + + cmd-name: + - match: "" + set: + - meta_scope: meta.function-call.shell variable.function.shell + - match: (?={{is_end_of_interpolation}}) + pop: true + - include: cmd-args-common + - match: (?={{is_start_of_arguments}}) + pop: true + + cmd-name-bt: + - match: "" + set: + - meta_scope: meta.function-call.shell variable.function.shell + - match: (?={{is_end_of_interpolation}}|`) # <---------- extra backtick + pop: true + - include: cmd-args-common + - match: (?={{is_start_of_arguments}}) + pop: true + + cmd-common: + - include: control + - include: compound + - match: (?=\)|}) + pop: true + - include: line-continuation-or-pop-at-end + + compound: + - match: \(\((?=.+\)\)) + scope: punctuation.definition.expression.begin.shell + push: + - match: \)\) + scope: punctuation.definition.expression.end.shell + pop: true + - include: expression + - match: \( + scope: punctuation.definition.compound.begin.shell + push: + - match: \) + scope: punctuation.definition.compound.end.shell + set: [cmd-post, cmd-args] + - include: main + + expansion: + - match: \$ + scope: keyword.other.expansion.shell + push: + - meta_scope: variable.other.readwrite.shell + - match: _(?!\w) + scope: variable.language.shell + - match: '[#@!~*?]' + scope: variable.language.shell + - match: \(\((?=.+\)\)) + scope: punctuation.section.parens.begin.shell + push: + - match: \)\) + scope: punctuation.section.parens.end.shell + pop: true + - include: expression + - match: \( + scope: punctuation.section.parens.begin.shell + push: + - match: \s*(\)) + captures: + 1: punctuation.section.parens.end.shell + pop: true + - match: "" + push: cmd + - match: \{ + scope: punctuation.section.brackets.begin.shell + set: + - meta_content_scope: variable.other.readwrite.shell + - match: \! + scope: keyword.operator.indirection.shell + set: expansion-bracket-post-first-character + - match: \# + scope: keyword.operator.arithmetic.shell + set: expansion-bracket-post-first-character + - match: "" + set: expansion-bracket-post-first-character + - match: \d+ + scope: variable.parameter.shell + pop: true + - match: \w+ + pop: true + - match: "" + pop: true + - match: \` + scope: punctuation.section.group.begin.shell + push: + - match: \` + scope: punctuation.section.group.end.shell + pop: true + - include: main-bt # all those *-bt contexts just for this!!!! + + expansion-bracket-common: + - meta_content_scope: variable.other.readwrite.shell + - match: \} + scope: + variable.other.readwrite.shell + punctuation.section.brackets.end.shell + pop: true + - include: array + - include: expansion-and-string + + array: + - match: \[ + scope: punctuation.section.braces.begin.shell + push: + - match: \] + scope: punctuation.section.braces.end.shell + pop: true + - match: '[*@]' + scope: variable.language.array.shell + - include: expression + + expansion-bracket-post-first-character: + - meta_scope: variable.other.readwrite.shell + - include: expansion-bracket-common + - match: / + scope: keyword.operator.substitution.shell + set: + - match: / + scope: punctuation.definition.keyword.shell + set: expansion-bracket-pattern + - match: "" + set: expansion-bracket-pattern + - match: \:?[-+=?] + scope: keyword.operator.assignment.shell + set: expansion-bracket-common + - match: ":" + scope: punctuation.accessor.colon.shell + set: + - include: expansion-bracket-common + - match: ":" + scope: punctuation.accessor.colon.shell + set: + - include: expansion-bracket-common + - match: \#(?=}) + - match: \#\#?|%%?|\^\^?|,,? + scope: keyword.operator.expansion.shell + set: expansion-bracket-common + - include: expansion + - match: \[ + scope: punctuation.section.sequence.begin.shell + push: + - match: \] + scope: punctuation.section.sequence.end.shell + pop: true + - match: '[*@](?=})' + scope: keyword.operator.expansion.shell + + expansion-bracket-pattern: + - include: expansion-bracket-common + - match: / + scope: keyword.operator.substitution.shell + set: expansion-bracket-common + + expression: + - include: expansion-and-string + - match: '[!~]' + scope: keyword.operator.logical.shell + - match: \b\d+ + scope: constant.numeric.integer.shell + - match: \+\+?|\-\-?|\*\*?|% + scope: keyword.operator.arithmetic.shell + - match: <[=<]?|>[=>]?|[=!]=|&&|\:|\|\| + scope: keyword.operator.logical.shell + - match: '[&|^]' + scope: keyword.operator.bitwise.shell + - match: '[*/%+\-&^|]?=|<<=|>>=' + scope: keyword.operator.assignment.shell + - match: \, + scope: punctuation.separator.shell + - match: ; + scope: punctuation.separator.shell + + expression-test: + - include: expansion-and-string + - match: ((-)[aobcdefghknoprstuvwxzGLNORS])(?=\s) + captures: + 2: punctuation.definition.parameter.shell + 1: variable.parameter.shell + - match: ((-)(?:ef|nt|ot|eq|ne|lt|le|gt|ge))(?=\s) + captures: + 2: punctuation.definition.parameter.shell + 1: variable.parameter.shell + - match: ==?|!=?|<|>| + scope: keyword.operator.logical.shell + + string: + - include: string-quoted-double + - include: string-quoted-single + - include: string-ansi-c + + # nothing is escaped in a singly-quoted string! + string-quoted-single: + - match: \' + scope: punctuation.definition.string.begin.shell + push: + - meta_include_prototype: false + - meta_scope: string.quoted.single.shell + scope: constant.character.escape.shell.zsh + - match: \' + scope: punctuation.definition.string.end.shell + pop: true + + string-quoted-double: + - match: \" + scope: punctuation.definition.string.begin.shell + push: + - meta_include_prototype: false + - meta_scope: string.quoted.double.shell + - match: \" + scope: punctuation.definition.string.end.shell + pop: true + - include: string-quoted-double-escape-character + - include: expansion + + string-quoted-double-escape-character: + - match: \\[$`"\\] + scope: constant.character.escape.shell + - match: \\\n + scope: constant.character.escape.shell + push: + - meta_include_prototype: false + - match: (?=\S) + pop: true + + # [Bash] 3.1.2.4 + string-ansi-c: + - match: \$' + scope: punctuation.definition.string.begin.shell + push: + - meta_include_prototype: false + # see 3.1.2.4 on why we choose string.quoted.single here + - meta_scope: string.quoted.single.shell + - match: "'" + scope: punctuation.definition.string.end.shell + pop: true + - include: string-quoted-double-escape-character + - match: \\([abfnrtv'"?]|[0-8]{1,3}|x\h{1,8}|c[a-z]) + scope: constant.character.escape.shell diff --git a/ShellScript/commands-builtin-shell-bash.sublime-syntax b/ShellScript/commands-builtin-shell-bash.sublime-syntax new file mode 100644 index 0000000000..9f5310bcb5 --- /dev/null +++ b/ShellScript/commands-builtin-shell-bash.sublime-syntax @@ -0,0 +1,1000 @@ +%YAML 1.2 +--- +# Automatically generated file -- do not edit! +contexts: + cmd-args-bind: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-bind-base + cmd-args-bind-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[mqurfx]|[lpsvPSVX]+)(?=\s|;|$|`|\)) + cmd-args-bind-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-bind-base + cmd-args-builtin: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-builtin-base + cmd-args-builtin-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + cmd-args-builtin-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-builtin-base + cmd-args-caller: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-caller-base + cmd-args-caller-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + cmd-args-caller-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-caller-base + cmd-args-cd: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-cd-base + cmd-args-cd-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[LPe@])(?=\s|;|$|`|\)) + cmd-args-cd-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-cd-base + cmd-args-colon: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + cmd-args-colon-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + cmd-args-command: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-command-base + cmd-args-command-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[pVv]+)(?=\s|;|$|`|\)) + cmd-args-command-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-command-base + cmd-args-dot: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + cmd-args-dot-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + cmd-args-echo: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-echo-base + cmd-args-echo-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[neE]+)(?=\s|;|$|`|\)) + cmd-args-echo-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-echo-base + cmd-args-enable: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-enable-base + cmd-args-enable-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[af]|[dnps]+)(?=\s|;|$|`|\)) + cmd-args-enable-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-enable-base + cmd-args-eval: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + cmd-args-eval-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + cmd-args-exec: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-exec-base + cmd-args-exec-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[a]|[cl]+)(?=\s|;|$|`|\)) + cmd-args-exec-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-exec-base + cmd-args-exit: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + cmd-args-exit-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + cmd-args-getopts: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-getopts-base + cmd-args-getopts-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + cmd-args-getopts-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-getopts-base + cmd-args-hash: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-hash-base + cmd-args-hash-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[rpl]|[dt]+)(?=\s|;|$|`|\)) + cmd-args-hash-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-hash-base + cmd-args-help: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-help-base + cmd-args-help-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[dms]+)(?=\s|;|$|`|\)) + cmd-args-help-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-help-base + cmd-args-logout: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-logout-base + cmd-args-logout-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + cmd-args-logout-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-logout-base + cmd-args-mapfile: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-mapfile-base + cmd-args-mapfile-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[dnOstuCc])(?=\s|;|$|`|\)) + cmd-args-mapfile-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-mapfile-base + cmd-args-printf: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-printf-base + cmd-args-printf-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[v])(?=\s|;|$|`|\)) + cmd-args-printf-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-printf-base + cmd-args-pwd: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-pwd-base + cmd-args-pwd-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[LP]+)(?=\s|;|$|`|\)) + cmd-args-pwd-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-pwd-base + cmd-args-read: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-read-base + cmd-args-read-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[adeinNprstu]|[ers]+)(?=\s|;|$|`|\)) + cmd-args-read-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-read-base + cmd-args-readarray: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-readarray-base + cmd-args-readarray-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[adeinNprstu]|[ers]+)(?=\s|;|$|`|\)) + cmd-args-readarray-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-readarray-base + cmd-args-return: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + cmd-args-return-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + cmd-args-set: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-set-base + cmd-args-set-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((\-|\+)(?:[o]|[abefhkmnptuvxBCEHPT]+))(?=\s|;|$|`|\)) + cmd-args-set-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-set-base + cmd-args-shift: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + cmd-args-shift-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + cmd-args-shopt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-shopt-base + cmd-args-shopt-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[o]|[pqsu]+)(?=\s|;|$|`|\)) + cmd-args-shopt-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-shopt-base + cmd-args-source: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-source-base + cmd-args-source-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + cmd-args-source-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-source-base + cmd-args-times: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-times-base + cmd-args-times-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + cmd-args-times-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-times-base + cmd-args-trap: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-trap-base + cmd-args-trap-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[lp]+)(?=\s|;|$|`|\)) + cmd-args-trap-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-trap-base + cmd-args-type: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-type-base + cmd-args-type-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[afptP]+)(?=\s|;|$|`|\)) + cmd-args-type-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-type-base + cmd-args-ulimit: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-ulimit-base + cmd-args-ulimit-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[HSabcdefiklmnpqrstuvxPT]+)(?=\s|;|$|`|\)) + cmd-args-ulimit-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-ulimit-base + cmd-args-umask: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-umask-base + cmd-args-umask-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[pS])(?=\s|;|$|`|\)) + cmd-args-umask-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-umask-base + cmd-args-unalias: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-unalias-base + cmd-args-unalias-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[a])(?=\s|;|$|`|\)) + cmd-args-unalias-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-unalias-base + cmd-args-unset: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate + - include: cmd-args-unset-base + cmd-args-unset-base: + - match: (?<=\s)--(?=\s|$) + scope: keyword.operator.end-of-options.shell + set: + - meta_content_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#expansion-and-string + - include: scope:source.shell.bash#line-continuation-or-pop-at-end + - captures: + 1: variable.parameter.shell + 2: punctuation.definition.parameter.shell + match: (?<=\s|^)((-)[fnv]+)(?=\s|;|$|`|\)) + cmd-args-unset-bt: + - match: '' + set: + - meta_scope: meta.function-call.arguments.shell + - include: scope:source.shell.bash#cmd-args-boilerplate-bt + - include: cmd-args-unset-base + main: + - match: '{{boundary_begin}}set{{boundary_end}}' + scope: meta.function-call.shell support.function.set.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-set + - match: '{{boundary_begin}}help{{boundary_end}}' + scope: meta.function-call.shell support.function.help.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-help + - match: '{{boundary_begin}}mapfile{{boundary_end}}' + scope: meta.function-call.shell support.function.mapfile.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-mapfile + - match: '{{boundary_begin}}getopts{{boundary_end}}' + scope: meta.function-call.shell support.function.getopts.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-getopts + - match: '{{boundary_begin}}cd{{boundary_end}}' + scope: meta.function-call.shell support.function.cd.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-cd + - match: '{{boundary_begin}}:{{boundary_end}}' + scope: meta.function-call.shell support.function.colon.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-colon + - match: '{{boundary_begin}}printf{{boundary_end}}' + scope: meta.function-call.shell support.function.printf.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-printf + - match: '{{boundary_begin}}hash{{boundary_end}}' + scope: meta.function-call.shell support.function.hash.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-hash + - match: '{{boundary_begin}}ulimit{{boundary_end}}' + scope: meta.function-call.shell support.function.ulimit.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-ulimit + - match: '{{boundary_begin}}umask{{boundary_end}}' + scope: meta.function-call.shell support.function.umask.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-umask + - match: '{{boundary_begin}}source{{boundary_end}}' + scope: meta.function-call.shell support.function.source.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-source + - match: '{{boundary_begin}}builtin{{boundary_end}}' + scope: meta.function-call.shell support.function.builtin.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-builtin + - match: '{{boundary_begin}}exit{{boundary_end}}' + scope: meta.function-call.shell support.function.exit.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-exit + - match: '{{boundary_begin}}type{{boundary_end}}' + scope: meta.function-call.shell support.function.type.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-type + - match: '{{boundary_begin}}enable{{boundary_end}}' + scope: meta.function-call.shell support.function.enable.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-enable + - match: '{{boundary_begin}}return{{boundary_end}}' + scope: meta.function-call.shell support.function.return.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-return + - match: '{{boundary_begin}}exec{{boundary_end}}' + scope: meta.function-call.shell support.function.exec.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-exec + - match: '{{boundary_begin}}read{{boundary_end}}' + scope: meta.function-call.shell support.function.read.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-read + - match: '{{boundary_begin}}pwd{{boundary_end}}' + scope: meta.function-call.shell support.function.pwd.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-pwd + - match: '{{boundary_begin}}logout{{boundary_end}}' + scope: meta.function-call.shell support.function.logout.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-logout + - match: '{{boundary_begin}}eval{{boundary_end}}' + scope: meta.function-call.shell support.function.eval.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-eval + - match: '{{boundary_begin}}echo{{boundary_end}}' + scope: meta.function-call.shell support.function.echo.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-echo + - match: '{{boundary_begin}}\.{{boundary_end}}' + scope: meta.function-call.shell support.function.dot.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-dot + - match: '{{boundary_begin}}bind{{boundary_end}}' + scope: meta.function-call.shell support.function.bind.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-bind + - match: '{{boundary_begin}}caller{{boundary_end}}' + scope: meta.function-call.shell support.function.caller.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-caller + - match: '{{boundary_begin}}times{{boundary_end}}' + scope: meta.function-call.shell support.function.times.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-times + - match: '{{boundary_begin}}unalias{{boundary_end}}' + scope: meta.function-call.shell support.function.unalias.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-unalias + - match: '{{boundary_begin}}command{{boundary_end}}' + scope: meta.function-call.shell support.function.command.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-command + - match: '{{boundary_begin}}trap{{boundary_end}}' + scope: meta.function-call.shell support.function.trap.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-trap + - match: '{{boundary_begin}}shift{{boundary_end}}' + scope: meta.function-call.shell support.function.shift.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-shift + - match: '{{boundary_begin}}readarray{{boundary_end}}' + scope: meta.function-call.shell support.function.readarray.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-readarray + - match: '{{boundary_begin}}shopt{{boundary_end}}' + scope: meta.function-call.shell support.function.shopt.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-shopt + - match: '{{boundary_begin}}unset{{boundary_end}}' + scope: meta.function-call.shell support.function.unset.shell + set: + - scope:source.shell.bash#cmd-post + - cmd-args-unset + main-bt: + - match: '{{boundary_begin}}set{{boundary_end}}' + scope: meta.function-call.shell support.function.set.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-set-bt + - match: '{{boundary_begin}}help{{boundary_end}}' + scope: meta.function-call.shell support.function.help.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-help-bt + - match: '{{boundary_begin}}mapfile{{boundary_end}}' + scope: meta.function-call.shell support.function.mapfile.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-mapfile-bt + - match: '{{boundary_begin}}getopts{{boundary_end}}' + scope: meta.function-call.shell support.function.getopts.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-getopts-bt + - match: '{{boundary_begin}}cd{{boundary_end}}' + scope: meta.function-call.shell support.function.cd.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-cd-bt + - match: '{{boundary_begin}}:{{boundary_end}}' + scope: meta.function-call.shell support.function.colon.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-colon-bt + - match: '{{boundary_begin}}printf{{boundary_end}}' + scope: meta.function-call.shell support.function.printf.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-printf-bt + - match: '{{boundary_begin}}hash{{boundary_end}}' + scope: meta.function-call.shell support.function.hash.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-hash-bt + - match: '{{boundary_begin}}ulimit{{boundary_end}}' + scope: meta.function-call.shell support.function.ulimit.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-ulimit-bt + - match: '{{boundary_begin}}umask{{boundary_end}}' + scope: meta.function-call.shell support.function.umask.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-umask-bt + - match: '{{boundary_begin}}source{{boundary_end}}' + scope: meta.function-call.shell support.function.source.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-source-bt + - match: '{{boundary_begin}}builtin{{boundary_end}}' + scope: meta.function-call.shell support.function.builtin.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-builtin-bt + - match: '{{boundary_begin}}exit{{boundary_end}}' + scope: meta.function-call.shell support.function.exit.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-exit-bt + - match: '{{boundary_begin}}type{{boundary_end}}' + scope: meta.function-call.shell support.function.type.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-type-bt + - match: '{{boundary_begin}}enable{{boundary_end}}' + scope: meta.function-call.shell support.function.enable.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-enable-bt + - match: '{{boundary_begin}}return{{boundary_end}}' + scope: meta.function-call.shell support.function.return.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-return-bt + - match: '{{boundary_begin}}exec{{boundary_end}}' + scope: meta.function-call.shell support.function.exec.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-exec-bt + - match: '{{boundary_begin}}read{{boundary_end}}' + scope: meta.function-call.shell support.function.read.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-read-bt + - match: '{{boundary_begin}}pwd{{boundary_end}}' + scope: meta.function-call.shell support.function.pwd.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-pwd-bt + - match: '{{boundary_begin}}logout{{boundary_end}}' + scope: meta.function-call.shell support.function.logout.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-logout-bt + - match: '{{boundary_begin}}eval{{boundary_end}}' + scope: meta.function-call.shell support.function.eval.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-eval-bt + - match: '{{boundary_begin}}echo{{boundary_end}}' + scope: meta.function-call.shell support.function.echo.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-echo-bt + - match: '{{boundary_begin}}\.{{boundary_end}}' + scope: meta.function-call.shell support.function.dot.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-dot-bt + - match: '{{boundary_begin}}bind{{boundary_end}}' + scope: meta.function-call.shell support.function.bind.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-bind-bt + - match: '{{boundary_begin}}caller{{boundary_end}}' + scope: meta.function-call.shell support.function.caller.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-caller-bt + - match: '{{boundary_begin}}times{{boundary_end}}' + scope: meta.function-call.shell support.function.times.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-times-bt + - match: '{{boundary_begin}}unalias{{boundary_end}}' + scope: meta.function-call.shell support.function.unalias.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-unalias-bt + - match: '{{boundary_begin}}command{{boundary_end}}' + scope: meta.function-call.shell support.function.command.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-command-bt + - match: '{{boundary_begin}}trap{{boundary_end}}' + scope: meta.function-call.shell support.function.trap.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-trap-bt + - match: '{{boundary_begin}}shift{{boundary_end}}' + scope: meta.function-call.shell support.function.shift.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-shift-bt + - match: '{{boundary_begin}}readarray{{boundary_end}}' + scope: meta.function-call.shell support.function.readarray.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-readarray-bt + - match: '{{boundary_begin}}shopt{{boundary_end}}' + scope: meta.function-call.shell support.function.shopt.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-shopt-bt + - match: '{{boundary_begin}}unset{{boundary_end}}' + scope: meta.function-call.shell support.function.unset.shell + set: + - scope:source.shell.bash#cmd-post-bt + - cmd-args-unset-bt + prototype: + - include: scope:source.shell.bash#prototype +hidden: true +scope: commands.builtin.shell.bash +variables: + boundary_begin: '' + boundary_end: (?=\s|;|$) diff --git a/ShellScript/commands-builtin-shell-bash.yml b/ShellScript/commands-builtin-shell-bash.yml new file mode 100644 index 0000000000..0f2a74743c --- /dev/null +++ b/ShellScript/commands-builtin-shell-bash.yml @@ -0,0 +1,127 @@ +%YAML 1.2 +--- #--------------------------------------------------------------------------- + +bind: + short-options: mqurfx + short-options-compact: lpsvPSVX + +builtin: + ~ + +caller: + ~ + +colon: + match: ":" + allow-end-of-options-token: false + scope: support.function.colon.shell + +command: + short-options-compact: pVv + +cd: + short-options: LPe@ + +dot: + match: "\\." + allow-end-of-options-token: false + scope: support.function.dot.shell + +enable: + short-options: af + short-options-compact: dnps + +help: + short-options-compact: dms + +logout: + ~ + +mapfile: + short-options: dnOstuCc + +printf: + short-options: v + +read: + short-options-compact: ers + short-options: adeinNprstu + +readarray: + short-options-compact: ers + short-options: adeinNprstu + +source: + allow-end-of-options-token: false + scope: support.function.dot.shell + +type: + short-options-compact: afptP + +ulimit: + short-options-compact: HSabcdefiklmnpqrstuvxPT + +unalias: + short-options: a + +eval: + allow-end-of-options-token: false + +exec: + short-options-compact: cl + short-options: a + +exit: + allow-end-of-options-token: false + +# "export" is handled as storage.modifier in the syntax def, don't put it here! +# export, readonly, declare, local, typeset + +getopts: + ~ + +hash: + short-options: rpl + short-options-compact: dt + +pwd: + short-options-compact: LP + +# "readonly" is handled as storage.modifier in the syntax def, don't put it here! + +return: + allow-end-of-options-token: false + +shift: + allow-end-of-options-token: false + +times: + ~ + +trap: + short-options-compact: lp + +umask: + short-options: pS + +unset: + short-options-compact: fnv + +echo: + short-options-compact: neE + +set: + short-options-compact: abefhkmnptuvxBCEHPT + short-options: o + short-option-prefixes: [\-, \+] + allow-end-of-options-token: true + allow-short-end-of-options-token: true + +source: + ~ + +shopt: + short-options-compact: pqsu + short-options: o + +... diff --git a/ShellScript/test/syntax_test_bash.sh b/ShellScript/test/syntax_test_bash.sh new file mode 100644 index 0000000000..39b7a777bf --- /dev/null +++ b/ShellScript/test/syntax_test_bash.sh @@ -0,0 +1,1160 @@ +# SYNTAX TEST "Packages/ShellScript/bash.sublime-syntax" +# <- comment.line punctuation.definition.comment +#^ comment.line +# ^ comment.line +# ^ - comment.line + +############## +# The basics # +############## + +echo hello, world! +# <- meta.function-call support.function - meta.function-call.arguments +# ^ meta.function-call.arguments +echo hello, \ +# ^^ punctuation.separator.continuation.line +# <- support.function.echo +world! +# TODO: This should be a variable.function above here +# The above is again a command, because the line continuation was prematurely +# ended by the comment. +echo hello, \ +world! +# <- meta.function-call.arguments - variable.function +# The above is not a command, because of the line continuation. +echo hello, \ +# ^^ - punctuation.separator.continuation.line +# (there's an extra space following the backslash, so not a line-continuation) +world! +# <- variable.function +echo This is a smiley :-\) \(I have to escape the parentheses, though!\) +# ^^ constant.character.escape +# ^^ constant.character.escape +# ^^ constant.character.escape +echo the q"uick" f"ox" ju"mp"ed o"ve"r t'he' 'la'zy 'dog' +# ^ string.quoted.double punctuation.definition.string.begin +# ^^^^ string.quoted.double +# ^ string.quoted.double punctuation.definition.string.end +# ^ string.quoted.single punctuation.definition.string.begin +# ^^ string.quoted.single +# ^ string.quoted.single punctuation.definition.string.end +echo 'no\e$capes\in\$ingle\quotes' +# ^ string.quoted.single punctuation.definition.string.begin +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.single +# ^ string.quoted.single punctuation.definition.string.end +# ^ - constant +# ^ - keyword +# ^ - constant +# ^ - constant +# ^ - keyword +# ^ - constant +randomname argument --opt1 --opt2 -x -y &>/dev/null +# <- meta.function-call variable.function - meta.function-call.arguments +#^^^^^^^^^ meta.function-call variable.function - meta.function-call.arguments +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.arguments +# ^^ variable.parameter punctuation +# ^^^^ variable.parameter - punctuation +# ^^ variable.parameter punctuation +# ^^^^ variable.parameter - punctuation +# ^ variable.parameter punctuation +# ^ variable.parameter - punctuation +# ^ variable.parameter punctuation +# ^ variable.parameter - punctuation + +# Test if commands are recognized even in the presence of strings and variable +# expansions +ch=ch +e${ch}"o" hello, world! +# <- meta.function-call variable.function +#^^^^^^^^ meta.function-call variable.function +# ^^^^^^^^^^^^^^ meta.function-call.arguments +#^ variable.other.readwrite keyword.other.expansion +# ^ variable.other.readwrite punctuation.section.brackets.begin +# ^^ variable.other.readwrite +# ^ variable.other.readwrite punctuation.section.brackets.end +# ^ string.quoted.double punctuation.definition.string.begin +# ^ string.quoted.double +# ^ string.quoted.double punctuation.definition.string.end +e=e +${e}'ch'o hello, world! +# <- meta.function-call variable.function +#^^^^^^^^ meta.function-call variable.function +# ^^^^^^^^^^^^^^ meta.function-call.arguments +# <- variable.other.readwrite keyword.other.expansion +#^ variable.other.readwrite punctuation.section.brackets.begin +# ^ variable.other.readwrite +# ^ variable.other.readwrite punctuation.section.brackets.end +# ^ string.quoted.single punctuation.definition.string.begin +# ^^ string.quoted.single +# ^ string.quoted.single punctuation.definition.string.end +echo hello#not-a-comment +# ^^^^^^^^^^^^^^ meta.function-call.arguments - comment.line - variable.function +echo -e "foo" +# ^ variable.parameter punctuation +# ^ variable.parameter +foo --opt1 arg1 +# ^^ variable.parameter punctuation +# ^^^^^^ variable.parameter +foo --opt1 arg1 -- --not-an-option +# ^^ keyword.operator +# ^ - variable.parameter punctuation +set -e +# ^ variable.parameter punctuation +# ^ variable.parameter +set +e +# ^ variable.parameter punctuation +# ^ variable.parameter + +######################## +# Variable assignments # +######################## +x=a +# <- variable.other.readwrite.assignment +#^ keyword.operator.assignment +# ^ string.unquoted +x=a pwd +# <- variable.other.readwrite.assignment +#^ keyword.operator.assignment +# ^^^ meta.function-call support.function +x="a b" pwd +# ^ string.quoted.double punctuation.definition.string.begin +# ^^^ string.quoted.double +# ^ string.quoted.double punctuation.definition.string.end +# ^^^ meta.function-call support.function +x=a y=b pwd +#^ keyword.operator.assignment +# ^ string.unquoted +# ^ keyword.operator.assignment +# ^ string.unquoted +# ^^^ meta.function-call support.function +foo=bar baz=qux +# ^^^ string.unquoted +# ^^^ string.unquoted +x=${foo} y=${baz}"asdf" pwd +#^ keyword.operator.assignment +# ^ string.unquoted variable.other.readwrite keyword.other.expansion +# ^ string.unquoted variable.other.readwrite punctuation.section.brackets.begin +# ^^^ string.unquoted variable.other.readwrite +# ^ string.unquoted variable.other.readwrite punctuation.section.brackets.end +# ^ keyword.operator.assignment +# ^ string.unquoted variable.other.readwrite keyword.other.expansion +# ^ string.unquoted variable.other.readwrite punctuation.section.brackets.begin +# ^^^ string.unquoted variable.other.readwrite +# ^ string.unquoted variable.other.readwrite punctuation.section.brackets.end +# ^ string.unquoted string.quoted.double punctuation.definition.string.begin +# ^^^^ string.unquoted string.quoted.double +# ^ string.unquoted string.quoted.double punctuation.definition.string.end +# ^^^ meta.function-call support.function + +# Spaces following an assignment token means an empty string value! +x= pwd +# <- variable.other.readwrite.assignment +#^ keyword.operator.assignment +# ^^^ meta.function-call support.function + +BOWL=$(($(cat food.txt | wc -l) + 5)) +# ^ keyword.operator.assignment +# ^ keyword.other +# ^^ punctuation +# ^ keyword.other +# ^^^ variable.function +# ^^^^^^^^ - variable.function +# ^ - meta.function-call +# ^ keyword.operator +# ^ - meta.function-call +# ^^ meta.function-call variable.function +# ^ punctuation +# ^ keyword.operator +# ^ constant.numeric +# ^^ punctuation + +############# +# Variables # +############# + +: $_ + #^ variable.language + +: $__ + #^ variable.other + +: $var_0 + # ^ variable.other + +: $_var0 + #^ variable.other + +: $_0var_ + #^ variable.other + +subdir/./myscript.sh --option arg1 arg2 -x + +${foo}/${bar}/${baz} +# ^^^ variable.function variable.other +# ^^^ variable.function variable.other +# ^^^ variable.function variable.other + +declare foo # 'foo' is a variable name +declare -A foo bar # 'foo' and 'bar' are variable names + +export foo # 'foo' is a variable name +# <- storage.modifier +# ^^^ variable.other.readwrite.assignment +export foo bar # 'foo' and 'bar' are variable names +# <- storage.modifier +# ^^^ variable.other.readwrite.assignment +# ^ - variable +# ^^^ variable.other.readwrite.assignment +export foo='bar' # 'foo' is a variable name +# <- storage.modifier +# ^^^ variable.other.readwrite.assignment +# ^ keyword.operator.assignment +# ^ string.unquoted string.quoted.single punctuation.definition.string.begin +local foo bar # 'foo' and 'bar' are variable names +# <- storage.modifier +# ^ - variable +# ^^^ variable.other.readwrite.assignment +# ^ - variable +# ^^^ variable.other.readwrite.assignment +local foo bar='baz' # 'foo' and 'bar' are variable names +# <- storage.modifier +# ^ - variable +# ^^^ variable.other.readwrite.assignment +# ^ - variable +# ^^^ variable.other.readwrite.assignment +# ^ keyword.operator.assignment +# ^ string.unquoted string.quoted.single punctuation.definition.string.begin +readonly foo # 'foo' is a variable name +# <- storage.modifier +# ^ - variable +# ^^^ variable.other.readwrite.assignment +typeset foo # 'foo' is a variable name +# <- storage.modifier +# ^ - variable +# ^^^ variable.other.readwrite.assignment +unset foo bar # 'foo' and 'bar' are variable names +# <- support.function +# ^ - variable + +if [[ -z "$PLATFORM" ]]; then PLATFORM=docker; fi +# ^ variable.other.readwrite.assignment +# ^ keyword.operator.assignment +# ^ string.unquoted + +asdf foo && FOO=some-value pwd +# <- meta.function-call variable.function +# ^^ keyword.operator.logical.and +# ^^^ variable.other.readwrite.assignment +# ^ keyword.operator.assignment +# ^^^^^^^^^^ string.unquoted +# ^^^ meta.function-call support.function.pwd + +(cd Layer1-linux && PLATFORM=${PLATFORM} ./build ) && +# <- punctuation.definition.compound.begin +# ^ punctuation.definition.compound.end +# ^ variable.other.readwrite.assignment +# ^ keyword.operator.assignment +# ^ string.unquoted +# ^ variable.function +(cd Layer2-nodejs && PLATFORM=${PLATFORM} ./build ) && +# ^ variable.other.readwrite.assignment +# ^ keyword.operator.assignment +# ^ string.unquoted +# ^ variable.function +(cd Layer3-base && PLATFORM=${PLATFORM} ./build ) && +# ^ variable.other.readwrite.assignment +# ^ keyword.operator.assignment +# ^ string.unquoted +# ^ variable.function +(cd Layer4-custom && PLATFORM=${PLATFORM} name=${NOSN} ./build ) || err $? +# ^ variable.other.readwrite.assignment +# ^ keyword.operator.assignment +# ^ string.unquoted +# ^ variable.other.readwrite.assignment +# ^ keyword.operator.assignment +# ^ string.unquoted +# ^ variable.function + +#################################################### +# Strings and interpolation in parameter expansion # +#################################################### + +: ${foo:-bar} + # <- keyword + # ^^ keyword + # ^ punctuation + +: ${foo:='bar'} + # <- keyword + # ^^ keyword + # ^ punctuation + # ^^^^^ string.quoted + # ^ punctuation + # ^ punctuation + +: ${foo//bar/baz} + # <- keyword + # ^ keyword + # ^ punctuation + # ^ keyword + # ^ punctuation + +: ${foo:=`bar`} + # <- keyword + # ^^ keyword + # ^ punctuation + # ^ punctuation + # ^ punctuation + +: ${foo:=$( bar )} + # <- keyword + # ^^ keyword + # ^ keyword + # ^ punctuation + # ^ punctuation + # ^ punctuation + +: ${foo:=$(( 1 + 1 ))} + # <- keyword + # ^^ keyword + # ^ keyword + # ^^ punctuation + # ^ constant.numeric + # ^ keyword.operator + # ^ constant.numeric + # ^^ punctuation + # ^ punctuation + +: ${foo:=$bar} + # <- keyword + # ^^ keyword + # ^ keyword.other + # ^^^ variable.other + # ^ punctuation + +: ${foo:="$bar"} + # <- keyword + # ^^ keyword + # ^ punctuation + # ^ keyword.other + # ^^^^ variable.other + # ^ punctuation + # ^ punctuation + +: ${foo//\}/foo} +# ^ keyword.other +# ^ punctuation +# ^ keyword +# ^ punctuation +# ^^ constant.character.escape +# ^ keyword +# ^ punctuation + +: ${foo//%/} +# ^ - keyword +: ${foo//#/} +# ^ - keyword +: ${foo//!/} +# ^ - keyword +: ${foo//:/} +# ^ - keyword +: ${foo//@/} +# ^ - keyword + +: ${foo#} +# ^ - keyword +: ${foo!} +# ^ - keyword +: ${!foo} +# ^ keyword +: ${#foo} +# ^ keyword + +: ${foo//a\/b/c/d} +# ^ keyword +# ^ punctuation +# ^^ constant.character.escape +# ^ keyword +# ^ - keyword + +################################# +# Braces in parameter expansion # +################################# + +: ${foo//foo\}foo\/foo/foo} + # <- keyword.other + # ^ keyword + # ^ punctuation + # ^^ constant.character.escape + # ^^ constant.character.escape + # ^ keyword + # ^ punctuation + +: ${foo:="${bar} baz"} + # <- keyword.other + # ^^ keyword + # ^ punctuation + # ^ punctuation.definition.string.end + # ^ punctuation + +# Sublime bug fix: " +# ^ comment.line.number-sign + +${!varprefix*} +# <- keyword.other +# ^ keyword.operator +# ^ keyword.operator +# ^ punctuation +# ^^^^^^^^^^^^ variable.function + +${!varprefix@} +# <- keyword.other +# ^ keyword.operator +# ^ keyword.operator +# ^ punctuation + +${var#Pattern} +# <- keyword.other +# ^ keyword.operator +# ^ punctuation + +${var##Pattern} +# <- keyword.other +# ^^ keyword.operator +# ^ punctuation + +${var###Pattern} +# <- keyword.other +# ^^ keyword.operator +# ^ - keyword.operator +# ^ punctuation + +${var%Pattern} +# <- keyword.other +# ^ keyword.operator +# ^ punctuation + +${var%%Pattern} +# <- keyword.other +# ^^ keyword.operator +# ^ punctuation + +${var%%%Pattern} +# <- keyword.other +# ^^ keyword.operator +# ^ - keyword.operator +# ^ punctuation + + +#################################################################### +# Parameter-expansion operators # +# cf. http://www.tldp.org/LDP/abs/html/parameter-substitution.html # +#################################################################### + +${foo//%/} +# <- keyword.other +# ^ keyword +# ^ punctuation +# ^ - keyword +# ^ keyword +# ^ punctuation + +${foo//#/} +# <- keyword.other +# ^ keyword.operator +# ^ punctuation +# ^ - keyword +# ^ keyword.operator +# ^ punctuation + +${foo//!/} +# <- keyword.other +# ^ keyword.operator +# ^ punctuation +# ^ - keyword +# ^ keyword.operator +# ^ punctuation + +${foo//:/} +# <- keyword.other +# ^ keyword.operator +# ^ punctuation +# ^ - keyword +# ^ keyword.operator +# ^ punctuation + +${foo//@/} +# <- keyword.other +# ^ keyword.operator +# ^ punctuation +# ^ - keyword +# ^ keyword.operator +# ^ punctuation + +${foo#} # "#" is not a operator here +# <- keyword.other +# ^ - keyword.operator +# ^ punctuation + +${foo!} # "!" is not a operator here +# <- keyword.other +# ^ - keyword.operator +# ^ punctuation + +${var:pos:len} +# <- keyword.other +# ^ punctuation.accessor +# ^ punctuation.accessor +# ^ punctuation + +${foo//a\/b/c/d} +# <- keyword.other +# ^ keyword.operator +# ^ punctuation +# ^^ constant.character.escape +# ^ keyword.operator +# ^ - keyword.operator +# ^ punctuation + +${foo^} +# <- keyword.other +# ^ keyword.operator +# ^ punctuation + +${foo,} +# <- keyword.other +# ^ keyword.operator +# ^ punctuation + +${foo^^} +# <- keyword.other +# ^^ keyword.operator +# ^ punctuation + +${foo,,} +# <- keyword.other +# ^^ keyword.operator +# ^ punctuation + +${foo,,,Pattern} +# <- keyword.other +# ^^ keyword.operator +# ^ - keyword +# ^ punctuation + +${foo,,Pattern} +# <- keyword.other +# ^^ keyword.operator +# ^ punctuation + +${foo-bar} +# <- keyword.other +# ^ keyword.operator +# ^ punctuation + +${foo:-bar} +# <- keyword.other +# ^^ keyword.operator +# ^ punctuation + +${foo+bar} +# <- keyword.other +# ^ keyword.operator +# ^ punctuation + +${foo:+bar} +# <- keyword.other +# ^^ keyword.operator +# ^ punctuation + +: ${foo=bar} + # <- keyword.other + # ^ keyword.operator + # ^ punctuation + +: ${foo:=bar} + # <- keyword.other + # ^^ keyword.operator + # ^ punctuation + +${foo?bar} +# <- keyword.other +# ^ keyword.operator +# ^ punctuation + +${foo:?bar} +# <- keyword.other +# ^^ keyword.operator +# ^ punctuation + +: ${foo}@ +# ^ - variable.language + +: ${foo}# +# ^ - variable.language + +: ${foo:="${bar} baz"} +# <- meta.function-call support.function.colon +# ^ meta.function-call.arguments variable.other.readwrite keyword.other.expansion +# ^^ meta.function-call.arguments variable.other.readwrite keyword.operator.assignment +# ^ meta.function-call.arguments variable.other.readwrite string.quoted.double punctuation.definition.string.begin +# ^ meta.function-call.arguments variable.other.readwrite string.quoted.double variable.other.readwrite punctuation.section.brackets.begin +# ^^^ meta.function-call.arguments variable.other.readwrite string.quoted.double variable.other.readwrite +# ^ meta.function-call.arguments variable.other.readwrite string.quoted.double variable.other.readwrite punctuation.section.brackets.end +# ^^^^ meta.function-call.arguments variable.other.readwrite string.quoted.double +# ^ meta.function-call.arguments variable.other.readwrite string.quoted.double punctuation.definition.string.end +# ^ meta.function-call.arguments variable.other.readwrite punctuation.section.brackets.end + +echo "Url: 'postgres://root:$DB_PASSWORD@$IP:$PORT/db'" +# ^ meta.function-call.arguments string.quoted.double variable.other.readwrite keyword.other.expansion +# ^^^^^^^^^^^ meta.function-call.arguments string.quoted.double variable.other.readwrite +# ^ - variable.language + +################### +# Misc. operators # +################### + +foo='bar' +# ^ keyword.operator + +foo[${j}+10]="`foo`" +# ^ variable.other.readwrite.assignment punctuation.section.braces.begin +# ^ variable.other.readwrite.assignment variable.other.readwrite keyword.other.expansion +# ^ variable.other.readwrite.assignment variable.other.readwrite punctuation.section.brackets.begin +# ^ variable.other.readwrite.assignment variable.other.readwrite +# ^ variable.other.readwrite.assignment variable.other.readwrite punctuation.section.brackets.end +# ^ variable.other.readwrite.assignment keyword.operator.arithmetic +# ^^ variable.other.readwrite.assignment constant.numeric.integer +# ^ variable.other.readwrite.assignment punctuation.section.braces.end +# ^ keyword.operator + +foo+=" baz" +# ^^ keyword.operator + +export foo='bar' +# <- storage.modifier +# ^ keyword.operator + +unset -f -n -v foo +# <- support.function +# ^ punctuation +# ^ variable +# ^ punctuation +# ^ variable +# ^ punctuation +# ^ variable + +foo=`let 5+5` +# ^ punctuation.section.group.begin +# ^ constant.numeric.integer +# ^ punctuation.section.group.end +foo=`some-command --long1` +# ^ punctuation.section.group.begin +# ^^^^^^^^^^^^ meta.function-call variable.function +# ^^ meta.function-call.arguments variable.parameter punctuation.definition.parameter +# ^^^^^ meta.function-call.arguments variable.parameter +# ^ punctuation.section.group.end +foo=`some-command -x` +# ^ punctuation.section.group.begin +# ^^^^^^^^^^^^ meta.function-call variable.function +# ^ meta.function-call.arguments variable.parameter punctuation.definition.parameter +# ^ meta.function-call.arguments variable.parameter +# ^ punctuation.section.group.end + +foo=`echo -e` +# ^ punctuation.section.group.begin +# ^^^^ meta.function-call support.function.echo +# ^ meta.function-call.arguments punctuation.definition.parameter +# ^ meta.function-call.arguments variable.parameter +# ^ punctuation.section.group.end + +foo=`cd -L` +# ^ punctuation.section.group.begin +# ^^ meta.function-call support.function.cd +# ^ meta.function-call.arguments punctuation.definition.parameter +# ^ meta.function-call.arguments variable.parameter +# ^ punctuation.section.group.end + +commits=($(git rev-list --reverse --abbrev-commit "$latest".. -- "$prefix")) + +# <- - variable.other.readwrite + +################ +# Control flow # +################ + +declare -a array +array[500]=value +# ^ variable.other.readwrite.assignment punctuation.section.braces.begin +# ^^^ variable.other.readwrite.assignment constant.numeric.integer +# ^ variable.other.readwrite.assignment punctuation.section.braces.end +# ^ keyword.operator.assignment +# ^^^^^ string.unquoted +echo ${array[@]} +# ^ meta.function-call.arguments variable.other.readwrite punctuation.section.braces.begin +# ^ meta.function-call.arguments variable.other.readwrite variable.language.array +# ^ meta.function-call.arguments variable.other.readwrite punctuation.section.braces.end + +array["foo"]=bar +# ^ variable.other.readwrite.assignment punctuation.section.braces.begin +# ^ variable.other.readwrite.assignment string.quoted.double punctuation.definition.string.begin +# ^^^ variable.other.readwrite.assignment string.quoted.double +# ^ variable.other.readwrite.assignment string.quoted.double punctuation.definition.string.end +# ^ variable.other.readwrite.assignment punctuation.section.braces.end +# ^ keyword.operator.assignment +array[foo]=bar +# ^ variable.other.readwrite.assignment punctuation.section.braces.begin +# ^^^ variable.other.readwrite.assignment +# ^ variable.other.readwrite.assignment punctuation.section.braces.end +# ^ keyword.operator.assignment +# ^^^ string.unquoted +array=($one "two" ${three} 'four' $5) +# <- variable.other.readwrite.assignment +# ^ keyword.operator.assignment +# ^ punctuation.section.parens.begin +# ^ variable.other.readwrite keyword.other.expansion +# ^^^ variable.other.readwrite +# ^ string.quoted.double punctuation.definition.string.begin +# ^^^ string.quoted.double +# ^ string.quoted.double punctuation.definition.string.end +# ^ variable.other.readwrite keyword.other.expansion +# ^ variable.other.readwrite punctuation.section.brackets.begin +# ^^^^^ variable.other.readwrite +# ^ variable.other.readwrite punctuation.section.brackets.end +# ^ string.quoted.single punctuation.definition.string.begin +# ^^^^ string.quoted.single +# ^ string.quoted.single punctuation.definition.string.end +# ^ variable.other.readwrite keyword.other.expansion +# ^ variable.other.readwrite variable.parameter +# ^ punctuation.section.parens.end +array=([foo]== ["bar"]='what' [5+10]=qux) +# ^ keyword.operator.assignment +# ^ punctuation.section.parens.begin +# ^ punctuation.section.brackets.begin +# ^ punctuation.section.brackets.end +# ^ keyword.operator.assignment +# ^ - keyword.operator.assignment +# ^ punctuation.section.brackets.begin +# ^ string.quoted.double punctuation.definition.string.begin +# ^ string.quoted.double punctuation.definition.string.end +# ^ punctuation.section.brackets.end +# ^ keyword.operator.assignment +# ^ string.quoted.single punctuation.definition.string.begin +# ^ string.quoted.single punctuation.definition.string.end +# ^ punctuation.section.brackets.begin +# ^ - constant.numeric +# ^ - keyword +# ^^ - constant.numeric +# ^ punctuation.section.brackets.end +# ^ keyword.operator.assignment +# ^ punctuation.section.parens.end +for (( i = 0; i < 10; i++ )); do +# <- keyword.control +# ^^ punctuation.definition.expression.begin +# ^ meta.group.for keyword.operator.assignment +# ^ meta.group.for constant.numeric.integer +# ^ meta.group.for punctuation.separator +# ^ meta.group.for keyword.operator.logical +# ^^ meta.group.for constant.numeric.integer +# ^ meta.group.for punctuation.separator +# ^^ meta.group.for keyword.operator.arithmetic +# ^^ meta.group.for punctuation.definition.expression.end +# ^ keyword.operator.logical.continue +# ^^ keyword.control.do + echo $i + # <- meta.function-call support.function.echo + # ^ meta.function-call.arguments variable.other.readwrite keyword.other.expansion + # ^ meta.function-call.arguments variable.other.readwrite +done +# <- keyword.control + +for i in $(seq 100); do +# <- keyword.control.for +# ^^ meta.group.for keyword.control.in +# ^ meta.group.for variable.other.readwrite keyword.other.expansion +# ^ meta.group.for variable.other.readwrite punctuation.section.parens.begin +# ^^^ meta.group.for variable.other.readwrite meta.function-call variable.function +# ^ meta.group.for variable.other.readwrite punctuation.section.parens.end +# ^ keyword.operator.logical.continue +# ^^ keyword.control.do + : + # <- meta.function-call support.function.colon +done +# <- keyword.control.done + +case "$1" in +# <- keyword.control.case +# ^ string.quoted.double punctuation.definition.string.begin +# ^ string.quoted.double variable.other.readwrite keyword.other.expansion +# ^ string.quoted.double variable.other.readwrite variable.parameter +# ^ string.quoted.double punctuation.definition.string.end +# ^^ keyword.control.case.in +setup ) +# <- - variable.function - support.function - meta.function-call +# ^ keyword.control.case.item +echo Preparing the server... +# <- meta.function-call support.function.echo +# ^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.arguments +;; +# <- punctuation.terminator.case +#^ punctuation.terminator.case +deploy ) +# <- - variable.function - support.function - meta.function-call +# ^ keyword.control.case.item +echo Deploying... +# <- meta.function-call support.function.echo +# ^^^^^^^^^^^^^ meta.function-call.arguments +;; +# <- punctuation.terminator.case +#^ punctuation.terminator.case +* ) +# <- variable.language +# ^ keyword.control.case.item +cat <<'ENDCAT' +# <- meta.function-call variable.function +# ^^ meta.function-call.arguments string.unquoted.heredoc keyword.operator.assignment.redirection +# ^ meta.function-call.arguments string.unquoted.heredoc punctuation.definition.string.begin +# ^^^^^^ meta.function-call.arguments string.unquoted.heredoc keyword.control.heredoc-token +# ^ meta.function-call.arguments string.unquoted.heredoc punctuation.definition.string.end +foo +# <- meta.function-call.arguments string.unquoted.heredoc +ENDCAT +# <- meta.function-call.arguments string.unquoted.heredoc keyword.control.heredoc-token +;; +# <- punctuation.terminator.case +#^ punctuation.terminator.case +esac +# <- keyword.control.case.end + +if [ ! -f q4m-$Q4MVER.tar.gz ]; then + #^ support.function.test.begin + # ^ support.function.test.end + #^ keyword.operator + # ^ variable.parameter punctuation + # ^ variable.parameter + # ^ - keyword.operator + # ^ keyword.operator + : + # <- meta.function-call support.function +fi +# <- keyword.control + +if (ruby extconf.rb && +# ^ punctuation.definition.compound.begin + { make clean || true; } && + # <- punctuation.definition.compound.braces.begin + # ^ punctuation.definition.compound.braces.end + make) 1> build.log 2>&1 + # ^ punctuation.definition.compound.end + # ^ - variable.function +fi + +if [ "$1" != "" -a "$2" != "" ]; then +# <- keyword.control.if.begin +# ^ support.function.test.begin +# ^^ meta.function-call.arguments keyword.operator.logical +# ^ meta.function-call.arguments variable.parameter punctuation.definition.parameter +# ^ meta.function-call.arguments variable.parameter +# ^^ meta.function-call.arguments keyword.operator.logical +# ^ meta.function-call.arguments support.function.test.end +# ^ keyword.operator.logical.continue +# ^^^^ keyword.control.if.then + local DIR=$1 + # <- storage.modifier + # ^^^ variable.other.readwrite.assignment + # ^ keyword.operator.assignment + local TARGET=$2 + # <- storage.modifier + # ^^^^^^ variable.other.readwrite.assignment + # ^ keyword.operator.assignment +elif [ "$1" ]; then +# <- keyword.control.if.elif +# ^^^^ keyword.control.if.then + local DIR=$PWD + # <- storage.modifier + # ^^^ variable.other.readwrite.assignment + # ^ keyword.operator.assignment + local TARGET=$1 + # <- storage.modifier + # ^^^^^^ variable.other.readwrite.assignment + # ^ keyword.operator.assignment +fi +# <- keyword.control.if.end + +case $TERM in + sun-cmd) + # ^ keyword.control.case.item + update_terminal_cwd() { print -Pn "\e]l%~\e\\" };; + # ^ meta.function punctuation.section.braces.end + # ^^ punctuation.terminator.case + *xterm*|rxvt|(dt|k|E)term) + # ^ variable.language + # ^ keyword.operator.logical + # ^ punctuation.section.parens.begin + # ^ keyword.operator.logical + # ^ keyword.operator.logical + # ^ punctuation.section.parens.end + # ^ keyword.control.case.item + update_terminal_cwd() { print -Pn "\e]2;%~\a" };; + # ^ meta.function punctuation.section.braces.end + # ^^ punctuation.terminator.case + *) + # <- variable.language + #^ keyword.control.case.item + update_terminal_cwd() {};; + # ^ meta.function punctuation.section.braces.end + # ^^ punctuation.terminator.case +esac + +if [ "$*" = '*' ] +then remotefilter="cat" +# ^ variable.other.readwrite.assignment +# ^ keyword.operator.assignment +else remotefilter="grep" +# ^ variable.other.readwrite.assignment +# ^ string.unquoted string.quoted.double punctuation.definition.string.begin + for glob in "$@" + do glob=$( + # ^ variable.other.readwrite.assignment + # ^ keyword.operator.assignment + # ^ string.unquoted variable.other.readwrite keyword.other.expansion + # ^ string.unquoted variable.other.readwrite punctuation.section.parens.begin + echo "$glob" | + sed -e 's@\*@[^ ]*@g' -e 's/\?/[^ ]/g' + # <- string.unquoted variable.other.readwrite meta.function-call variable.function + ) + # <- string.unquoted variable.other.readwrite punctuation.section.parens.end + remotefilter="$remotefilter -e '^$glob ' -e ' $glob\$'" + # ^ variable.other.readwrite.assignment + # ^ keyword.operator.assignment + done + # <- keyword.control.done +fi +# <- keyword.control.if.end + +################################ +# And, or, pipes, redirections # +################################ +cmd1 --opt1 arg1 | cmd2 --opt2 arg2 | cmd3 --opt3 arg3 +# ^ meta.function-call variable.function +# ^ variable.parameter - variable.function +# ^ - variable +# ^ keyword + # ^ meta.function-call variable.function + # ^ variable.parameter - variable.function + # ^ - variable + # ^ keyword + # ^ meta.function-call variable.function + # ^ variable.parameter - variable.function + # ^ - variable +C2=c2 C3=c3 C4=c4 +c1 -c1 c1 && ${C2} -c2 c2 || c3 -c3 ${C3} ; c4 -${C4} c4 | c5 -c5 c5 +#^ meta.function-call variable.function +# ^ variable.parameter - variable.function +# ^ - variable +# ^ keyword + # ^ meta.function-call variable.function + # ^ variable.parameter - variable.function + # ^ - variable + # ^ keyword + # ^ meta.function-call variable.function + # ^ variable.parameter - variable.function + # ^ - variable.parameter + # ^ keyword + # ^ + # ^^ variable.function + # ^^^^^^ variable.parameter + +foo 2>&1 +# ^ meta.function-call.arguments constant.numeric.file-descriptor +# ^^ meta.function-call.arguments keyword.operator.assignment.redirection +# ^ meta.function-call.arguments constant.numeric.file-descriptor +foo | bar 2>&1 +# ^ meta.function-call.arguments constant.numeric.file-descriptor +# ^^ meta.function-call.arguments keyword.operator.assignment.redirection +# ^ meta.function-call.arguments constant.numeric.file-descriptor +foo | bar --opt1 arg1 < file.txt +# ^ meta.function-call.arguments keyword.operator.assignment.redirection +foo | bar --opt1 arg1 > file.txt +# ^ meta.function-call.arguments keyword.operator.assignment.redirection +foo -x arg1 &>/dev/null +# ^^ meta.function-call.arguments keyword.operator.assignment.redirection +foo -x arg1 &> /dev/null +# ^^ meta.function-call.arguments keyword.operator.assignment.redirection + +################## +# Here documents # +################## +var=world! +cat < foo.txt +# <- meta.function-call variable.function +# ^ meta.function-call.arguments string.unquoted.heredoc keyword.control.heredoc-token +# ^ meta.function-call.arguments - variable.function keyword.operator.assignment.redirection +# ^ meta.function-call.arguments - variable.function +hello +# <- meta.function-call.arguments string.unquoted.heredoc +redirection_comes_next +# <- meta.function-call.arguments string.unquoted.heredoc keyword.control.heredoc-token + +cat << FARAWAY +# ^ keyword.control +foo +# <- string.unquoted +FARAWAY +# <- keyword.control + +############# +# Functions # +############# + + logC () { [[ $# == 2 ]] && tput setaf $2 || tput setaf 3; echo -e "$1"; tput setaf 15; } +# <- meta.function - entity.name.function +#^^ meta.function - entity.name.function +# ^^^^ meta.function entity.name.function +# ^ meta.function punctuation.section.parens.begin +# ^ meta.function punctuation.section.parens.end +# ^ meta.function +# ^ meta.function punctuation.section.braces.begin +# ^^ meta.function support.function.test.begin +# ^ meta.function meta.function-call.arguments variable.other.readwrite keyword.other.expansion +# ^ meta.function meta.function-call.arguments variable.other.readwrite variable.language +# ^^ meta.function meta.function-call.arguments keyword.operator.logical +# ^^ meta.function meta.function-call.arguments support.function.test.end +# ^^ meta.function keyword.operator.logical.and +logExit () { +#^^^^^^ meta.function entity.name.function +# ^ meta.function punctuation.section.parens.begin +# ^ meta.function punctuation.section.parens.end +# ^ meta.function +# ^ meta.function punctuation.section.braces.begin + [[ $1 == '0' ]] && tput setaf 2 || tput setaf 1; + # <- meta.function support.function.test.begin + # ^^ meta.function meta.function-call.arguments support.function.test.end + [[ $1 == '0' ]] && echo -e "$2 PASSED" || echo -e "$2 FAILED"; + # <- meta.function support.function.test.begin + # ^^ meta.function meta.function-call.arguments support.function.test.end + # ^^ meta.function keyword.operator.logical.and + # ^^^^ meta.function meta.function-call support.function.echo + tput setaf 15; + # <- meta.function meta.function-call variable.function + # ^ meta.function keyword.operator.logical.continue + [[ $1 == '0' ]] || exit -1 + # <- meta.function support.function.test.begin + # ^^ meta.function meta.function-call.arguments support.function.test.end + # ^^ meta.function keyword.operator.logical.or + # ^^^^ meta.function meta.function-call support.function.exit +} + +function connect_to_db() { +# <- meta.function storage.type.function +# ^ meta.function +# ^^^^^^^^^^^^^ meta.function entity.name.function +# ^ meta.function punctuation.section.parens.begin +# ^ meta.function punctuation.section.parens.end +# ^ meta.function +# ^ meta.function punctuation.section.braces.begin + export PGPASSWORD=$(cat "$DOKKU_ROOT/.postgresql/pwd_$APP") + # <- meta.function storage.modifier + # ^^^^^^^^^^ meta.function variable.other.readwrite.assignment + # ^ meta.function keyword.operator.assignment + IP=$(get_postgresql_ip) + # <- meta.function variable.other.readwrite.assignment + # ^ meta.function keyword.operator.assignment + # ^ meta.function string.unquoted variable.other.readwrite keyword.other.expansion + # ^ meta.function string.unquoted variable.other.readwrite punctuation.section.parens.begin + # ^^^^^^^^^^^^^^^^^ meta.function string.unquoted variable.other.readwrite meta.function-call variable.function + # ^ meta.function string.unquoted variable.other.readwrite punctuation.section.parens.end + PORT=$(get_postgresql_port) + # <- meta.function variable.other.readwrite.assignment + # ^ meta.function keyword.operator.assignment + # ^ meta.function string.unquoted variable.other.readwrite keyword.other.expansion + # ^ meta.function string.unquoted variable.other.readwrite punctuation.section.parens.begin + # ^^^^^^^^^^^^^^^^^^^ meta.function string.unquoted variable.other.readwrite meta.function-call variable.function + # ^ meta.function string.unquoted variable.other.readwrite punctuation.section.parens.end + + psql -h $IP -p $PORT -U root db +} +# <- meta.function punctuation.section.braces.end + +# <- - meta.function + +logExit $? $WEIRD +# <- meta.function-call variable.function +# ^ meta.function-call.arguments variable.other.readwrite keyword.other.expansion +# ^ meta.function-call.arguments variable.other.readwrite variable.language +# ^ meta.function-call.arguments variable.other.readwrite keyword.other.expansion +# ^^^^^ meta.function-call.arguments variable.other.readwrite + +declare -f _init_completion > /dev/null && complete -F _upto upto +# <- storage.modifier +# ^ variable.parameter punctuation +# ^ variable.parameter +# ^ keyword.operator.assignment.redirection diff --git a/ShellScript/tools/update-commands.py b/ShellScript/tools/update-commands.py new file mode 100644 index 0000000000..25bbce5785 --- /dev/null +++ b/ShellScript/tools/update-commands.py @@ -0,0 +1,135 @@ +from __future__ import print_function +import yaml +import sys +import os + +def main(): + parent = "scope:source.shell.{}#".format(os.path.splitext(sys.argv[1])[0].split("-")[-1]) + with open(sys.argv[1], "r") as stream: + commands_input = yaml.load(stream) + main = [] + main_bt = [] + contexts = { "main": main, "main-bt": main_bt } + eoo = { + "match": r"(?<=\s)--(?=\s|$)", + "scope": r"keyword.operator.end-of-options.shell", + "set": [ + { "meta_content_scope" : r"meta.function-call.arguments.shell"}, + { "include": parent + r"expansion-and-string" }, + { "include": parent + r"line-continuation-or-pop-at-end" } + ] + } + opt_end_boundary = r"(?=\s|;|$|`|\))" + for command, value in commands_input.items(): + if not value: + value = {} + match = value.get("match", None) + short_options = value.get("short-options", None) + long_options = value.get("long-options", None) + short_option_prefixes = value.get("short-option-prefixes", None) + short_options_compact = value.get("short-options-compact", None) + allow_eoo = value.get("allow-end-of-options-token", True) + scope = value.get("scope", None) + if not scope: + scope = "support.function.{}.shell".format(command) + scope = "meta.function-call.shell " + scope + cmd_args_base = [] + cmd_args = [] + cmd_args_bt = [] + if match: + match = "{{boundary_begin}}%s{{boundary_end}}" % match + else: + match = "{{boundary_begin}}%s{{boundary_end}}" % command + if allow_eoo: + cmd_args_base.append(eoo) + if long_options: + thedict = { + "match": r"(?<=\s|^)((--)" + "|".join(long_options) + r")" + opt_end_boundary, + "captures": { + 2: "punctuation.definition.parameter.shell", + 1: "variable.parameter.shell" + } + } + cmd_args_base.append(thedict) + thedict = {} + thelist = [] + opts = "" + if short_options: + opts += "[" + short_options + "]" + if short_options_compact: + if opts: + opts += "|" + opts += "[" + short_options_compact + "]+" + if opts: + if short_option_prefixes: + prefix = "|".join(short_option_prefixes) + thedict = { + "match": r"(?<=\s|^)((" + prefix + r")(?:" + opts + r"))" + opt_end_boundary, + "captures": { + 2: "punctuation.definition.parameter.shell", + 1: "variable.parameter.shell" + } + } + else: + thedict = { + "match": r"(?<=\s|^)((-)" + opts + r")" + opt_end_boundary, + "captures": { + 2: "punctuation.definition.parameter.shell", + 1: "variable.parameter.shell" + } + } + if thedict: + cmd_args_base.append(thedict) + if thelist: + cmd_args_base.extend(thelist) + cmd_args.append({ "meta_scope": "meta.function-call.arguments.shell" }) + cmd_args.append({ "include": parent + r"cmd-args-boilerplate" }) + cmd_args_bt.append({ "meta_scope": "meta.function-call.arguments.shell" }) + cmd_args_bt.append({ "include": parent + r"cmd-args-boilerplate-bt" }) + if len(cmd_args_base) > 0: + cmd_args.append({ "include": "cmd-args-{}-base".format(command) }) + cmd_args_bt.append({ "include": "cmd-args-{}-base".format(command) }) + contexts["cmd-args-{}-base".format(command)] = cmd_args_base + cmd_args = [ {"match": "", "set": cmd_args }] + cmd_args_bt = [ {"match": "", "set": cmd_args_bt }] + contexts["cmd-args-{}".format(command)] = cmd_args + contexts["cmd-args-{}-bt".format(command)] = cmd_args_bt + main.append({ + "match": match, + "scope": scope, + "set": ["{}cmd-post".format(parent), "cmd-args-{}".format(command)] + }) + main_bt.append({ + "match": match, + "scope": scope, + "set": ["{}cmd-post-bt".format(parent), "cmd-args-{}-bt".format(command)] + }) + contexts["prototype"] = [{ + "include":parent + r"prototype" + }] + + commands_output = { + "scope": os.path.splitext(sys.argv[1])[0].replace("-", "."), + "hidden": True, + "variables": { + "boundary_end": r"(?=\s|;|$)", + "boundary_begin": '' #r"(?:(?<=\s)|^)" + }, + "contexts": contexts + } + + with open(sys.argv[2], "w") as stream: + print("%YAML 1.2\n---", file=stream) + print("# Automatically generated file -- do not edit!", file=stream) + noalias_dumper = yaml.dumper.SafeDumper + noalias_dumper.ignore_aliases = lambda self, data: True + yaml.dump(commands_output, stream, + default_flow_style=False, + allow_unicode=True, + default_style='', + Dumper=noalias_dumper) + + return 0 + +if __name__ == '__main__': + exit(main())