From a4fec4f00f52581f42b7fe07a1bc6efdc17be9d2 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Sat, 27 May 2023 10:04:04 +1200 Subject: [PATCH 1/2] tree-sitter: Add the .slint UI language --- CHANGELOG.md | 1 + Cargo.lock | 10 ++ lapce-app/Cargo.toml | 1 + lapce-core/Cargo.toml | 2 + lapce-core/queries/slint/highlights.scm | 155 ++++++++++++++++++++++++ lapce-core/queries/slint/indents.scm | 16 +++ lapce-core/queries/slint/locals.scm | 2 + lapce-core/src/language.rs | 32 ++++- lapce-proxy/src/buffer.rs | 1 + 9 files changed, 215 insertions(+), 5 deletions(-) create mode 100644 lapce-core/queries/slint/highlights.scm create mode 100644 lapce-core/queries/slint/indents.scm create mode 100644 lapce-core/queries/slint/locals.scm diff --git a/CHANGELOG.md b/CHANGELOG.md index 16efc543fc..9443221a7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - [#3026](https://github.com/lapce/lapce/pull/3026): Add missing file explorer context menu entries - [#3047](https://github.com/lapce/lapce/pull/3047): Add support for different CrLf/Lf line endings per-file - [#3053](https://github.com/lapce/lapce/pull/3053): Add tooltips to various places +- [2407](https://github.com/lapce/lapce/pull/2407): Add support for slint UI language ### Bug Fixes - [#2779](https://github.com/lapce/lapce/pull/2779): Fix files detection on fresh git/VCS repository diff --git a/Cargo.lock b/Cargo.lock index 828f5083ef..a56495020d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3132,6 +3132,7 @@ dependencies = [ "tree-sitter-md", "tree-sitter-python", "tree-sitter-rust", + "tree-sitter-slint", "tree-sitter-toml", "tree-sitter-yaml", ] @@ -5874,6 +5875,15 @@ dependencies = [ "tree-sitter", ] +[[package]] +name = "tree-sitter-slint" +version = "0.0.1" +source = "git+https://github.com/jrmoulton/tree-sitter-slint.git?rev=00c8a2d3645766f68c0d0460086c0a994e5b0d85#00c8a2d3645766f68c0d0460086c0a994e5b0d85" +dependencies = [ + "cc", + "tree-sitter", +] + [[package]] name = "tree-sitter-toml" version = "0.20.0" diff --git a/lapce-app/Cargo.toml b/lapce-app/Cargo.toml index 1597ec2777..084f082854 100644 --- a/lapce-app/Cargo.toml +++ b/lapce-app/Cargo.toml @@ -92,6 +92,7 @@ all-languages = [ "lapce-core/lang-markdown", "lapce-core/lang-python", "lapce-core/lang-rust", + "lapce-core/lang-slint", "lapce-core/lang-toml", "lapce-core/lang-yaml", ] diff --git a/lapce-core/Cargo.toml b/lapce-core/Cargo.toml index 259543e7ac..e6f9bbf7b0 100644 --- a/lapce-core/Cargo.toml +++ b/lapce-core/Cargo.toml @@ -40,6 +40,7 @@ tree-sitter-json = { git = "https://github.com/tree-sitter/tree-sitter-json.git" tree-sitter-md = { git = "https://github.com/MDeiml/tree-sitter-markdown.git", rev = "272e080bca0efd19a06a7f4252d746417224959e", optional = true } tree-sitter-python = { version = "0.20.4", optional = true } tree-sitter-rust = { version = "0.20.4", optional = true } +tree-sitter-slint = { git = "https://github.com/jrmoulton/tree-sitter-slint.git", rev = "00c8a2d3645766f68c0d0460086c0a994e5b0d85", optional = true } tree-sitter-toml = { version = "0.20.0", optional = true } tree-sitter-yaml = { git = "https://github.com/panekj/tree-sitter-yaml", rev = "80c8d76847f03e772c5c524cf29bafb56858a8d1", optional = true } @@ -57,6 +58,7 @@ lang-json = ["dep:tree-sitter-json"] lang-markdown = ["dep:tree-sitter-md"] lang-python = ["dep:tree-sitter-python"] lang-rust = ["dep:tree-sitter-rust"] +lang-slint = ["dep:tree-sitter-slint"] lang-toml = ["dep:tree-sitter-toml"] lang-yaml = ["dep:tree-sitter-yaml"] diff --git a/lapce-core/queries/slint/highlights.scm b/lapce-core/queries/slint/highlights.scm new file mode 100644 index 0000000000..d41d49cf3d --- /dev/null +++ b/lapce-core/queries/slint/highlights.scm @@ -0,0 +1,155 @@ + +(identifier) @variable +(type_identifier) @type +(comment) @comment +(int_literal) @number +(float_literal) @float +(string_literal) @string +(function_identifier) @function +[ +(image_macro) +(children_macro) +(radial_grad_macro) +(linear_grad_macro) +] @function.macro +(call_expression + function: (identifier) @function.call) +(call_expression + function: (field_expression + field: (identifier) @function.call)) +(vis) @include +(units) @type +(array_literal + (identifier) @type) +(transition_statement state: (identifier) @field) +(state_expression state: (identifier) @field) +(struct_block_definition + (identifier) @field) + +; (state_identifier) @field + +[ +"in" +"for" +] @repeat + +"@" @keyword + +[ +"import" +"from" +] @include + +[ +"if" +"else" +] @conditional + +[ +"root" +"parent" +"duration" +"easing" +] @variable.builtin + +[ +"true" +"false" +] @boolean + + +[ +"struct" +"property" +"callback" +"in" +"animate" +"states" +"when" +"out" +"transitions" +"global" +] @keyword + +[ +"black" +"transparent" +"blue" +"ease" +"ease_in" +"ease-in" +"ease_in_out" +"ease-in-out" +"ease_out" +"ease-out" +"end" +"green" +"red" +"red" +"start" +"yellow" +"white" +"gray" +] @constant.builtin + + +; Punctuation +[ +"," +"." +";" +":" +] @punctuation.delimiter + +; Brackets +[ +"(" +")" +"[" +"]" +"{" +"}" +] @punctuation.bracket + +(define_property ["<" ">"] @punctuation.bracket) + +[ +"angle" +"bool" +"brush" +"color" +"float" +"image" +"int" +"length" +"percent" +"physical-length" +"physical_length" +"string" +] @type.builtin + +[ + ":=" + "<=>" + "!" + "-" + "+" + "*" + "/" + "&&" + "||" + ">" + "<" + ">=" + "<=" + "=" + ":" + "+=" + "-=" + "*=" + "/=" + "?" + "=>" + ] @operator + +(ternary_expression [":" "?"] @conditional) diff --git a/lapce-core/queries/slint/indents.scm b/lapce-core/queries/slint/indents.scm new file mode 100644 index 0000000000..42627a7c1b --- /dev/null +++ b/lapce-core/queries/slint/indents.scm @@ -0,0 +1,16 @@ + + +[ +(comp_body) +(state_statement) +(transition_statement) +(handler_body) +(consequence_body) +(global_single) +] @indent + +"}" @indent_end + +(comment) @auto + +(string_literal) @auto diff --git a/lapce-core/queries/slint/locals.scm b/lapce-core/queries/slint/locals.scm new file mode 100644 index 0000000000..6c8bc89ce2 --- /dev/null +++ b/lapce-core/queries/slint/locals.scm @@ -0,0 +1,2 @@ + +(component_item) @local.scope diff --git a/lapce-core/src/language.rs b/lapce-core/src/language.rs index 2cdc4c75a8..f92e25dcf6 100644 --- a/lapce-core/src/language.rs +++ b/lapce-core/src/language.rs @@ -69,19 +69,19 @@ macro_rules! comment_properties { #[derive(Eq, PartialEq, Hash, Clone, Copy, Debug, PartialOrd, Ord, Default)] pub struct SyntaxProperties { - /// An extra check to make sure that the array elements are in the correct order. + /// An extra check to make sure that the array elements are in the correct order. /// If this id does not match the enum value, a panic will happen with a debug assertion message. id: LapceLanguage, /// All tokens that can be used for comments in language comment: CommentProperties, - /// The indent unit. + /// The indent unit. /// " " for bash, " " for rust, for example. indent: &'static str, - /// Filenames that belong to this language + /// Filenames that belong to this language /// `["Dockerfile"]` for Dockerfile, `[".editorconfig"]` for EditorConfig files: &'static [&'static str], - /// File name extensions to determine the language. + /// File name extensions to determine the language. /// `["py"]` for python, `["rs"]` for rust, for example. extensions: &'static [&'static str], /// Tree-sitter properties @@ -90,7 +90,7 @@ pub struct SyntaxProperties { #[derive(Eq, PartialEq, Hash, Clone, Copy, Debug, PartialOrd, Ord)] struct TreeSitterProperties { - /// This is the factory function defined in the tree-sitter crate that creates the language parser. + /// This is the factory function defined in the tree-sitter crate that creates the language parser. /// For most languages, it is `tree_sitter_$crate::language`. language: Option tree_sitter::Language>, /// the grammar name that's in the grammars folder @@ -246,6 +246,8 @@ pub enum LapceLanguage { Scss, #[strum(message = "Shell (POSIX)")] Sh, + #[strum(message = "Slint")] + Slint, #[strum(message = "SQL")] Sql, #[strum(message = "Svelte")] @@ -1302,6 +1304,26 @@ const LANGUAGES: &[SyntaxProperties] = &[ sticky_headers: &[], }), }, + SyntaxProperties { + id: LapceLanguage::Slint, + + indent: " ", + files: &[], + extensions: &["slint"], + + comment: comment_properties!("//"), + + #[cfg(feature = "lang-slint")] + tree_sitter: Some(TreeSitterProperties { + language: Some(tree_sitter_slint::language), + grammar: Some("slint"), + query: Some("slint"), + code_lens: (DEFAULT_CODE_LENS_LIST, DEFAULT_CODE_LENS_IGNORE_LIST), + sticky_headers: &[], + }), + #[cfg(not(feature = "lang-slint"))] + tree_sitter: None, + }, SyntaxProperties { id: LapceLanguage::Sql, diff --git a/lapce-proxy/src/buffer.rs b/lapce-proxy/src/buffer.rs index 9c2ca90708..ca6d1a9e84 100644 --- a/lapce-proxy/src/buffer.rs +++ b/lapce-proxy/src/buffer.rs @@ -258,6 +258,7 @@ pub fn language_id_from_path(path: &Path) -> Option<&'static str> { "scss" | "sass" => "scss", "sc" | "scala" => "scala", "sh" | "bash" | "zsh" => "shellscript", + "slint" => "slint", "sql" => "sql", "swift" => "swift", "svelte" => "svelte", From 47b13d0e41f8d9fd58cc5de1486bc1a0b056acdd Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Sun, 3 Mar 2024 00:31:07 +1300 Subject: [PATCH 2/2] Update slint --- lapce-core/Cargo.toml | 2 +- lapce-core/queries/slint/folds.scm | 11 + lapce-core/queries/slint/highlights.scm | 364 +++++++++++++++--------- lapce-core/queries/slint/indents.scm | 34 ++- lapce-core/queries/slint/injections.scm | 2 + lapce-core/queries/slint/locals.scm | 117 +++++++- 6 files changed, 387 insertions(+), 143 deletions(-) create mode 100644 lapce-core/queries/slint/folds.scm create mode 100644 lapce-core/queries/slint/injections.scm diff --git a/lapce-core/Cargo.toml b/lapce-core/Cargo.toml index e6f9bbf7b0..f76eb41e50 100644 --- a/lapce-core/Cargo.toml +++ b/lapce-core/Cargo.toml @@ -40,7 +40,7 @@ tree-sitter-json = { git = "https://github.com/tree-sitter/tree-sitter-json.git" tree-sitter-md = { git = "https://github.com/MDeiml/tree-sitter-markdown.git", rev = "272e080bca0efd19a06a7f4252d746417224959e", optional = true } tree-sitter-python = { version = "0.20.4", optional = true } tree-sitter-rust = { version = "0.20.4", optional = true } -tree-sitter-slint = { git = "https://github.com/jrmoulton/tree-sitter-slint.git", rev = "00c8a2d3645766f68c0d0460086c0a994e5b0d85", optional = true } +tree-sitter-slint = { git = "https://github.com/slint-ui/tree-sitter-slint.git", optional = true } tree-sitter-toml = { version = "0.20.0", optional = true } tree-sitter-yaml = { git = "https://github.com/panekj/tree-sitter-yaml", rev = "80c8d76847f03e772c5c524cf29bafb56858a8d1", optional = true } diff --git a/lapce-core/queries/slint/folds.scm b/lapce-core/queries/slint/folds.scm new file mode 100644 index 0000000000..4c5b1307ab --- /dev/null +++ b/lapce-core/queries/slint/folds.scm @@ -0,0 +1,11 @@ +[ + (anon_struct_block) + (block) + (callback_event) + (component) + (enum_block) + (function_definition) + (global_definition) + (imperative_block) + (struct_block) +] @fold diff --git a/lapce-core/queries/slint/highlights.scm b/lapce-core/queries/slint/highlights.scm index d41d49cf3d..2e6d5997e6 100644 --- a/lapce-core/queries/slint/highlights.scm +++ b/lapce-core/queries/slint/highlights.scm @@ -1,155 +1,261 @@ +(comment) @comment @spell -(identifier) @variable -(type_identifier) @type -(comment) @comment -(int_literal) @number -(float_literal) @float -(string_literal) @string -(function_identifier) @function -[ -(image_macro) -(children_macro) -(radial_grad_macro) -(linear_grad_macro) -] @function.macro -(call_expression - function: (identifier) @function.call) -(call_expression - function: (field_expression - field: (identifier) @function.call)) -(vis) @include -(units) @type -(array_literal - (identifier) @type) -(transition_statement state: (identifier) @field) -(state_expression state: (identifier) @field) -(struct_block_definition - (identifier) @field) - -; (state_identifier) @field +; Different types: +(string_value) @string @spell -[ -"in" -"for" -] @repeat +(escape_sequence) @string.escape -"@" @keyword +(color_value) @constant [ -"import" -"from" -] @include + (children_identifier) + (easing_kind_identifier) +] @constant.builtin -[ -"if" -"else" -] @conditional +(bool_value) @boolean [ -"root" -"parent" -"duration" -"easing" -] @variable.builtin + (int_value) + (physical_length_value) +] @number [ -"true" -"false" -] @boolean + (angle_value) + (duration_value) + (float_value) + (length_value) + (percent_value) + (relative_font_size_value) +] @number.float +(purity) @type.qualifier -[ -"struct" -"property" -"callback" -"in" -"animate" -"states" -"when" -"out" -"transitions" -"global" -] @keyword +(function_visibility) @type.qualifier + +(property_visibility) @type.qualifier + +(builtin_type_identifier) @type.builtin + +(reference_identifier) @variable.builtin + +(type + [ + (type_list) + (user_type_identifier) + (anon_struct_block) + ]) @type + +(user_type_identifier) @type + +; Functions and callbacks +(argument) @variable.parameter + +(function_call + name: (_) @function.call) + +; definitions +(callback + name: (_) @function) + +(callback_alias + name: (_) @function) + +(callback_event + name: (simple_identifier) @function.call) + +(component + id: (_) @variable) + +(enum_definition + name: (_) @type) + +(function_definition + name: (_) @function) + +(struct_definition + name: (_) @type) + +(typed_identifier + type: (_) @type) + +; Operators +(binary_expression + op: (_) @operator) + +(unary_expression + op: (_) @operator) [ -"black" -"transparent" -"blue" -"ease" -"ease_in" -"ease-in" -"ease_in_out" -"ease-in-out" -"ease_out" -"ease-out" -"end" -"green" -"red" -"red" -"start" -"yellow" -"white" -"gray" -] @constant.builtin + (comparison_operator) + (mult_prec_operator) + (add_prec_operator) + (unary_prec_operator) + (assignment_prec_operator) +] @operator +[ + ":=" + "=>" + "->" + "<=>" +] @operator ; Punctuation [ -"," -"." -";" -":" + ";" + "." + "," + ":" ] @punctuation.delimiter -; Brackets [ -"(" -")" -"[" -"]" -"{" -"}" + "(" + ")" + "[" + "]" + "{" + "}" ] @punctuation.bracket -(define_property ["<" ">"] @punctuation.bracket) +(property + [ + "<" + ">" + ] @punctuation.bracket) -[ -"angle" -"bool" -"brush" -"color" -"float" -"image" -"int" -"length" -"percent" -"physical-length" -"physical_length" -"string" -] @type.builtin +; Properties, Variables and Constants: +(component + id: (simple_identifier) @constant) + +(property + name: (simple_identifier) @property) + +(binding_alias + name: (simple_identifier) @property) + +(binding + name: (simple_identifier) @property) + +(struct_block + (simple_identifier) @variable.member) + +(anon_struct_block + (simple_identifier) @variable.member) +(property_assignment + property: (simple_identifier) @property) + +(states_definition + name: (simple_identifier) @variable) + +(callback + name: (simple_identifier) @variable) + +(typed_identifier + name: (_) @variable) + +(simple_indexed_identifier + name: (simple_identifier) @variable + index_var: (simple_identifier) @variable) + +(expression + (simple_identifier) @variable) + +(member_access + member: + (expression + (simple_identifier) @property)) + +(states_definition + name: (simple_identifier) @constant) + +; Attributes: [ - ":=" - "<=>" - "!" - "-" - "+" - "*" - "/" - "&&" - "||" - ">" - "<" - ">=" - "<=" - "=" - ":" - "+=" - "-=" - "*=" - "/=" - "?" - "=>" - ] @operator - -(ternary_expression [":" "?"] @conditional) + (linear_gradient_identifier) + (radial_gradient_identifier) + (radial_gradient_kind) +] @attribute + +(image_call + "@image-url" @attribute) + +(tr + "@tr" @attribute) + +; Keywords: +(animate_option_identifier) @keyword + +(export) @keyword + +(if_statement + "if" @keyword.conditional) + +(if_expr + [ + "if" + "else" + ] @keyword.conditional) + +(ternary_expression + [ + "?" + ":" + ] @keyword.conditional.ternary) + +(animate_statement + "animate" @keyword) + +(callback + "callback" @keyword) + +(component_definition + [ + "component" + "inherits" + ] @keyword) + +(enum_definition + "enum" @keyword) + +(for_loop + [ + "for" + "in" + ] @keyword.repeat) + +(function_definition + "function" @keyword.function) + +(global_definition + "global" @keyword) + +(imperative_block + "return" @keyword.return) + +(import_statement + [ + "import" + "from" + ] @keyword.import) + +(import_type + "as" @keyword.import) + +(property + "property" @keyword) + +(states_definition + [ + "states" + "when" + ] @keyword) + +(struct_definition + "struct" @keyword) + +(transitions_definition + [ + "transitions" + "in" + "out" + ] @keyword) diff --git a/lapce-core/queries/slint/indents.scm b/lapce-core/queries/slint/indents.scm index 42627a7c1b..d6bdeacde4 100644 --- a/lapce-core/queries/slint/indents.scm +++ b/lapce-core/queries/slint/indents.scm @@ -1,16 +1,26 @@ - - [ -(comp_body) -(state_statement) -(transition_statement) -(handler_body) -(consequence_body) -(global_single) -] @indent + (arguments) + (block) + (enum_block) + (global_block) + (imperative_block) + (struct_block) + (typed_identifier) +] @indent.begin -"}" @indent_end +([ + (block) + (enum_block) + (global_block) + (imperative_block) + (struct_block) +] + "}" @indent.end) -(comment) @auto +([ + (arguments) + (typed_identifier) +] + ")" @indent.end) -(string_literal) @auto +(string_value) @indent.auto diff --git a/lapce-core/queries/slint/injections.scm b/lapce-core/queries/slint/injections.scm new file mode 100644 index 0000000000..2f0e58eb64 --- /dev/null +++ b/lapce-core/queries/slint/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/lapce-core/queries/slint/locals.scm b/lapce-core/queries/slint/locals.scm index 6c8bc89ce2..2d256b7ac2 100644 --- a/lapce-core/queries/slint/locals.scm +++ b/lapce-core/queries/slint/locals.scm @@ -1,2 +1,117 @@ +[ + (anon_struct_block) + (block) + (callback_event) + (component) + (enum_block) + (function_definition) + (global_definition) + (imperative_block) + (struct_block) +] @local.scope -(component_item) @local.scope +(anon_struct_block + (_) @local.definition.field) + +(argument) @local.definition.var + +(callback + name: (_) @local.definition.member) + +(component_definition + name: (_) @local.definition.type) + +(enum_definition + name: (_) @local.definition.type) + +(enum_block + (_) @local.definition.field) + +(function_definition + name: (_) @local.definition.function) + +(global_definition + name: (_) @local.definition.type) + +(import_type + import_name: (_) + !local_name) @local.definition.import + +(import_type + import_name: (_) + local_name: (_) @local.definition.import) + +(property + name: (_) @local.definition.field) + +(struct_block + (_) @local.definition.field) + +(struct_definition + name: (_) @local.definition.type) + +(typed_identifier + name: (_) @local.definition.var) + +(argument + (_) @local.reference) + +(binary_expression + left: (_) @local.reference) + +(binary_expression + right: (_) @local.reference) + +(callback_event + name: (_) @local.reference) + +(component + type: (_) @local.reference + (#set! reference.kind "type")) + +(component_definition + base_type: (_) @local.reference + (#set! reference.kind "type")) + +(function_call + name: (_) @local.reference) + +(index_op + index: (_) @local.reference) + +(index_op + left: (_) @local.reference) + +(member_access + base: (_) @local.reference) + +(member_access + member: (_) @local.reference) + +(parens_op + left: (_) @local.reference) + +(property + type: (_) @local.reference + (#set! reference.kind "type")) + +(property_assignment + property: (_) @local.reference + (#set! reference.kind "field")) + +(property_assignment + value: (_) @local.reference) + +(struct_block + (_) @local.reference + (#set! reference.kind "type")) + +(tr + percent: (_) @local.reference) + +(typed_identifier + type: (_) @local.reference + (#set! reference.kind "type")) + +(unary_expression + left: (_) @local.reference)