luckasRanarison / tailwind-tools.nvim

An unofficial Tailwind CSS integration and tooling for Neovim
https://dotfyle.com/plugins/luckasRanarison/tailwind-tools.nvim
MIT License
348 stars 15 forks source link

Leptos / Rust support #25

Closed loganbnielsen closed 1 month ago

loganbnielsen commented 4 months ago

The plugin basically works with any language as long it has a treesitter parser and a class query. You can check the currently available queries and supported filetypes here, feel free to request other languages support.

For some reason I'm having a hard time getting this to work with Leptos which is Rust front end framework. I'm not sure if this is expected or if I'm just doing the setup wrong but wanted to raise that it'd be very cool if this supported leptos. view!{} macros might be what make this difficult to achieve so no worries if it's too much effort.

Thanks for sharing this btw, really neat plugin :smile:

luckasRanarison commented 4 months ago

I don't think we can support that one through treesitter, because expressions inside macro are parsed as normal rust expressions and don't provide useful information.

Example code ```rust use leptos::*; use leptos_meta::*; #[component] fn App(cx: Scope) -> impl IntoView { let (count, set_count) = create_signal(cx, 0); provide_meta_context(cx); view! { cx, } } fn main() { leptos::mount_to_body(|cx| view!{ cx, }) } ```
Parse tree ``` (use_declaration) ; [1:1 - 14] argument: (use_wildcard) ; [1:5 - 13] (identifier) ; [1:5 - 10] (use_declaration) ; [2:1 - 19] argument: (use_wildcard) ; [2:5 - 18] (identifier) ; [2:5 - 15] (attribute_item) ; [4:1 - 12] (attribute) ; [4:3 - 11] (identifier) ; [4:3 - 11] (function_item) ; [5:1 - 21:1] name: (identifier) ; [5:4 - 6] parameters: (parameters) ; [5:7 - 17] (parameter) ; [5:8 - 16] pattern: (identifier) ; [5:8 - 9] type: (type_identifier) ; [5:12 - 16] return_type: (abstract_type) ; [5:22 - 34] trait: (type_identifier) ; [5:27 - 34] body: (block) ; [5:36 - 21:1] (let_declaration) ; [6:5 - 50] pattern: (tuple_pattern) ; [6:9 - 26] (identifier) ; [6:10 - 14] (identifier) ; [6:17 - 25] value: (call_expression) ; [6:30 - 49] function: (identifier) ; [6:30 - 42] arguments: (arguments) ; [6:43 - 49] (identifier) ; [6:44 - 45] (integer_literal) ; [6:48 - 48] (expression_statement) ; [7:5 - 29] (call_expression) ; [7:5 - 28] function: (identifier) ; [7:5 - 24] arguments: (arguments) ; [7:25 - 28] (identifier) ; [7:26 - 27] (macro_invocation) ; [9:5 - 20:5] macro: (identifier) ; [9:5 - 8] (token_tree) ; [9:11 - 20:5] (expression_statement) ; [9:11 - 20:5] (block) ; [9:11 - 20:5] (ERROR) ; [9:13 - 10:19] (identifier) ; [9:13 - 14] (identifier) ; [10:10 - 19] (assignment_expression) ; [10:21 - 19:16] left: (assignment_expression) ; [10:21 - 13:28] left: (assignment_expression) ; [10:21 - 31] left: (identifier) ; [10:21 - 22] right: (string_literal) ; [10:24 - 31] (ERROR) ; [10:33 - 36] (identifier) ; [10:33 - 36] right: (binary_expression) ; [10:38 - 13:28] left: (binary_expression) ; [10:38 - 57] left: (string_literal) ; [10:38 - 56] right: (identifier) ; [10:58 - 57] (ERROR) ; [11:9 - 12:25] (identifier) ; [11:10 - 15] (identifier) ; [12:13 - 17] (identifier) ; [12:20 - 20] (integer_literal) ; [12:22 - 22] (identifier) ; [12:24 - 25] right: (binary_expression) ; [12:26 - 13:28] left: (binary_expression) ; [12:26 - 13:25] left: (binary_expression) ; [12:26 - 106] left: (binary_expression) ; [12:26 - 102] left: (binary_expression) ; [12:26 - 98] left: (binary_expression) ; [12:26 - 71] left: (binary_expression) ; [12:26 - 53] left: (binary_expression) ; [12:26 - 40] left: (binary_expression) ; [12:26 - 36] left: (unary_expression) ; [12:26 - 29] (float_literal) ; [12:27 - 29] (ERROR) ; [12:31 - 32] (identifier) ; [12:31 - 32] right: (identifier) ; [12:34 - 36] right: (integer_literal) ; [12:38 - 40] (ERROR) ; [12:42 - 49] (identifier) ; [12:42 - 46] (identifier) ; [12:48 - 49] right: (identifier) ; [12:51 - 53] (ERROR) ; [12:55 - 64] (integer_literal) ; [12:55 - 57] (identifier) ; [12:59 - 63] right: (identifier) ; [12:65 - 71] (ERROR) ; [12:73 - 94] (identifier) ; [12:73 - 76] (identifier) ; [12:78 - 82] (identifier) ; [12:84 - 87] (identifier) ; [12:89 - 93] right: (identifier) ; [12:95 - 98] right: (identifier) ; [12:100 - 102] right: (integer_literal) ; [12:104 - 106] (ERROR) ; [12:108 - 117] (identifier) ; [12:108 - 112] (identifier) ; [12:114 - 117] (ERROR) ; [12:119 - 13:18] (identifier) ; [12:119 - 123] (identifier) ; [13:13 - 17] right: (identifier) ; [13:19 - 25] right: (identifier) ; [13:27 - 28] right: (closure_expression) ; [13:30 - 19:16] parameters: (closure_parameters) ; [13:35 - 36] body: (assignment_expression) ; [13:38 - 19:16] left: (binary_expression) ; [13:38 - 53] left: (binary_expression) ; [13:38 - 48] left: (call_expression) ; [13:38 - 44] function: (identifier) ; [13:38 - 42] arguments: (arguments) ; [13:43 - 44] right: (integer_literal) ; [13:48 - 48] right: (integer_literal) ; [13:53 - 53] (ERROR) ; [14:13 - 20] (identifier) ; [14:13 - 14] (identifier) ; [14:16 - 20] right: (closure_expression) ; [14:22 - 19:16] parameters: (closure_parameters) ; [14:27 - 29] body: (binary_expression) ; [14:31 - 19:16] left: (binary_expression) ; [14:31 - 18:38] left: (block) ; [14:31 - 16:13] (expression_statement) ; [15:17 - 46] (call_expression) ; [15:17 - 45] function: (field_expression) ; [15:17 - 32] value: (identifier) ; [15:17 - 25] field: (field_identifier) ; [15:27 - 32] arguments: (arguments) ; [15:33 - 45] (closure_expression) ; [15:34 - 44] parameters: (closure_parameters) ; [15:34 - 36] (identifier) ; [15:35 - 35] body: (compound_assignment_expr) ; [15:38 - 44] left: (unary_expression) ; [15:38 - 39] (identifier) ; [15:39 - 39] right: (integer_literal) ; [15:44 - 44] (ERROR) ; [18:9 - 20] (string_literal) ; [18:9 - 20] right: (block) ; [18:22 - 38] (closure_expression) ; [18:23 - 37] parameters: (closure_parameters) ; [18:28 - 29] body: (call_expression) ; [18:31 - 37] function: (identifier) ; [18:31 - 35] arguments: (arguments) ; [18:36 - 37] (ERROR) ; [19:10 - 11] (outer_doc_comment) ; [19:10 - 11] right: (identifier) ; [19:12 - 16] (ERROR) ; [19:17 - 17] (identifier) ; [9:13 - 14] (identifier) ; [10:10 - 19] (identifier) ; [10:21 - 22] (string_literal) ; [10:24 - 31] (identifier) ; [10:33 - 36] (string_literal) ; [10:38 - 56] (identifier) ; [11:10 - 15] (identifier) ; [12:13 - 17] (string_literal) ; [12:19 - 124] (identifier) ; [13:13 - 17] (identifier) ; [13:19 - 25] (identifier) ; [13:27 - 28] (identifier) ; [13:30 - 33] (identifier) ; [13:38 - 42] (token_tree) ; [13:43 - 44] (integer_literal) ; [13:48 - 48] (integer_literal) ; [13:53 - 53] (identifier) ; [14:13 - 14] (identifier) ; [14:16 - 20] (identifier) ; [14:22 - 25] (token_tree) ; [14:31 - 16:13] (identifier) ; [15:17 - 25] (identifier) ; [15:27 - 32] (token_tree) ; [15:33 - 45] (identifier) ; [15:35 - 35] (identifier) ; [15:39 - 39] (integer_literal) ; [15:44 - 44] (string_literal) ; [18:9 - 20] (token_tree) ; [18:22 - 38] (identifier) ; [18:23 - 26] (identifier) ; [18:31 - 35] (token_tree) ; [18:36 - 37] (identifier) ; [19:11 - 16] (function_item) ; [23:1 - 25:1] name: (identifier) ; [23:4 - 7] parameters: (parameters) ; [23:8 - 9] body: (block) ; [23:11 - 25:1] (call_expression) ; [24:5 - 52] function: (scoped_identifier) ; [24:5 - 25] path: (identifier) ; [24:5 - 10] name: (identifier) ; [24:13 - 25] arguments: (arguments) ; [24:26 - 52] (closure_expression) ; [24:27 - 51] parameters: (closure_parameters) ; [24:27 - 30] (identifier) ; [24:28 - 29] body: (macro_invocation) ; [24:32 - 51] macro: (identifier) ; [24:32 - 35] (token_tree) ; [24:38 - 51] (expression_statement) ; [24:38 - 51] (block) ; [24:38 - 51] (ERROR) ; [24:40 - 44] (identifier) ; [24:40 - 41] (identifier) ; [24:45 - 47] (ERROR) ; [24:48 - 49] (identifier) ; [24:40 - 41] (identifier) ; [24:45 - 47] ```

To solve this maybe we could add a regex solution as a fallback.

luckasRanarison commented 1 month ago

Leeptos support has been added in #31.

highjeans commented 1 month ago

@luckasRanarison How do I add the server completions for rust files for lepton? I am currently working on a leptos project and below is my config for your plugin:

return {
  "luckasRanarison/tailwind-tools.nvim",
  name = "tailwind-tools",
  build = ":UpdateRemotePlugins",
  dependencies = {
    "nvim-treesitter/nvim-treesitter",
    "neovim/nvim-lspconfig",
  },
  opts = {
      server = {
          settings = {
              includeLanguages = {
                  rust = "html"
              }
          }
      },
      extension = {
          patterns = {
              rust = { "class=[\"']([^\"']+)[\"']" },
          }
      }
  } -- your configuration
}

Running :LspInfo shows that no language servers are binded to the rust file. My config for LSP is from https://github.com/alvarojsino813/nvim-config-guide?tab=readme-ov-file.

Thanks for any/all help!

luckasRanarison commented 1 month ago

@highjeans Rust is now supported by default from the server and the plugin so you don't need to add additional server setting or luapattern extension, it should work out of the box.

highjeans commented 1 month ago

@luckasRanarison Thank you so much!