joaotavora / eglot

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

HTML and CSS Servers support #203

Closed easbarba closed 5 years ago

easbarba commented 5 years ago

Hey, I noticed there is no, yet, support for HTML and CSS LSP servers.

Would anyone kindly add those to us?! :+1:

With the recent move of MS Edge to Chromium/blink as its base I reckon a lot of people, as me, is yet again giving web languages another try!

That should easy our web journeys! HEHE

PS: I know just about nothing of Elisp for now! Otherwise, I would pull it myself!

blandest commented 5 years ago

I have created a pull request: https://github.com/joaotavora/eglot/pull/204 for these language servers. You can always define your own by updating the 'eglot-servers-programs variable like this:

(pushnew '(css-mode "css-languageserver" "--stdio") eglot-server-programs :key 'car)

(add-hook 'css-mode-hook 'eglot-ensure)

Install the server with:

$ npm install vscode-css-languageservice-bin

easbarba commented 5 years ago

Thank you, sir!

joaotavora commented 5 years ago

@eubarbosa can we cool a bit the opening and reopening of issues? It's quite noisy in my (and other people's) inboxes, so think twice before doing it. I like that non-collaborators have access to these basic management features, but think about the noise, too, please.

easbarba commented 5 years ago

@joaotavora Sorry for troubling you all! :+1:

joaotavora commented 5 years ago

No problem, just save your energy for the important stuff :-)

easbarba commented 5 years ago

lol

c0001 commented 3 years ago

vscode-html-server with error of eglot--error: [eglot] -32603: Request initialize failed with message: Cannot read property 'css' of undefined

muffinmad commented 3 years ago

@c0001 Looks like the server expects some initialization options: https://github.com/vscode-langservers/vscode-html-languageserver/blob/3292e4cc7d1ac40d3de9a21bca5cc0dae6f7271e/src/htmlServer.ts#L119

Try to pass css and javascript in initializationOptions.

c0001 commented 3 years ago

@muffinmad

Thanks for your suggestion!

But if just gives the :css and :javascript key pair into the init options, we don't have the completion and other restriction yet, thus for, I post my scratch configuration here for other user use on scratch aim, see below:


 ;; Here's my simple grab vscode-html-lang eglot initializaton class
 ;; defination with completion and other details added from sublime's html
 ;; lsp plugin index post:

  (defclass eglot-html-languageserver (eglot-lsp-server) ()
    :documentation "Vscode html-languageserver class for eglot")
  (cl-defmethod eglot-initialization-options ((server eglot-html-languageserver))
    "`eglot-html-languageserver' initialization method"
    '(:embeddedLanguages
      (:css "true" :javascript "true")
      :provideFormatte "true"
      :settings (
                 :html.customData []
                 :html.format.enable "true"
                 :html.format.wrapLineLength 120
                 :html.format.unformatted "wbr"
                 :html.format.contentUnformatted "pre,code,textarea"
                 :html.format.indentInnerHtml "false"
                 :html.format.preserveNewLines "true"
                 :html.format.maxPreserveNewLines "null"
                 :html.format.indentHandlebars "false"
                 :html.format.endWithNewline "false"
                 :html.format.extraLiners "head, body, /html"
                 :html.format.wrapAttributes "auto"
                 :html.suggest.html5 "true"
                 :html.validate.scripts "true"
                 :html.validate.styles "true"
                 :css.customData []
                 :css.completion.triggerPropertyValueCompletion "true"
                 :css.completion.completePropertyWithSemicolon "true"
                 :css.validate "true"
                 :css.lint.compatibleVendorPrefixes "ignore"
                 :css.lint.vendorPrefix "warning"
                 :css.lint.duplicateProperties "ignore"
                 :css.lint.emptyRules "warning"
                 :css.lint.importStatement "ignore"
                 :css.lint.boxModel "ignore"
                 :css.lint.universalSelector "ignore"
                 :css.lint.zeroUnits "ignore"
                 :css.lint.fontFaceProperties "warning"
                 :css.lint.hexColorLength "error"
                 :css.lint.argumentsInColorFunction "error"
                 :css.lint.unknownProperties "warning"
                 :css.lint.validProperties []
                 :css.lint.ieHack "ignore"
                 :css.lint.unknownVendorSpecificProperties "ignore"
                 :css.lint.propertyIgnoredDueToDisplay "warning"
                 :css.lint.important "ignore"
                 :css.lint.float "ignore"
                 :css.lint.idSelector "ignore"
                 :css.lint.unknownAtRules "warning"
                 :javascript.referencesCodeLens.enabled "false"
                 :javascript.referencesCodeLens.showOnAllFunctions "false"
                 :javascript.suggest.completeFunctionCalls "false"
                 :javascript.suggest.includeAutomaticOptionalChainCompletions "true"
                 :javascript.suggest.names "true"
                 :javascript.suggest.paths "true"
                 :javascript.suggest.autoImports "true"
                 :javascript.suggest.completeJSDocs "true"
                 :javascript.suggest.enabled "true"
                 :javascript.validate.enable "true"
                 :javascript.format.enable "true"
                 :javascript.format.insertSpaceAfterCommaDelimiter "true"
                 :javascript.format.insertSpaceAfterConstructor "false"
                 :javascript.format.insertSpaceAfterSemicolonInForStatements "true"
                 :javascript.format.insertSpaceBeforeAndAfterBinaryOperators "true"
                 :javascript.format.insertSpaceAfterKeywordsInControlFlowStatements "true"
                 :javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions "false"
                 :javascript.format.insertSpaceBeforeFunctionParenthesis "false"
                 :javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis "false"
                 :javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets "false"
                 :javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces "true"
                 :javascript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces "false"
                 :javascript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces "false"
                 :javascript.format.placeOpenBraceOnNewLineForFunctions "false"
                 :javascript.format.placeOpenBraceOnNewLineForControlBlocks "false"
                 :javascript.format.semicolons "ignore"
                 :javascript.implicitProjectConfig.checkJs "true"
                 :javascript.implicitProjectConfig.experimentalDecorators "false"
                 :javascript.suggestionActions.enabled "true"
                 :javascript.preferences.quoteStyle "single"
                 :javascript.preferences.importModuleSpecifier "auto"
                 :javascript.preferences.renameShorthandProperties "true"
                 :javascript.updateImportsOnFileMove.enabled "prompt"
                 )
      ))
muffinmad commented 3 years ago

@c0001

(:css "true" :javascript "true")

To pass true or false, use t and :json-false respectively.

we don't have the completion and other restriction yet

M-x eglot-events-buffer may be useful here to investigate further.

How did you install that language server?

c0001 commented 3 years ago

Thanks for your notice on, t or nil is in lisp way so that I use proto native string specification for confused thoughts aimed on scratch implementation as is here, thanks you to telling me that's indeed not necessary.

I install server from npm repositry just as normal way, would you willing to post an standard eglot html server spec configuration let me learning on? that's may be extremely grateful.

muffinmad commented 3 years ago

Well, I don't use html/css language server myself, but let's see how we can make it work.

  1. npm install @bmewburn/vscode-html-languageserver

Is this the right package?

  1. Configure eglot

In emacs -Q

M-x package-initialize

(require 'eglot)

(defclass test/html-langserver (eglot-lsp-server) ())

(cl-defmethod eglot-initialization-options ((_server test/html-langserver))
  '(:embeddedLanguages
    (:css t :javascript t)))

(add-to-list 'eglot-server-programs
         '(mhtml-mode test/html-langserver "node" "/path/to/node_modules/@bmewburn/vscode-html-languageserver/out/node/htmlServerMain.js" "--stdio"))

Don't know why, but this laguage server enables completions capability only if client support snippets:

completionProvider: clientSnippetSupport ? { resolveProvider: true, triggerCharacters: ['.', ':', '<', '"', '=', '/'] } : undefined,

Eglot uses yasnippet package for snippet support.

So make sure the yasnippet package is installed and do:

M-x yas-global-mode

  1. Edit some html

C-x C-f test.html M-x eglot Type <h

Because C-M-i runs the command ispell-complete-word (found in mhtml-mode-map), we need to call completions like this:

M-x completion-at-point

I see completion candidates in the *Completions* buffer.

Here is request-response transcript from eglot events buffer:

[client-request] (id:8) Wed Jan 20 22:37:23 2021:
(:jsonrpc "2.0" :id 8 :method "textDocument/completion" :params
      (:textDocument
       (:uri "file:///Users/mad/workspace/test/test.html")
       :position
       (:line 0 :character 2)
       :context
       (:triggerKind 1)))
[server-reply] (id:8) Wed Jan 20 22:37:23 2021:
(:jsonrpc "2.0" :id 8 :result
      (:isIncomplete :json-false :items
             [(:label "html" :kind 10 :documentation
                  (:kind "plaintext" :value "The html element represents the root of an HTML document.\n\nMDN Reference: https://developer.mozilla.org/docs/Web/HTML/Element/html")
                  :textEdit
                  (:range
                   (:start
                    (:line 0 :character 1)
                    :end
                    (:line 0 :character 2))
                   :newText "html")
                  :insertTextFormat 1)
              (:label "head" :kind 10 :documentation
                  (:kind "plaintext" :value "The head element represents a collection of metadata for the Document.\n\nMDN Reference: https://developer.mozilla.org/docs/Web/HTML/Element/head")
                  :textEdit
                  (:range
                   (:start
                    (:line 0 :character 1)
                    :end
                    (:line 0 :character 2))
                   :newText "head")
                  :insertTextFormat 1)
...