diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index c114faa13d82..17f6149d0f8b 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -175,7 +175,7 @@ | nickel | ✓ | | ✓ | | | `nls` | | nim | ✓ | ✓ | ✓ | | | `nimlangserver` | | nix | ✓ | ✓ | ✓ | | ✓ | `nil`, `nixd` | -| nu | ✓ | | | | | `nu` | +| nu | ✓ | ✓ | ✓ | | | `nu` | | nunjucks | ✓ | | | | | | | ocaml | ✓ | | ✓ | | | `ocamllsp` | | ocaml-interface | ✓ | | | | | `ocamllsp` | diff --git a/languages.toml b/languages.toml index 9055a6d9a808..613030c54798 100644 --- a/languages.toml +++ b/languages.toml @@ -2368,7 +2368,7 @@ language-servers = [ "nu-lsp" ] [[grammar]] name = "nu" -source = { git = "https://github.com/nushell/tree-sitter-nu", rev = "358c4f509eb97f0148bbd25ad36acc729819b9c1" } +source = { git = "https://github.com/nushell/tree-sitter-nu", rev = "cc4624fbc6ec3563d98fbe8f215a8b8e10b16f32" } [[language]] name = "vala" diff --git a/runtime/queries/nu/folds.scm b/runtime/queries/nu/folds.scm new file mode 100644 index 000000000000..53607745aa60 --- /dev/null +++ b/runtime/queries/nu/folds.scm @@ -0,0 +1,10 @@ +[ + (attribute_list) + (block) + (command_list) + (parameter_bracks) + (record_body) + (val_list) + (val_table) + (val_closure) +] @fold diff --git a/runtime/queries/nu/highlights.scm b/runtime/queries/nu/highlights.scm index 66a305840508..27583f2fea55 100644 --- a/runtime/queries/nu/highlights.scm +++ b/runtime/queries/nu/highlights.scm @@ -1,284 +1,410 @@ -;;; --- -;;; keywords +; --- +; keywords [ - "def" - "alias" - "export-env" - "export" - "extern" - "module" - - "let" - "let-env" - "mut" - "const" - - "hide-env" + "let" + "mut" + "const" +] @keyword - "source" - "source-env" +[ + "if" + "else" + "match" +] @keyword.control.conditional - "overlay" - "register" +[ + "loop" + "while" +] @keyword.control.repeat - "loop" - "while" - "error" +"def" @keyword.function - "do" - "if" - "else" - "try" - "catch" - "match" +[ + "try" + "catch" + "error" +] @keyword.control.exception - "break" - "continue" - "return" +[ + "module" + "use" +] @keyword.control.import -] @keyword +[ + "alias" + "export-env" + "export" + "extern" +] @keyword.storage.modifier -(hide_mod "hide" @keyword) -(decl_use "use" @keyword) +(decl_use + "use" @keyword.control.import) (ctrl_for - "for" @keyword - "in" @keyword -) -(overlay_list "list" @keyword.storage.modifier) -(overlay_hide "hide" @keyword.storage.modifier) -(overlay_new "new" @keyword.storage.modifier) -(overlay_use - "use" @keyword.storage.modifier - "as" @keyword -) -(ctrl_error "make" @keyword.storage.modifier) + "for" @keyword.control.repeat + "in" @keyword.control.repeat) -;;; --- -;;; literals +; --- +; literals (val_number) @constant.numeric + (val_duration - unit: [ - "ns" "µs" "us" "ms" "sec" "min" "hr" "day" "wk" - ] @variable.parameter -) + unit: _ @variable.parameter) + (val_filesize - unit: [ - "b" "B" - - "kb" "kB" "Kb" "KB" - "mb" "mB" "Mb" "MB" - "gb" "gB" "Gb" "GB" - "tb" "tB" "Tb" "TB" - "pb" "pB" "Pb" "PB" - "eb" "eB" "Eb" "EB" - - "kib" "kiB" "kIB" "kIb" "Kib" "KIb" "KIB" - "mib" "miB" "mIB" "mIb" "Mib" "MIb" "MIB" - "gib" "giB" "gIB" "gIb" "Gib" "GIb" "GIB" - "tib" "tiB" "tIB" "tIb" "Tib" "TIb" "TIB" - "pib" "piB" "pIB" "pIb" "Pib" "PIb" "PIB" - "eib" "eiB" "eIB" "eIb" "Eib" "EIb" "EIB" - ] @variable.parameter -) + unit: _ @variable.parameter) + (val_binary - [ - "0b" - "0o" - "0x" - ] @constant.numeric - "[" @punctuation.bracket - digit: [ - "," @punctuation.delimiter - (hex_digit) @constant.number - ] - "]" @punctuation.bracket -) @constant.numeric -(val_bool) @constant.builtin + [ + "0b" + "0o" + "0x" + ] @constant.numeric + "[" @punctuation.bracket + digit: [ + "," @punctuation.delimiter + (hex_digit) @constant.numeric + ] + "]" @punctuation.bracket) @constant.numeric + +(val_bool) @constant.builtin.boolean + (val_nothing) @constant.builtin + (val_string) @string -(val_date) @constant.number + +arg_str: (val_string) @variable.parameter + +file_path: (val_string) @variable.parameter + +(val_date) @constant.numeric + (inter_escape_sequence) @constant.character.escape + (escape_sequence) @constant.character.escape -(val_interpolated [ + +(val_interpolated + [ "$\"" "$\'" "\"" "\'" -] @string) + ] @string) + (unescaped_interpolated_content) @string + (escaped_interpolated_content) @string -(expr_interpolated ["(" ")"] @variable.parameter) -;;; --- -;;; operators -(expr_binary [ - "+" - "-" - "*" - "/" - "mod" - "//" - "++" - "**" - "==" - "!=" - "<" - "<=" - ">" - ">=" - "=~" - "!~" - "and" - "or" - "xor" - "bit-or" - "bit-xor" - "bit-and" - "bit-shl" - "bit-shr" - "in" - "not-in" - "starts-with" - "ends-with" -] @operator ) - -(where_command [ - "+" - "-" - "*" - "/" - "mod" - "//" - "++" - "**" - "==" - "!=" - "<" - "<=" - ">" - ">=" - "=~" - "!~" - "and" - "or" - "xor" - "bit-or" - "bit-xor" - "bit-and" - "bit-shl" - "bit-shr" - "in" - "not-in" - "starts-with" - "ends-with" -] @operator) - -(assignment [ +(expr_interpolated + [ + "(" + ")" + ] @variable.parameter) + +(raw_string_begin) @punctuation.special + +(raw_string_end) @punctuation.special + +; --- +; operators +(expr_binary + opr: _ @operator) + +(where_predicate + opr: _ @operator) + +(assignment + [ "=" "+=" "-=" "*=" "/=" "++=" -] @operator) + ] @operator) -(expr_unary ["not" "-"] @operator) +(expr_unary + [ + "not" + "-" + ] @operator) -(val_range [ +(val_range + [ ".." "..=" "..<" -] @operator) + ] @operator) -["=>" "=" "|"] @operator +[ + "=>" + "=" + "|" +] @operator [ - "o>" "out>" - "e>" "err>" - "e+o>" "err+out>" - "o+e>" "out+err>" -] @special - -;;; --- -;;; punctuation + "o>" + "out>" + "e>" + "err>" + "e+o>" + "err+out>" + "o+e>" + "out+err>" + "o>>" + "out>>" + "e>>" + "err>>" + "e+o>>" + "err+out>>" + "o+e>>" + "out+err>>" + "e>|" + "err>|" + "e+o>|" + "err+out>|" + "o+e>|" + "out+err>|" +] @operator + +; --- +; punctuation [ - "," - ";" -] @punctuation.delimiter - -(param_short_flag "-" @punctuation.delimiter) -(param_long_flag ["--"] @punctuation.delimiter) -(long_flag ["--"] @punctuation.delimiter) -(param_rest "..." @punctuation.delimiter) -(param_type [":"] @punctuation.special) -(param_value ["="] @punctuation.special) -(param_cmd ["@"] @punctuation.special) -(param_opt ["?"] @punctuation.special) + "," + ";" +] @punctuation.special + +(param_long_flag + "--" @punctuation.delimiter) + +(long_flag + "--" @punctuation.delimiter) + +(short_flag + "-" @punctuation.delimiter) + +(long_flag + "=" @punctuation.special) + +(short_flag + "=" @punctuation.special) + +(param_short_flag + "-" @punctuation.delimiter) + +(param_rest + "..." @punctuation.delimiter) + +(param_type + ":" @punctuation.special) + +(param_value + "=" @punctuation.special) + +(param_cmd + "@" @punctuation.special) + +(attribute + "@" @punctuation.special) + +(param_opt + "?" @punctuation.special) + +(returns + "->" @punctuation.special) [ - "(" ")" - "{" "}" - "[" "]" + "(" + ")" + "{" + "}" + "[" + "]" + "...[" + "...(" + "...{" ] @punctuation.bracket (val_record - (record_entry ":" @punctuation.delimiter)) -;;; --- -;;; identifiers + (record_entry + ":" @punctuation.delimiter)) + +key: (identifier) @property + +; --- +; identifiers (param_rest - name: (_) @variable.parameter) + name: (_) @variable.parameter) + (param_opt - name: (_) @variable.parameter) + name: (_) @variable.parameter) + (parameter - param_name: (_) @variable.parameter) + param_name: (_) @variable.parameter) + (param_cmd - (cmd_identifier) @string) -(param_long_flag) @variable.parameter -(param_short_flag) @variable.parameter + (cmd_identifier) @string) + +(param_long_flag + (long_flag_identifier) @attribute) + +(param_short_flag + (param_short_flag_identifier) @attribute) + +(attribute + (attribute_identifier) @attribute) + +(short_flag + (short_flag_identifier) @attribute) -(short_flag) @variable.parameter -(long_flag) @variable.parameter +(long_flag_identifier) @attribute -(scope_pattern [(wild_card) @function]) +(scope_pattern + (wild_card) @function) (cmd_identifier) @function -(command - "^" @punctuation.delimiter - head: (_) @function +(decl_def . "def" + (val_string + (string_content) @function + ) ) -"where" @function +; generated with Nu 0.107.0 +; help commands +; | where $it.command_type == built-in and $it.category != core +; | each {$'"($in.name | split row " " | $in.0)"'} +; | uniq +; | str join ' ' +(command + head: (cmd_identifier) @function.builtin + (#any-of? @function.builtin + "all" "ansi" "any" "append" "ast" "bits" "bytes" "cal" "cd" "char" "chunk-by" "chunks" "clear" "collect" "columns" "compact" "complete" "config" "cp" "date" "debug" "decode" "default" "detect" "drop" "du" "each" "encode" "enumerate" "every" "exec" "exit" "explain" "explore" "fill" "filter" "find" "first" "flatten" "format" "from" "generate" "get" "glob" "grid" "group-by" "hash" "headers" "histogram" "history" "http" "input" "insert" "inspect" "interleave" "into" "is-empty" "is-not-empty" "is-terminal" "items" "job" "join" "keybindings" "kill" "last" "length" "let-env" "lines" "load-env" "ls" "math" "merge" "metadata" "mkdir" "mktemp" "move" "mv" "nu-check" "nu-highlight" "open" "panic" "par-each" "parse" "path" "plugin" "port" "prepend" "print" "ps" "query" "random" "reduce" "reject" "rename" "reverse" "rm" "roll" "rotate" "run-external" "save" "schema" "select" "seq" "shuffle" "skip" "sleep" "slice" "sort" "sort-by" "split" "start" "stor" "str" "sys" "table" "take" "tee" "term" "timeit" "to" "touch" "transpose" "tutor" "ulimit" "uname" "uniq" "uniq-by" "update" "upsert" "url" "values" "version" "view" "watch" "which" "whoami" "window" "with-env" "wrap" "zip")) + +(command + head: (cmd_identifier) @keyword.control.repeat + (#any-of? @keyword.control.repeat "break" "continue" "return")) + +(command + head: (cmd_identifier) @keyword + (#any-of? @keyword "do" "source" "source-env" "hide" "hide-env")) + +(command + head: (cmd_identifier) @keyword + . + arg_str: (val_string) @keyword.control.import + (#any-of? @keyword "overlay" "error")) + +(command + head: (cmd_identifier) @cmd + arg_str: (val_string) @keyword + (#eq? @cmd "overlay") + (#eq? @keyword "as")) + +(command + "^" @punctuation.delimiter + head: (_) @function) + +"where" @function.builtin + +(where_predicate + [ + "?" + "!" + ] @punctuation.delimiter) (path - ["." "?"] @punctuation.delimiter -) @variable.parameter + [ + "." + "?" + "!" + ]? @punctuation.delimiter) @variable.parameter + +(stmt_let + (identifier) @variable) -(val_variable - "$" @variable.parameter +(val_variable + "$"? @punctuation.special + "...$"? @punctuation.special [ - (identifier) @namespace - "in" - "nu" - "env" - "nothing" - ] @special -) -;;; --- -;;; types -(flat_type) @type.builtin + (identifier) @variable + "in" @special + "nu" @namespace + "env" @constant + ]) @none + +(val_cellpath + "$" @punctuation.special) + +(record_entry + ":" @punctuation.special) + +; --- +; types +(flat_type) @type + (list_type - "list" @type.enum - ["<" ">"] @punctuation.bracket -) + "list" @type.enum + [ + "<" + ">" + ] @punctuation.bracket) + (collection_type - ["record" "table"] @type.enum - "<" @punctuation.bracket - key: (_) @variable.parameter - ["," ":"] @punctuation.delimiter - ">" @punctuation.bracket -) + [ + "record" + "table" + ] @type.enum + "<" @punctuation.bracket + key: (_) @variable.parameter + [ + "," + ":" + ] @punctuation.special + ">" @punctuation.bracket) + +(composite_type + "oneof" @type.enum + [ + "<" + ">" + ] @punctuation.bracket) + +[(comment) (shebang)] @comment + +((comment)+ @comment.documentation + . + (decl_def)) -(shebang) @comment -(comment) @comment +(parameter + (comment) @comment.documentation) + +(command + head: ((cmd_identifier) @function.builtin + (#match? @function.builtin "^\\s*(find|parse|split|str)$")) + flag: (_ + name: (_) @attribute + (#any-of? @attribute "r" "regex")) + . + arg: (_ + (string_content) @string.regexp)) + +(_ + opr: [ + "=~" + "!~" + "like" + "not-like" + ] + rhs: (_ + (string_content) @string.regexp)) + +(command + head: ((_) @function + (#any-of? @function "nu" "$nu.current-exe")) + flag: (_ + name: (_) @attribute + (#any-of? @attribute "c" "e" "commands" "execute")) + . + arg: (_ + (string_content) @string.code)) diff --git a/runtime/queries/nu/indents.scm b/runtime/queries/nu/indents.scm new file mode 100644 index 000000000000..5a1f109b7026 --- /dev/null +++ b/runtime/queries/nu/indents.scm @@ -0,0 +1,18 @@ +[ + (expr_parenthesized) + (parameter_bracks) + (ctrl_match) + + (val_record) + (val_list) + (val_closure) + (val_table) + + (block) +] @indent + +[ + "}" + "]" + ")" +] @outdent diff --git a/runtime/queries/nu/injections.scm b/runtime/queries/nu/injections.scm index 690ff9a864ca..8005ffdc64bc 100644 --- a/runtime/queries/nu/injections.scm +++ b/runtime/queries/nu/injections.scm @@ -1,7 +1,50 @@ ((comment) @injection.content - (#set! injection.language "comment")) + (#set! injection.language "comment")) + +(command + head: ((cmd_identifier) @_cmd + (#match? @_cmd "^\\s*(find|parse|split|str)$")) + flag: (_ + name: (_) @_flag + (#any-of? @_flag "r" "regex")) + . + arg: (_ + (string_content) @injection.content + (#set! injection.language "regex"))) + +(_ + opr: [ + "=~" + "!~" + "like" + "not-like" + ] + rhs: (_ + (string_content) @injection.content + (#set! injection.language "regex"))) + +(command + head: (_) @_cmd + (#any-of? @_cmd "nu" "$nu.current-exe") + flag: (_ + name: (_) @_flag + (#any-of? @_flag "c" "e" "commands" "execute")) + . + arg: (_ + (string_content) @injection.content + (#set! injection.language "nu"))) (command head: (cmd_identifier) @_command (#any-of? @_command "jq" "jaq") - arg: (val_string) @injection.content - (#set! injection.language "jq")) + . + arg: (_ (string_content) @injection.content) + (#set! injection.language "jq") +) + +(command + head: (cmd_identifier) @_command (#eq? @_command "fish") + flag: (short_flag "-") @_flag (#match? @_flag "^-.*c$") + . + arg: (_ (string_content) @injection.content) + (#set! injection.language "fish") +) diff --git a/runtime/queries/nu/textobjects.scm b/runtime/queries/nu/textobjects.scm new file mode 100644 index 000000000000..ddf92ee2d364 --- /dev/null +++ b/runtime/queries/nu/textobjects.scm @@ -0,0 +1,78 @@ +; (stmt_let) @assignment.outer + +; (stmt_mut) @assignment.outer + +; (stmt_const) @assignment.outer + +; (stmt_let +; value: (_) @assignment.inner) + +; (stmt_mut +; value: (_) @assignment.inner) + +; (stmt_const +; value: (_) @assignment.inner) + +; (block) @block.outer + +(comment) @comment.around + +; (pipeline) @pipeline.outer + +; (pipe_element) @pipeline.inner + +(decl_def) @function.around + +(decl_def + body: (_) @function.inside) + +; (ctrl_for) @loop.outer + +; (ctrl_loop) @loop.outer + +; (ctrl_while) @loop.outer + +; (ctrl_for +; body: (_) @loop.inner) + +; (ctrl_loop +; body: (_) @loop.inner) + +; (ctrl_while +; body: (_) @loop.inner) + +; Conditional inner counts the last one, rather than the current one. +; (ctrl_if +; then_branch: (_) @conditional.inner +; else_block: (_)? @conditional.inner) @conditional.outer + +(parameter) @parameter.around + +; (command +; head: (_) @call.inner) @call.outer + +; (where_command +; predicate: (_) @call.inner) @call.outer + +; define pipeline first, because it should only match as a fallback +; e.g., `let a = date now` should match the whole assignment. +; But a standalone `date now` should also match a statement +; (pipeline) @statement.outer + +; (stmt_let) @statement.outer + +; (stmt_mut) @statement.outer + +; (stmt_const) @statement.outer + +; (ctrl_if) @statement.outer + +; (ctrl_try) @statement.outer + +; (ctrl_match) @statement.outer + +; (ctrl_while) @statement.outer + +; (ctrl_loop) @statement.outer + +; (val_number) @number.inner