diff --git a/SUPPORTED_LANGUAGES.md b/SUPPORTED_LANGUAGES.md index 177b3951a..ce74e9795 100644 --- a/SUPPORTED_LANGUAGES.md +++ b/SUPPORTED_LANGUAGES.md @@ -196,6 +196,7 @@ jsx (queries only)[^jsx] | unstable | `HFIJ ` | @steelsojka [nu](https://github.com/nushell/tree-sitter-nu) | unstable | `HFIJ ` | @abhisheksingh0x558 [objc](https://github.com/tree-sitter-grammars/tree-sitter-objc) | unstable | `HFIJL` | @amaanq [objdump](https://github.com/ColinKennedy/tree-sitter-objdump) | unstable | `H  J ` | @ColinKennedy +[objectscript](https://github.com/intersystems/tree-sitter-objectscript) | unstable | `H IJL` | @davem-intersys [ocaml](https://github.com/tree-sitter/tree-sitter-ocaml) | unstable | `HFIJL` | @undu [ocaml_interface](https://github.com/tree-sitter/tree-sitter-ocaml) | unstable | `HFIJL` | @undu [ocamllex](https://github.com/atom-ocaml/tree-sitter-ocamllex) | unstable | `H  J ` | @undu diff --git a/lua/nvim-treesitter/parsers.lua b/lua/nvim-treesitter/parsers.lua index e980ae3c3..53c991629 100644 --- a/lua/nvim-treesitter/parsers.lua +++ b/lua/nvim-treesitter/parsers.lua @@ -1509,6 +1509,15 @@ return { maintainers = { '@ColinKennedy' }, tier = 2, }, + objectscript = { + install_info = { + revision = '4d34cb2d4a4924f0b9c9524ffaba1b9c0644067e', + url = 'https://github.com/intersystems/tree-sitter-objectscript', + location = 'udl', + }, + maintainers = { '@davem-intersys' }, + tier = 2, + }, ocaml = { install_info = { location = 'grammars/ocaml', diff --git a/plugin/filetypes.lua b/plugin/filetypes.lua index 5e23adffd..7bfb9e6df 100644 --- a/plugin/filetypes.lua +++ b/plugin/filetypes.lua @@ -31,6 +31,7 @@ local filetypes = { make = { 'automake' }, markdown = { 'pandoc' }, muttrc = { 'neomuttrc' }, + objectscript = { 'objectscript', 'udl' }, ocaml_interface = { 'ocamlinterface' }, perl = { 'pl' }, poe_filter = { 'poefilter' }, diff --git a/runtime/queries/objectscript/highlights.scm b/runtime/queries/objectscript/highlights.scm new file mode 100644 index 000000000..8cc31c3cd --- /dev/null +++ b/runtime/queries/objectscript/highlights.scm @@ -0,0 +1,273 @@ +; -------------- Objectscript ------------- +; Variables +; ^| e.g. '^||ppg', 'do', 'D' +; ----------------------------------------- +(gvn) @variable.builtin + +(ssvn) @variable.builtin + +(lvn) @variable + +(instance_variable) @variable.member + +; String literals +; e.g. "Fo345349*_)(*_)8023841-40"" " +; ----------------------------------------- +(string_literal) @string + +(pattern_expression) @string.regexp + +; Operators +(_ + operator: _ @operator) + +; Numeric literals +; e.g. 12345 +(numeric_literal) @number + +; System variable name +; e.g. $IO, $SY[SYTEM] +(system_defined_variable) @function.builtin + +; System defined functions +; e.g. $ASCII(62) +(system_defined_function) @function.builtin + +(dollarsf + ; $SYSTEM.Foo.Bar() + (dollar_system_keyword) @function.builtin) + +(property_name) @property + +(parameter_name) @constant + +(_ + parameter: _ @variable.parameter) + +; Method invcoations +(instance_method_call) @function.method.call + +(class_method_call + (class_ref + (class_name) @type.definition) + (method_name) @function.method.call) + +(oref_method + (method_name) @function.method.call) + +(_ + preproc_keyword: (_) @keyword.directive) + +(_ + modifier: (_) @keyword.directive) + +; User-defined functions +(extrinsic_function) @function.call + +; Goto labels and locations +(_ + label: (_) @label) + +(_ + offset: (_) @number) + +(_ + routine: (_) @module) + +; JSON literals +(json_boolean_literal) @boolean + +(json_null_literal) @constant.builtin + +(json_number_literal) @number + +(json_string_literal) @string.escape + +; Macros +(macro + (macro_constant)) @constant.macro + +(macro + (macro_function)) @function.macro + +; -------------- Objectscript Core ------------- +; Commands +; e.g. 'set', 'do', 'D' +; ----------------------------------------- +(_ + command_name: (_) @keyword) + +(_ + macro_name: (_) @function.macro) + +(_ + macro_arg: (_) @constant.macro) + +(_ + mnemonic: (_) @constant.macro) + +; Functions that can be on the LHS of a SET +(doable_dollar_functions) @function.builtin + +; non-extrinsic routine call +(routine_tag_call) @function.call + +; Technically elseif and else_block are not statements, +; so we need ot query them explicitly +;(elseif_block command_name: (_) @keyword) +;(else_block command_name: (_) @keyword) +"{" @punctuation.bracket + +"}" @punctuation.bracket + +; Comments +; e.g. '// fj;lkasdfj', '#; sklfjas;k', '; sklfjas','/* sdfs */' +[ + (line_comment_1) + (line_comment_2) + (line_comment_3) + (block_comment) +] @comment + +(embedded_html + (keyword_embedded_html) @keyword.directive + "<" @keyword.directive + ">" @keyword.directive) + +; (embedded_sql_hash +; (keyword_embedded_sql_hash) @keyword.directive +; ) +; (embedded_sql_amp +; (keyword_embedded_sql_amp) @keyword.directive +; "(" @keyword.directive +; ")" @keyword.directive +; (embedded_sql_reverse_marker) @keyword.directive +; ) +(embedded_sql_amp + (keyword_embedded_sql_amp) @keyword.directive + "(" @keyword.directive + ")" @keyword.directive) + +(embedded_sql_hash + (keyword_embedded_sql_hash) @keyword.directive + "(" @keyword.directive + ")" @keyword.directive) + +(embedded_js + (keyword_embedded_js) @keyword.directive + "<" @keyword.directive + ">" @keyword.directive) + +(embedded_xml + (keyword_embedded_xml) @keyword.directive + "<" @keyword.directive + ">" @keyword.directive) + +(tag) @label + +; Lock type specifications +(locktype) @variable.parameter.builtin + +(_ + keyword: (_) @keyword) + +; (identifier) @variable +; Alternatively +; (class_statement (_ class_statement_keyword: (_) @keyword ) .) +"{" @punctuation.bracket + +"}" @punctuation.bracket + +; @class.name capture group is not suppported in nvim highlighter +; (class_definition class_name: (identifier) @class.name) +(include_clause + (identifier) @keyword.import) + +(property + (identifier) @property) + +(parameter + (identifier) @constant) + +(projection + (identifier) @type.definition) + +(trigger + (identifier) @type.definition) + +(index + (identifier) @type.definition) + +(relationship + (identifier) @type.definition) + +(foreignkey + (identifier) @type.definition) + +(xdata + (identifier) @constant) + +(typename) @type + +(class_definition + class_name: (identifier) @type + (class_extends + (identifier) @type)) + +(method_definition + (identifier + (identifier)) @function) + +(query + (identifier) @function) + +(argument + (identifier) @variable.parameter) + +(keyword_name) @keyword + +(class_keywords + (_ + rhs: _ @constant.builtin)) + +(parameter_keywords + (_ + rhs: _ @constant.builtin)) + +(property_keywords + (_ + rhs: _ @constant.builtin)) + +(xdata_keywords + (_ + rhs: _ @constant.builtin)) + +(method_keywords + (_ + rhs: _ @constant.builtin)) + +(trigger_keywords + (_ + rhs: _ @constant.builtin)) + +(query_keywords + (_ + rhs: _ @constant.builtin)) + +(index_keywords + (_ + rhs: _ @constant.builtin)) + +(foreignkey_keywords + (_ + rhs: _ @constant.builtin)) + +(projection_keywords + (_ + rhs: _ @constant.builtin)) + +(relationship_keywords + (_ + rhs: _ @constant.builtin)) + +(documatic_line) @comment.documentation diff --git a/runtime/queries/objectscript/indents.scm b/runtime/queries/objectscript/indents.scm new file mode 100644 index 000000000..70384b549 --- /dev/null +++ b/runtime/queries/objectscript/indents.scm @@ -0,0 +1,35 @@ +; Indentation rules for ObjectScript UDL (nvim-treesitter) +; --- Class Definition --- +(class_body + "{" @indent.begin + "}" @indent.end) + +; --- Block-style commands with braces --- +(command_while + "{" @indent.begin + "}" @indent.end) + +(command_for + "{" @indent.begin + "}" @indent.end) + +(command_if + "{" @indent.begin + "}" @indent.end) + +(elseif_block + "{" @indent.begin + "}" @indent.end) + +(else_block + "{" @indent.begin + "}" @indent.end) + +; --- Generic brace and parenthesis handling --- +"{" @indent.begin + +"}" @indent.end + +("(" @indent.align + (#set! indent.open_delimiter "(") + (#set! indent.close_delimiter ")")) diff --git a/runtime/queries/objectscript/injections.scm b/runtime/queries/objectscript/injections.scm new file mode 100644 index 000000000..6bb4fcf10 --- /dev/null +++ b/runtime/queries/objectscript/injections.scm @@ -0,0 +1,124 @@ +; Target method_body_content and reparse it using +; objectscript_core +(embedded_html + (angled_bracket_fenced_text) @injection.content + (#set! injection.language "html") + (#set! injection.include-children "false") + (#set! injection.combined "true")) + +(embedded_sql + (_ + (paren_fenced_text) @injection.content) + (#set! injection.language "sql") + (#set! injection.include-children "false") + (#set! injection.combined "true")) + +(embedded_js + (angled_bracket_fenced_text) @injection.content + (#set! injection.language "javascript") + (#set! injection.include-children "false") + (#set! injection.combined "true")) + +(embedded_xml + (angled_bracket_fenced_text) @injection.content + (#set! injection.language "xml") + (#set! injection.include-children "false") + (#set! injection.combined "true")) + +([ + (line_comment_1) + (line_comment_2) + (line_comment_3) + (block_comment) + (documatic_line) +] @injection.content + (#set! injection.language "comment")) + +; Keywords, one of type language = "python", none of type codemode +(method_definition + keywords: (_ + (kw_External_Language + rhs: _ @injection.language)) + body: (_) @injection.content + (#set! injection.include-children "true")) + +(trigger + keywords: (_ + (kw_External_Language + rhs: _ @injection.language)) + body: (_) @injection.content + (#set! injection.include-children "true")) + +; A query must be of type %SQLQuery to have an SQL body, otherwise the body +; is empty +(query + type: (_ + (typename + (identifier) @_querytype + (#eq? @_querytype "%SQLQuery"))) + (_ + (query_body_content) @injection.content) + (#set! injection.language "sql") + (#set! injection.include-children "true")) + +; XDATA blocks. There's a MimeType keyword that defines the content-type +; To prevent overlapping matches, we use a different body for the case where +; no MimeType is given and default to XML, otherwise we extract the language +; from the mimetype. +(xdata + keywords: (_ + (kw_MimeType + rhs: _ @_mimetype + (#eq? @_mimetype "\"text/markdown\""))) + body: (xdata_body_content_any) @injection.content + (#set! injection.language "markdown") + (#set! injection.include-children "true")) + +(xdata + keywords: (_ + (kw_MimeType + rhs: _ @_mimetype + (#eq? @_mimetype "\"text/xml\""))) + ; NOTE: Since MimeType is given, we match xdata_body_content_any not xml + body: (xdata_body_content_any) @injection.content + (#set! injection.language "xml") + (#set! injection.include-children "true")) + +(xdata + keywords: (_ + (kw_MimeType + rhs: _ @_mimetype + (#eq? @_mimetype "\"text/html\""))) + body: (xdata_body_content_any) @injection.content + (#set! injection.language "html") + (#set! injection.include-children "true")) + +(xdata + keywords: (_ + (kw_MimeType + rhs: _ @_mimetype + (#eq? @_mimetype "\"application/json\""))) + body: (xdata_body_content_any) @injection.content + (#set! injection.language "json") + (#set! injection.include-children "true")) + +(xdata + keywords: (_ + (kw_MimeType + rhs: _ @_mimetype + (#eq? @_mimetype "\"text/css\""))) + body: (xdata_body_content_any) @injection.content + (#set! injection.language "css") + (#set! injection.include-children "true")) + +; Match an unspecified XDATA -- defaults to XML +(xdata + body: (xdata_body_content_xml) @injection.content + (#set! injection.language "xml") + (#set! injection.include-children "true")) + +; Storage definition is XML +(storage + body: (_) @injection.content + (#set! injection.language "xml") + (#set! injection.include-children "true")) diff --git a/runtime/queries/objectscript/locals.scm b/runtime/queries/objectscript/locals.scm new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/runtime/queries/objectscript/locals.scm @@ -0,0 +1 @@ +