joaotavora / eglot

A client for Language Server Protocol servers
GNU General Public License v3.0
2.21k stars 203 forks source link

tailwindcss language server support #1403

Open illia-danko opened 1 month ago

illia-danko commented 1 month ago

Hello @joaotavora. It would be really nice to have TailwindCSS be a part of multi language support (I have failed to make an standalone client either). It would unleash frond-end developing as TailwindCSS framework becomes very popular nowadays.

The server could be installed as: npm install -g @tailwindcss/language-server . See https://www.npmjs.com/package/@tailwindcss/language-server

Theoretically it should simply work by setting it as:

(add-to-list 'eglot-server-programs
             '((web-mode :language-id "html") . ("tailwindcss-language-server" "--stdio")))

But unfortunately it doesn't:

[internal] Fri May 24 20:34:51 2024:
(:message "Running language server: tailwindcss-language-server --stdio")
[client-request] (id:1) Fri May 24 20:34:51 2024:
(:jsonrpc "2.0" :id 1 :method "initialize" :params
          (:processId 274748 :rootPath "/home/idanko/github.com/illia-danko/slivce/" :rootUri "file:///home/idanko/github.com/illia-danko/slivce" :initializationOptions #s(hash-table size 1 test eql rehash-size 1.5 rehash-threshold 0.8125 data
                                                                                                                                                                                       ())
                      :capabilities
                      (:workspace
                       (:applyEdit t :executeCommand
                                   (:dynamicRegistration :json-false)
                                   :workspaceEdit
                                   (:documentChanges t)
                                   :didChangeWatchedFiles
                                   (:dynamicRegistration t)
                                   :symbol
                                   (:dynamicRegistration :json-false)
                                   :configuration t :workspaceFolders t)
                       :textDocument
                       (:synchronization
                        (:dynamicRegistration :json-false :willSave t :willSaveWaitUntil t :didSave t)
                        :completion
                        (:dynamicRegistration :json-false :completionItem
                                              (:snippetSupport t :deprecatedSupport t :resolveSupport
                                                               (:properties
                                                                ["documentation" "details" "additionalTextEdits"])
                                                               :tagSupport
                                                               (:valueSet
                                                                [1]))
                                              :contextSupport t)
                        :hover
                        (:dynamicRegistration :json-false :contentFormat
                                              ["markdown" "plaintext"])
                        :signatureHelp
                        (:dynamicRegistration :json-false :signatureInformation
                                              (:parameterInformation
                                               (:labelOffsetSupport t)
                                               :activeParameterSupport t))
                        :references
                        (:dynamicRegistration :json-false)
                        :definition
                        (:dynamicRegistration :json-false :linkSupport t)
                        :declaration
                        (:dynamicRegistration :json-false :linkSupport t)
                        :implementation
                        (:dynamicRegistration :json-false :linkSupport t)
                        :typeDefinition
                        (:dynamicRegistration :json-false :linkSupport t)
                        :documentSymbol
                        (:dynamicRegistration :json-false :hierarchicalDocumentSymbolSupport t :symbolKind
                                              (:valueSet
                                               [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26]))
                        :documentHighlight
                        (:dynamicRegistration :json-false)
                        :codeAction
                        (:dynamicRegistration :json-false :codeActionLiteralSupport
                                              (:codeActionKind
                                               (:valueSet
                                                ["quickfix" "refactor" "refactor.extract" "refactor.inline" "refactor.rewrite" "source" "source.organizeImports"]))
                                              :isPreferredSupport t)
                        :formatting
                        (:dynamicRegistration :json-false)
                        :rangeFormatting
                        (:dynamicRegistration :json-false)
                        :rename
                        (:dynamicRegistration :json-false)
                        :inlayHint
                        (:dynamicRegistration :json-false)
                        :publishDiagnostics
                        (:relatedInformation :json-false :codeDescriptionSupport :json-false :tagSupport
                                             (:valueSet
                                              [1 2])))
                       :window
                       (:workDoneProgress t)
                       :general
                       (:positionEncodings
                        ["utf-32" "utf-8" "utf-16"])
                       :experimental #s(hash-table size 1 test eql rehash-size 1.5 rehash-threshold 0.8125 data
                                                   ()))
                      :workspaceFolders
                      [(:uri "file:///home/idanko/github.com/illia-danko/slivce" :name "~/github.com/illia-danko/slivce/")]))
[server-reply] (id:1) Fri May 24 20:34:51 2024:
(:jsonrpc "2.0" :id 1 :result
          (:capabilities
           (:textDocumentSync 1 :hoverProvider t :colorProvider t :codeActionProvider t :documentLinkProvider nil :completionProvider
                              (:resolveProvider t :triggerCharacters
                                                ["\"" "'" "`" " " "." "(" "[" "!" "/" ":"]))))
[client-notification] Fri May 24 20:34:51 2024:
(:jsonrpc "2.0" :method "initialized" :params #s(hash-table size 1 test eql rehash-size 1.5 rehash-threshold 0.8125 data
                                                            ()))
[client-notification] Fri May 24 20:34:51 2024:
(:jsonrpc "2.0" :method "textDocument/didOpen" :params
          (:textDocument
           (:uri "file:///home/idanko/github.com/illia-danko/slivce/lib/slivce_web/components/layouts/root.html.heex" :version 0 :languageId "html" :text "<html>\n  <body class=\"\"></body>\n</html>\n")))
[client-notification] Fri May 24 20:34:51 2024:
(:jsonrpc "2.0" :method "workspace/didChangeConfiguration" :params
          (:settings #s(hash-table size 1 test eql rehash-size 1.5 rehash-threshold 0.8125 data
                                   ())))
[server-request] (id:0) Fri May 24 20:34:51 2024:
(:jsonrpc "2.0" :id 0 :method "workspace/configuration" :params
          (:items
           [(:section "editor")]))
[client-reply] (id:0) Fri May 24 20:34:51 2024:
(:jsonrpc "2.0" :id 0 :result
          [nil])
[server-request] (id:1) Fri May 24 20:34:51 2024:
(:jsonrpc "2.0" :id 1 :method "workspace/configuration" :params
          (:items
           [(:section "tailwindCSS")]))
[client-reply] (id:1) Fri May 24 20:34:51 2024:
(:jsonrpc "2.0" :id 1 :result
          [nil])
[server-notification] Fri May 24 20:34:51 2024:
(:jsonrpc "2.0" :method "window/logMessage" :params
          (:type 4 :message "[Global] Creating projects: [{\"folder\":\"/home/idanko/github.com/illia-danko/slivce\",\"configPath\":\"/home/idanko/github.com/illia-danko/slivce/assets/tailwind.config.js\",\"isUserConfigured\":false,\"documentSelector\":[{\"pattern\":\"/home/idanko/github.com/illia-danko/slivce/assets/tailwind.config.js\",\"priority\":0},{\"pattern\":\"/home/idanko/github.com/illia-danko/slivce/assets/**\",\"priority\":3},{\"pattern\":\"/home/idanko/github.com/illia-danko/slivce/**\",\"priority\":4}]}]"))
[server-request] (id:2) Fri May 24 20:34:51 2024:
(:jsonrpc "2.0" :id 2 :method "client/registerCapability" :params
          (:registrations
           [(:id "a2530c16-0eab-4c8c-99f6-6ba76818356b" :method "workspace/didChangeWatchedFiles" :registerOptions
                 (:watchers
                  [(:globPattern "**/{tailwind,tailwind.config,tailwind.*.config,tailwind.config.*}.{js,cjs,ts,mjs}")
                   (:globPattern "**/{package-lock.json,yarn.lock,pnpm-lock.yaml}")
                   (:globPattern "**/*.{css,scss,sass,less,pcss}")]))]))
[client-reply] (id:2) ERROR Fri May 24 20:34:51 2024:
(:jsonrpc "2.0" :id 2 :error
          (:code -32603 :message "Internal error"))
[server-notification] Fri May 24 20:34:51 2024:
(:jsonrpc "2.0" :method "window/logMessage" :params
          (:type 3 :message "Registering request handler for workspace/didChangeWatchedFiles failed."))
[server-notification] Fri May 24 20:34:52 2024:
(:jsonrpc "2.0" :method "window/logMessage" :params
          (:type 1 :message "Unhandled exception: Internal error\nError: Internal error\n    at Ae (/nix/store/00gakawfrjkbbivcpw274qy7r9m2j02h-tailwindcss-language-server-0.0.14/lib/node_modules/tailwindcss-intellisense/bin/tailwindcss-language-server:139:236)\n    at X (/nix/store/00gakawfrjkbbivcpw274qy7r9m2j02h-tailwindcss-language-server-0.0.14/lib/node_modules/tailwindcss-intellisense/bin/tailwindcss-language-server:138:6870)\n    at Immediate.<anonymous> (/nix/store/00gakawfrjkbbivcpw274qy7r9m2j02h-tailwindcss-language-server-0.0.14/lib/node_modules/tailwindcss-intellisense/bin/tailwindcss-language-server:138:6719)\n    at process.processImmediate (node:internal/timers:476:21)"))
[client-request] (id:2) Fri May 24 20:34:52 2024:
(:jsonrpc "2.0" :id 2 :method "textDocument/hover" :params
          (:textDocument
           (:uri "file:///home/idanko/github.com/illia-danko/slivce/lib/slivce_web/components/layouts/root.html.heex")
           :position
           (:line 1 :character 15)))
[server-reply] (id:2) ERROR Fri May 24 20:34:52 2024:
(:jsonrpc "2.0" :id 2 :error
          (:code -32603 :message "Internal error"))
[internal] (id:2) ERROR Fri May 24 20:34:52 2024:
(:message "error ignored, status set (Internal error)" :id 2 :error -32603)
[client-notification] Fri May 24 20:34:55 2024:
(:jsonrpc "2.0" :method "textDocument/didChange" :params
          (:textDocument
           (:uri "file:///home/idanko/github.com/illia-danko/slivce/lib/slivce_web/components/layouts/root.html.heex" :version 1)
           :contentChanges
           [(:text "<html>\n  <body class=\"b\"></body>\n</html>\n")]))
[client-request] (id:3) Fri May 24 20:34:55 2024:
(:jsonrpc "2.0" :id 3 :method "textDocument/completion" :params
          (:textDocument
           (:uri "file:///home/idanko/github.com/illia-danko/slivce/lib/slivce_web/components/layouts/root.html.heex")
           :position
           (:line 1 :character 16)
           :context
           (:triggerKind 1)))
[server-reply] (id:3) ERROR Fri May 24 20:34:55 2024:
(:jsonrpc "2.0" :id 3 :error
          (:code -32603 :message "Internal error"))
[client-request] (id:4) Fri May 24 20:34:55 2024:
(:jsonrpc "2.0" :id 4 :method "textDocument/completion" :params
          (:textDocument
           (:uri "file:///home/idanko/github.com/illia-danko/slivce/lib/slivce_web/components/layouts/root.html.heex")
           :position
           (:line 1 :character 16)
           :context
           (:triggerKind 1)))
[server-reply] (id:4) ERROR Fri May 24 20:34:55 2024:
(:jsonrpc "2.0" :id 4 :error
          (:code -32603 :message "Internal error"))
[client-notification] Fri May 24 20:34:55 2024:
(:jsonrpc "2.0" :method "textDocument/didChange" :params
          (:textDocument
           (:uri "file:///home/idanko/github.com/illia-danko/slivce/lib/slivce_web/components/layouts/root.html.heex" :version 2)
           :contentChanges
           [(:text "<html>\n  <body class=\"bg\"></body>\n</html>\n")]))
[client-request] (id:5) Fri May 24 20:34:55 2024:
(:jsonrpc "2.0" :id 5 :method "textDocument/completion" :params
          (:textDocument
           (:uri "file:///home/idanko/github.com/illia-danko/slivce/lib/slivce_web/components/layouts/root.html.heex")
           :position
           (:line 1 :character 17)
           :context
           (:triggerKind 1)))
[server-reply] (id:5) ERROR Fri May 24 20:34:55 2024:
(:jsonrpc "2.0" :id 5 :error
          (:code -32603 :message "Internal error"))
[client-request] (id:6) Fri May 24 20:34:55 2024:
(:jsonrpc "2.0" :id 6 :method "textDocument/completion" :params
          (:textDocument
           (:uri "file:///home/idanko/github.com/illia-danko/slivce/lib/slivce_web/components/layouts/root.html.heex")
           :position
           (:line 1 :character 17)
           :context
           (:triggerKind 1)))
[server-reply] (id:6) ERROR Fri May 24 20:34:55 2024:
(:jsonrpc "2.0" :id 6 :error
          (:code -32603 :message "Internal error"))
[client-request] (id:7) Fri May 24 20:34:55 2024:
(:jsonrpc "2.0" :id 7 :method "textDocument/hover" :params
          (:textDocument
           (:uri "file:///home/idanko/github.com/illia-danko/slivce/lib/slivce_web/components/layouts/root.html.heex")
           :position
           (:line 1 :character 17)))
[server-reply] (id:7) ERROR Fri May 24 20:34:55 2024:
(:jsonrpc "2.0" :id 7 :error
          (:code -32603 :message "Internal error"))
[internal] (id:7) ERROR Fri May 24 20:34:55 2024:
(:message "error ignored, status set (Internal error)" :id 7 :error -32603)
[client-request] (id:8) Fri May 24 20:34:57 2024:
(:jsonrpc "2.0" :id 8 :method "textDocument/hover" :params
          (:textDocument
           (:uri "file:///home/idanko/github.com/illia-danko/slivce/lib/slivce_web/components/layouts/root.html.heex")
           :position
           (:line 1 :character 16)))
[server-reply] (id:8) ERROR Fri May 24 20:34:57 2024:
(:jsonrpc "2.0" :id 8 :error
          (:code -32603 :message "Internal error"))
[internal] (id:8) ERROR Fri May 24 20:34:57 2024:
(:message "error ignored, status set (Internal error)" :id 8 :error -32603)
[client-request] (id:9) Fri May 24 20:35:08 2024:
(:jsonrpc "2.0" :id 9 :method "textDocument/hover" :params
          (:textDocument
           (:uri "file:///home/idanko/github.com/illia-danko/slivce/lib/slivce_web/components/layouts/root.html.heex")
           :position
           (:line 3 :character 0)))
[server-reply] (id:9) ERROR Fri May 24 20:35:08 2024:
(:jsonrpc "2.0" :id 9 :error
          (:code -32603 :message "Internal error"))
[internal] (id:9) ERROR Fri May 24 20:35:08 2024:
(:message "error ignored, status set (Internal error)" :id 9 :error -32603)

The file I edited: root.html.heex

<html>
  <body class="bg[cursor_is_here]"></body>
</html>

By using neovim the following setup works:

The settings:

  lspconfig.tailwindcss.setup({
    on_attach = on_attach,
    capabilities = capabilities,
    filetypes = { "html", "elixir", "eelixir", "heex" },
    init_options = {
      userLanguages = {
        elixir = "html-eex",
        eelixir = "html-eex",
        heex = "html-eex",
      },
    },
    settings = {
      tailwindCSS = {
        experimental = {
          classRegex = {
            'class[:]\\s*"([^"]*)"',
          },
        },
      },
    },
  })

Neovim lsp logs are attached. lsp.log

@joaotavora can you help to add tailwind server to eglot?