Giter Site home page Giter Site logo

efm-langserver's Introduction

efm-langserver

Actions Status

General purpose Language Server that can use specified error message format generated from specified command. This is useful for editing code with linter.

efm

Installation

go install github.com/mattn/efm-langserver@latest

or via Homebrew:

brew install efm-langserver

Usage

Usage of efm-langserver:
  -c string
        path to config.yaml
  -d    dump configuration
  -logfile string
        logfile
  -loglevel int
        loglevel (default 1)
  -q    Run quieter
  -v    Print the version

Configuration

Configuration can be done with either a config.yaml file, or through a DidChangeConfiguration notification from the client. DidChangeConfiguration can be called any time and will overwrite only provided properties.

DidChangeConfiguration only supports V2 configuration and cannot set LogFile.

efm-langserver does not include formatters/linters for any languages, you must install these manually, e.g.

InitializeParams

Because the configuration can be updated on the fly, capabilities might change throughout the lifetime of the server. To enable support for capabilities that will be available later, set them in the InitializeParams

Example

{
    "initializationOptions": {
        "documentFormatting": true,
        "documentRangeFormatting": true,
        "hover": true,
        "documentSymbol": true,
        "codeAction": true,
        "completion": true
    }
}

Example for config.yaml

Location of config.yaml is:

  • UNIX: $XDG_CONFIG_HOME/efm-langserver/config.yaml or $HOME/.config/efm-langserver/config.yaml
  • Windows: %APPDATA%\efm-langserver\config.yaml

Below is example for config.yaml for Windows. Please see schema.md for full documentation of the available options.

version: 2
root-markers:
  - .git/
lint-debounce: 1s
commands:
  - command: notepad
    arguments:
      - ${INPUT}
    title: メモ帳

tools:
  any-excitetranslate: &any-excitetranslate
    hover-command: 'excitetranslate'
    hover-stdin: true

  blade-blade-formatter: &blade-blade-formatter
    format-command: 'blade-formatter --stdin'
    format-stdin: true

  css-prettier: &css-prettier
    format-command: './node_modules/.bin/prettier ${--tab-width:tabWidth} ${--single-quote:singleQuote} --parser css'

  csv-csvlint: &csv-csvlint
    lint-command: 'csvlint'

  dockerfile-hadolint: &dockerfile-hadolint
    lint-command: 'hadolint'
    lint-formats:
      - '%f:%l %m'

  eruby-erb: &eruby-erb
    lint-debounce: 2s
    lint-command: 'erb -x -T - | ruby -c'
    lint-stdin: true
    lint-offset: 1
    format-stdin: true
    format-command: htmlbeautifier

  gitcommit-gitlint: &gitcommit-gitlint
    lint-command: 'gitlint'
    lint-stdin: true
    lint-formats:
      - '%l: %m: "%r"'
      - '%l: %m'

  html-prettier: &html-prettier
    format-command: './node_modules/.bin/prettier ${--tab-width:tabWidth} ${--single-quote:singleQuote} --parser html'

  javascript-eslint: &javascript-eslint
    lint-command: 'eslint -f visualstudio --stdin --stdin-filename ${INPUT}'
    lint-ignore-exit-code: true
    lint-stdin: true
    lint-formats:
      - "%f(%l,%c): %tarning %m"
      - "%f(%l,%c): %rror %m"

  json-fixjson: &json-fixjson
    format-command: 'fixjson'

  json-jq: &json-jq
    lint-command: 'jq .'

  json-prettier: &json-prettier
    format-command: './node_modules/.bin/prettier ${--tab-width:tabWidth} --parser json'

  lua-lua-format: &lua-lua-format
    format-command: 'lua-format -i'
    format-stdin: true

  make-checkmake: &make-checkmake
    lint-command: 'checkmake'
    lint-stdin: true

  markdown-markdownlint: &markdown-markdownlint
    lint-command: 'markdownlint -s -c %USERPROFILE%\.markdownlintrc'
    lint-stdin: true
    lint-formats:
      - '%f:%l %m'
      - '%f:%l:%c %m'
      - '%f: %l: %m'

  markdown-pandoc: &markdown-pandoc
    format-command: 'pandoc -f markdown -t gfm -sp --tab-stop=2'

  mix_credo: &mix_credo
    lint-command: "mix credo suggest --format=flycheck --read-from-stdin ${INPUT}"
    lint-stdin: true
    lint-formats:
      - '%f:%l:%c: %t: %m'
      - '%f:%l: %t: %m'
    root-markers:
      - mix.lock
      - mix.exs

  perl-perlcritic: &perl-perlcritic
    lint-command: 'perlcritic --nocolor -3 --verbose "%l:%c %m\n"'
    lint-ignore-exit-code: true
    lint-formats:
      - '%l:%c %m'

  perl-perltidy: &perl-perltidy
    format-command: "perltidy -b"
    format-stdin: true

  php-phpstan: &php-phpstan
    lint-command: './vendor/bin/phpstan analyze --error-format raw --no-progress'

  php-psalm: &php-psalm
    lint-command: './vendor/bin/psalm --output-format=emacs --no-progress'
    lint-formats:
      - '%f:%l:%c:%trror - %m'
      - '%f:%l:%c:%tarning - %m'

  prettierd: &prettierd
    format-command: >
      prettierd ${INPUT} ${--range-start=charStart} ${--range-end=charEnd} \
        ${--tab-width=tabSize}
    format-stdin: true
    root-markers:
      - .prettierrc
      - .prettierrc.json
      - .prettierrc.js
      - .prettierrc.yml
      - .prettierrc.yaml
      - .prettierrc.json5
      - .prettierrc.mjs
      - .prettierrc.cjs
      - .prettierrc.toml

  python-autopep8: &python-autopep8
    format-command: 'autopep8 -'
    format-stdin: true

  python-black: &python-black
    format-command: 'black --quiet -'
    format-stdin: true

  python-flake8: &python-flake8
    lint-command: 'flake8 --stdin-display-name ${INPUT} -'
    lint-stdin: true
    lint-formats:
      - '%f:%l:%c: %m'

  python-isort: &python-isort
    format-command: 'isort --quiet -'
    format-stdin: true

  python-mypy: &python-mypy
    lint-command: 'mypy --show-column-numbers'
    lint-formats:
      - '%f:%l:%c: %trror: %m'
      - '%f:%l:%c: %tarning: %m'
      - '%f:%l:%c: %tote: %m'

  python-pylint: &python-pylint
    lint-command: 'pylint --output-format text --score no --msg-template {path}:{line}:{column}:{C}:{msg} ${INPUT}'
    lint-stdin: false
    lint-formats:
      - '%f:%l:%c:%t:%m'
    lint-offset-columns: 1
    lint-category-map:
      I: H
      R: I
      C: I
      W: W
      E: E
      F: E

  python-yapf: &python-yapf
    format-command: 'yapf --quiet'
    format-stdin: true

  rst-lint: &rst-lint
    lint-command: 'rst-lint'
    lint-formats:
      - '%tNFO %f:%l %m'
      - '%tARNING %f:%l %m'
      - '%tRROR %f:%l %m'
      - '%tEVERE %f:%l %m'

  rst-pandoc: &rst-pandoc
    format-command: 'pandoc -f rst -t rst -s --columns=79'

  sh-shellcheck: &sh-shellcheck
    lint-command: 'shellcheck -f gcc -x'
    lint-source: 'shellcheck'
    lint-formats:
      - '%f:%l:%c: %trror: %m'
      - '%f:%l:%c: %tarning: %m'
      - '%f:%l:%c: %tote: %m'

  sh-shfmt: &sh-shfmt
    format-command: 'shfmt -ci -s -bn'
    format-stdin: true

  vim-vint: &vim-vint
    lint-command: 'vint -'
    lint-stdin: true
    lint-formats:
      - '%f:%l:%c: %m'

  yaml-yamllint: &yaml-yamllint
    lint-command: 'yamllint -f parsable -'
    lint-stdin: true

languages:
  blade:
    - <<: *blade-blade-formatter

  css:
    - <<: *css-prettier

  csv:
    - <<: *csv-csvlint

  dockerfile:
    - <<: *dockerfile-hadolint

  elixir:
    - <<: *mix_credo

  eruby:
    - <<: *eruby-erb

  gitcommit:
    - <<: *gitcommit-gitlint

  html:
    - <<: *html-prettier

  javascript:
    - <<: *javascript-eslint
    - <<: *prettierd

  json:
    - <<: *json-fixjson
    - <<: *json-jq
    # - <<: *json-prettier

  lua:
    - <<: *lua-lua-format

  make:
    - <<: *make-checkmake

  markdown:
    - <<: *markdown-markdownlint
    - <<: *markdown-pandoc

  perl:
    - <<: *perl-perltidy
    - <<: *perl-perlcritic

  php:
    - <<: *php-phpstan
    - <<: *php-psalm

  python:
    - <<: *python-black
    - <<: *python-flake8
    - <<: *python-isort
    - <<: *python-mypy
    # - <<: *python-autopep8
    # - <<: *python-yapf

  rst:
    - <<: *rst-lint
    - <<: *rst-pandoc

  sh:
    - <<: *sh-shellcheck
    - <<: *sh-shfmt

  vim:
    - <<: *vim-vint

  yaml:
    - <<: *yaml-yamllint

  =:
    - <<: *any-excitetranslate

If you want to debug output of commands:

version: 2
log-file: /path/to/output.log
log-level: 1

Example for DidChangeConfiguration notification

{
    "settings": {
        "rootMarkers": [".git/"],
        "languages": {
            "lua": {
                "formatCommand": "lua-format -i",
                "formatStdin": true
            }
        }
    }
}

Client Setup

Configuration for vim-lsp

augroup LspEFM
  au!
  autocmd User lsp_setup call lsp#register_server({
      \ 'name': 'efm-langserver',
      \ 'cmd': {server_info->['efm-langserver', '-c=/path/to/your/config.yaml']},
      \ 'allowlist': ['vim', 'eruby', 'markdown', 'yaml'],
      \ })
augroup END

vim-lsp-settings provide installer for efm-langserver.

Configuration for coc.nvim

coc-settings.json

  // languageserver
  "languageserver": {
    "efm": {
      "command": "efm-langserver",
      "args": [],
      // custom config path
      // "args": ["-c", "/path/to/your/config.yaml"],
      "filetypes": ["vim", "eruby", "markdown", "yaml"]
    }
  },

Configuration for Eglot (Emacs)

Add to eglot-server-programs with major mode you want.

(with-eval-after-load 'eglot
  (add-to-list 'eglot-server-programs
    `(markdown-mode . ("efm-langserver"))))

Configuration for neovim builtin LSP with nvim-lspconfig

Neovim's built-in LSP client sends DidChangeConfiguration, so config.yaml is optional.

init.lua example (settings follows schema.md):

require "lspconfig".efm.setup {
    init_options = {documentFormatting = true},
    settings = {
        rootMarkers = {".git/"},
        languages = {
            lua = {
                {formatCommand = "lua-format -i", formatStdin = true}
            }
        }
    }
}

You can get premade tool definitions from creativenull/efmls-configs-nvim:

lua = {
  require('efmls-configs.linters.luacheck'),
  require('efmls-configs.formatters.stylua'),
}

If you define your own, make sure to define as table:

lua = {
    {formatCommand = "lua-format -i", formatStdin = true}
}
-- NOT
lua = {
    formatCommand = "lua-format -i", formatStdin = true
}

-- and for multiple formatters, add to the table
lua = {
    {formatCommand = "lua-format -i", formatStdin = true},
    {formatCommand = "lua-pretty -i"}
}

Configuration for Helix

~/.config/helix/languages.toml

[language-server.efm]
command = "efm-langserver"

[[language]]
name = "typescript"
language-servers = [
  { name = "efm", only-features = [ "diagnostics", "format" ] },
  { name = "typescript-language-server", except-features = [ "format" ] }
]

Configuration for VSCode

Generic LSP Client for VSCode

Example settings.json (change to fit your local installs):

{
  "glspc.languageId": "lua",
  "glspc.serverCommand": "/Users/me/.local/share/nvim/mason/bin/efm-langserver",
  "glspc.pathPrepend": "/Users/me/.local/share/rtx/installs/python/3.11.4/bin:/Users/me/.local/share/rtx/installs/node/20.3.1/bin",
}

License

MIT

Author

Yasuhiro Matsumoto (a.k.a. mattn)

efm-langserver's People

Contributors

arrow2nd avatar atrautsch avatar disrupted avatar fsouza avatar hori-ryota avatar iamcco avatar ivanterrible avatar llllvvuu avatar lotusirous avatar lukas-reineke avatar mattn avatar matts966 avatar megalithic avatar mikatpt avatar n3wborn avatar nametake avatar ndreas avatar notomo avatar pedrogameiro avatar ray-x avatar renovate-bot avatar seirdy avatar skanehira avatar staticssleever668 avatar tennashi avatar tsuyoshicho avatar vanhtuan0409 avatar xuanduc987 avatar yaegassy avatar zonuexe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

efm-langserver's Issues

Trouble setting up MATLAB's mlint

I've been trying to setup efm-langserver through Neovim's built-in LSO for linting MATLAB files. I've checked the implementations in Neomake and ALE, which I've used before and both worked well.
These are the relevant lines of my failed attempt:

require "lspconfig".efm.setup {
    init_options = {documentFormatting = true},
    filetypes = {'matlab'},
    settings = {
        languages = {
            matlab = {
                lintCommand = 'mlint -id',
                lintStderr = true,
                lintStdin= false,
                lintFormats = {
                    [[%f:L %l (C %c): %m]],
                    [[%f:L %l (C %c-%*[0-9]): %m]],
                },
            },
        },
    },
}

They are not producing any visible result nor any error, though, and I'm unable to determine why. According to :LSPInfo, efm-langserver is correctly loaded and the only language server running.
To exemplify to output of mlint -id, I'll attach a random warning and error:

L 135 (C 5-9): SAGROW: The variable 'pesos' appears to change size on every loop iteration (within a script). Consider preallocating for speed.
L 165 (C 2): SYNER: Parse error at <EOL>: usage might be invalid MATLAB syntax.

I suppose there may be a misconfiguration on my part, so I'll be happy to accept any help or hint in the right direction.

Multiple jobs overloading the cpu

Thanks for this interesting project.
I would like to use it with pylint for python in neovim (with its builtin client).

Unfortunately if I make many changes to the file (like deleting multiple chars) many jobs get spawned eating up the cpu very fast (I have 8 threads). This means that deleting 20 chars produce 20 jobs that could last for a minute or two globally. Also all other tasks become slow as the cpu s clogged.

I'm aware of this PR #82 but it seem that it's not working for me.
Maybe the reason is that all jobs are running somehow and not waiting in any queue.

This is the relevant configuration I'm providing to the language server:

lspconfig.efm.setup {
    cmd = {"efm-langserver", "-logfile", "/home/xxxxx/efm.log"},
    on_attach = on_attach,
    filetypes = {'python'},
    root_dir = lspconfig.util.root_pattern(".git/", ".bashrc"),
    settings = {
        rootMarkers = {".git/", ".bashrc"},
        languages = {
            python = {
                {
                    lintCommand = "pylint -j 1 --from-stdin ${INPUT} --score no --msg-template '{path}:{line}:{column}:{C} {msg_id} {msg} ({symbol}) -- PL' | sed -e 's/:I\\s/:H /' -e 's/:[CR]\\s/:I /' -e '/C0103/d'",
                    lintIgnoreExitCode = true,
                    lintStdin = true,
                    lintDebounce = 5,
                    lintFormats = {"%f:%l:%c:%t %m"},
                    onSave = true,
                },
            },
        },
    },
    diagnostics = {
        onChange = false
    }
}

Problems installing with `go get`

Problem description

Attempting to install efm-langserver would exit with a non-zero status.

$ go get github.com/mattn/efm-langserver/cmd/efm-langserver
# github.com/mattn/efm-langserver/cmd/efm-langserver
../go/src/github.com/mattn/efm-langserver/cmd/efm-langserver/main.go:25:8: undefined: yaml.NewDecoder
$ echo $?
2

Versions

$ uname -msrv
Darwin 18.5.0 Darwin Kernel Version 18.5.0: Mon Mar 11 20:40:32 PDT 2019; root:xnu-4903.251.3~3/RELEASE_X86_64 x86_64
$ go version
go version go1.12.3 darwin/amd64

pylint: need configurable severity types, or default to "I" (information)

First off, I love this tool! It's got big dreams and I'd like it to keep getting better! This is issue 2 of 2 related to pylint.

pylint has additional messages types:

  • [I]nformational messages that Pylint emits (do not contribute to your analysis score)
  • [R]efactor for a "good practice" metric violation
  • [C]onvention for coding standard violation
  • [W]arning for stylistic problems, or minor programming issues
  • [E]rror for important programming issues (i.e. most probably bug)
  • [F]atal for errors which prevented further processing

Currently, when efm encounters an unknown message type, it defaults to the "Error" value. See current logic here: https://github.com/mattn/efm-langserver/blob/master/langserver/handler.go#L282

Example pylint error messages (0-indexed): I currently use the efm format %f:%l:%c: %t%m which works well if you ignore #49.

file.py:13:0: C0116: Missing function or method docstring (missing-function-docstring)
file.py:27:0: R0902: Too many instance attributes (8/7) (too-many-instance-attributes)
file.py:40:8: W0612: Unused variable 'response' (unused-variable)
file.py:55:4: E0102: method already defined line 36 (function-redefined)
file.py:71:4: E0602: Undefined variable 'url' (undefined-variable)
file.py:6:0: W0611: Unused Final imported from typing (unused-import)

feat: Require detect marker to run tool command

Thanks for making this great language server!

One thing I wish I could do is add a detect marker requirement. This would make it possible to not run tools if a marker files or pattern was not detected. These opinionated formatters can wreck havoc if done on projects that don't support them.

Example:
Only run prettier if .prettierrc is detected.
Only run stylua if stylua.toml is detected.

 lua-stylua-format: &lua-stylua-format
      format-command: 'stylua -'
      format-stdin: true
      root-markers:
        - 'stylua.toml'
      require-markers:
        - 'stylua.toml'
   prettier: &prettier
      format-command: 'prettier --stdin-filename ${INPUT}'
      format-stdin: true
      require-markers:
        - '.prettierrc'
        - '.prettierrc.json'

Alternative:

 lua-stylua-format: &lua-stylua-format
      format-command: 'stylua -'
      format-stdin: true
      root-markers:
        - 'stylua.toml'
      require-marker: true

Also to note sometimes markers are found inside a main config file. Like prettier supports package.json { prettier: ...}

JSON not being formatted

Hey, excellent work on this project. I've just replaced w0rp/ale with this and oh is it nice. Thank you!

However, I am having some issues when it comes to JSON.

This is a snippet of my config.yaml:

tools:
  json-jq: &json-jq
    lint-command: 'jq .'
    lint-stdin: true
    lint-ignore-exit-code: true
  json-prettier: &json-prettier
    format-command: 'prettier ${--tab-width:tabWidth} --parser json'

languages:
  json:
    - <<: *json-jq
    - <<: *json-prettier

Now, with that config loaded I can see lint errors just fine. However, if I attempt to use :lua vim.lsp.buf.formatting() it will format fine, however my shortcut <leader>p does nothing.

I have <leader>p setup with this block (yes, copied from some neovim/lua guide)

  if client.resolved_capabilities.document_formatting then
    buf_set_keymap("n", "<space>p", "<cmd>lua vim.lsp.buf.formatting()<CR>", opts)
  elseif client.resolved_capabilities.document_range_formatting then
    buf_set_keymap("n", "<space>p", "<cmd>lua vim.lsp.buf.range_formatting()<CR>", opts)
  end

I have a json language server installed.

However I am totally unaware of how this feature is set - is this something efm needs configuring for or is this a problem elsewhere?

Thanks again!

EDIT:

Just replacing that lua block above with only the keymap set (without the conditional) makes it work fine, but I don't understand how it's not letting me. Here's the setup from my init.vim

local on_attach = function(client, bufnr)
  local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
  local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end

  buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')

  -- Mappings.
  -- ...snip keymappings...

  -- Linting - THIS IS THE PROBLEMATIC BLOCK
  -- if client.resolved_capabilities.document_formatting then
    buf_set_keymap("n", "<space>p", "<cmd>lua vim.lsp.buf.formatting()<CR>", opts)
  -- elseif client.resolved_capabilities.document_range_formatting then
    -- buf_set_keymap("n", "<space>p", "<cmd>lua vim.lsp.buf.range_formatting()<CR>", opts)
  -- end

  -- Set autocommands conditional on server_capabilities
  if client.resolved_capabilities.document_highlight then
    vim.api.nvim_exec([[
      hi LspReferenceRead cterm=bold ctermbg=red guibg=LightYellow
      hi LspReferenceText cterm=bold ctermbg=red guibg=LightYellow
      hi LspReferenceWrite cterm=bold ctermbg=red guibg=LightYellow
      augroup lsp_document_highlight
        autocmd! * <buffer>
        autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()
        autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()
      augroup END
    ]], false)
  end
end


nvim_lsp.efm.setup {
  on_attach = on_attach,
  init_options = {
    documentFormatting = true
  },
  settings = {}
}

Error installing with go

When I use command from readme I get the following error

$ go get github.com/mattn/efm-langserver
# github.com/mattn/efm-langserver/langserver
go/src/github.com/mattn/efm-langserver/langserver/handle_text_document_code_action.go:133:24: cmd.String undefined (type *exec.Cmd has no field or method String)
go/src/github.com/mattn/efm-langserver/langserver/handler.go:399:20: exitErr.ExitCode undefined (type *exec.ExitError has no field or method ExitCode)

I can't any error message for init.vim

I set up efm-langserver according to the readme in this repository and tested with init.vim file
which has errors. But I can't any error messages. I checked that the efm-langserver start successfully.
But, I can't see any messages from vim-vint.

What do I examine to solve this problem?

Feature request: Debounce(delay) setting

diagnostic-ls has an option to set debounce time which is a very useful feature in LSP programs. I regularly deal with moderate to huge size files for which the linters take more time to finish. But the efm-server cannot cope with such delays and the diagnostics flicker and disappear often. If there is an option to set the debounce time, that is the delay after which the linter is run again, I am hopeful that this problem can be resolved.

Can't instal with LspInstall

I am running :LspIstall eft and getting the following error

package github.com/mattn/efm-langserver@HEAD: invalid github.com/ import path "github.com/mattn/efm
-langserver@HEAD"

[Process exited 1]

Documentation

Hello, are there any documentation I can look at to see what options are available, what they do and what each format specifier mean?

Thanks in advance.

Using environment variables for config path

I tried to use $HOME to get my config file

{
    "languageserver": {
        "efm": {
            "command": "efm-langserver",
            "args": [],
            "trace.server": "verbose",
            "args": ["-c", "$HOME/.vim/vim/efm_config.yaml"],
            "filetypes": ["vim", "eruby", "markdown", "yaml"]
        }
    }
}

but there was an error when check log by:CocCommand workspace.showOutput

open $HOME/.vim/vim/efm_config.yaml: no such file or directory

htmlbeautifier as format-command for erb filetypes

I'll try to explain this as best I can, and I'm not sure if this is an issue with CoC, efm-langserver or htmlbeautifier.

First off, in case it's not obvious from the above this is using:

efm-langserver 0.0.26 (rev: HEAD/go1.15.6)
coc.nvim 0.0.80 using node 15.4.0
htmlbeautifier 1.3.1
nvim 0.4.4
ruby 2.7.2

coc-settings.json

{
  "coc.preferences.formatOnSaveFiletypes": [
    "css",
    "typescript",
    "javascript",
    "json",
    "jsonc",
    "jsx",
    "html",
    "yaml",
    "graphql",
    "less",
    "scss",
    "markdown",
    "mdx",
    "eruby"
  ],
  "solargraph.useBundler": true,
  "languageserver": {
    "efm": {
      "command": "/Users/mattkern/golang/bin/efm-langserver",
      "filetypes": ["eruby"],
      "args": []
    }
  },
  "cSpell.enabledLanguageIds": [
    "git-commit",
    "html",
    "latex",
    "markdown",
    "plaintext",
    "text"
  ]
}
~/.config/efm-langserver/config.yaml

version: 2
root-markers:
  - .git/
log-file: /Users/mattkern/tmp/output.log
log-level: 1
tools:
  eruby-erb: &eruby-erb
    lint-command: "erb -x -T - | ruby -c"
    lint-stdin: true
    lint-offset: 1
    format-command: htmlbeautifier

languages:
  eruby:
    - <<: *eruby-erb

I can see from the efm-langserver logs that the format is successful on writing an eruby filetype.

2020/12/29 13:10:32 htmlbeautifier /Users/mattkern/projects/liquidysplit/liquidysplit-web/app/views/orders/new.html.erb:
2020/12/29 13:10:32 format succeeded

But when that happens I get:

WARNING: The file has been changed since reading it!!!
Do you really want to write to it (y/n)?

If I say no the buffer goes blank and I see a W12 warning:

W12: Warning: File "x.erb" has changed and the buffer was changed in Vim as well.
See ":help W12" for more info.
[O]k, (L)oad File:

L will load the file with the formatting applied properly. So it's clear that the file is being written to outside of vim.

But if I choose O the file is saved as the empty buffer, overwriting the changes as an empty file. Very not ideal.

Of course, if I carefully choose the path through the options the formatting works. But this doesn't happen with any of the other format on write formatters I use, and it can't be the expected behavior.

What's wrong?

Give filepath to lint-command when lint-stdin is false

When lint-stdin is false in config, the lint command should take the path to an input file as an argument.
But for now, the lint command is called without the filepath, while lint-stdin is false.

I'm not familiar with golang, but following patch seems to work for me.
(Just adding filename at the end of the lint command.)

--- a/langserver/handler.go
+++ b/langserver/handler.go
@@ -157,11 +157,17 @@ func (h *langHandler) lint(uri string) []Diagnostic {

        diagnostics := []Diagnostic{}

+    var lintfname string
+       if !config.LintStdin {
+               lintfname = " " + fname
+       } else {
+               lintfname = ""
+       }
        var cmd *exec.Cmd
        if runtime.GOOS == "windows" {
-               cmd = exec.Command("cmd", "/c", config.LintCommand)
+               cmd = exec.Command("cmd", "/c", config.LintCommand+lintfname)
        } else {
-               cmd = exec.Command("sh", "-c", config.LintCommand)
+               cmd = exec.Command("sh", "-c", config.LintCommand+lintfname)
        }
        if config.LintStdin {
                cmd.Stdin = strings.NewReader(f.Text)

Or, providing a placeholder for the filepath in the config file (like lint-command: 'some-lint-command %s', %s will be replaced with the filepath) might be more elegant.

Note: I'd like to use redpen with efm-langserver. redpen does not accept stdin as an input.

Issue with formatter

I'm configured this to run htmlbeautifer on eruby and html files and am running with the vim-lsp plugin. When I format the following file using efm-langserver:

<html>
  <body>
    <ul>
      <li></li>
          <li></li>
            <li></li>
    </ul>
  </body>
</html>

I get

  <body>
    <ul>
      <li></li>
          <li></li>
            <li></li>
    </ul>
  </body>
</html>

i.e. the first line is deleted and nothing else happens.

By contrast, running (in vim) :! htmlbeautifer does the right thing:

<html>
  <body>
    <ul>
      <li></li>
      <li></li>
      <li></li>
    </ul>
  </body>
</html>

I'm not sure if the issue is due to efm-langserver or vim-lsp, although the second last line of the logs below suggests the response coming back has issues.

Tue Jan 14 14:33:52 2020:["lsp#register_server", "server registered", "solargraph"]
Tue Jan 14 14:33:52 2020:["lsp#register_server", "server registered", "efm-langserver"]
Tue Jan 14 14:33:52 2020:["lsp#register_server", "server registered", "javascript support using typescript-language-server"]
Tue Jan 14 14:33:52 2020:["lsp#register_server", "server registered", "pyls"]
Tue Jan 14 14:33:52 2020:["lsp#register_server", "server registered", "intelephense"]
Tue Jan 14 14:33:52 2020:["lsp#register_server", "server registered", "clangd"]
Tue Jan 14 14:33:52 2020:["s:on_text_document_did_open()", 1, "html", "/private/tmp", "file:///private/tmp/index.html"]
Tue Jan 14 14:33:52 2020:[{"response": {"data": {"__data__": "vim-lsp", "lsp_id": 5, "server_name": "efm-langserver"}, "message": "started lsp server successfully"}}]
Tue Jan 14 14:33:52 2020:["--->", 5, "efm-langserver", {"method": "initialize", "params": {"rootUri": "file:///private/tmp", "capabilities": {"workspace": {"configuration": true, "applyEdit": true}, "textDocument": {"foldingRange": {"lineFoldingOnly": true}, "documentSymbol": {"symbolKind": {"valueSet": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 1, 2, 3, 4, 5, 6, 7, 8, 9]}, "hierarchicalDocumentSymbolSupport": false}, "semanticHighlightingCapabilities": {"semanticHighlighting": true}, "definition": {"linkSupport": true}, "completion": {"completionItem": {"snippetSupport": false, "documentationFormat": ["plaintext"]}, "completionItemKind": {"valueSet": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 1, 2, 3, 4, 5, 6, 7, 8, 9]}}, "implementation": {"linkSupport": true}, "declaration": {"linkSupport": true}, "typeDefinition": {"linkSupport": true}}}, "rootPath": "/private/tmp", "processId": 53596, "trace": "off"}}]
Tue Jan 14 14:33:52 2020:["<---", 5, "efm-langserver", {"response": {"id": 1, "result": {"capabilities": {"documentFormattingProvider": true, "documentSymbolProvider": true, "textDocumentSync": 1, "completionProvider": {"triggerCharacters": ["*"]}}}, "jsonrpc": "2.0"}, "request": {"id": 1, "jsonrpc": "2.0", "method": "initialize", "params": {"rootUri": "file:///private/tmp", "capabilities": {"workspace": {"configuration": true, "applyEdit": true}, "textDocument": {"foldingRange": {"lineFoldingOnly": true}, "documentSymbol": {"symbolKind": {"valueSet": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 1, 2, 3, 4, 5, 6, 7, 8, 9]}, "hierarchicalDocumentSymbolSupport": false}, "semanticHighlightingCapabilities": {"semanticHighlighting": true}, "definition": {"linkSupport": true}, "completion": {"completionItem": {"snippetSupport": false, "documentationFormat": ["plaintext"]}, "completionItemKind": {"valueSet": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 1, 2, 3, 4, 5, 6, 7, 8, 9]}}, "implementation": {"linkSupport": true}, "declaration": {"linkSupport": true}, "typeDefinition": {"linkSupport": true}}}, "rootPath": "/private/tmp", "processId": 53596, "trace": "off"}}}]
Tue Jan 14 14:33:52 2020:["--->", 5, "efm-langserver", {"method": "initialized", "params": {}}]
Tue Jan 14 14:33:52 2020:[{"response": {"data": {"__data__": "vim-lsp", "server_name": "efm-langserver"}, "message": "configuration sent"}}]
Tue Jan 14 14:33:52 2020:["s:update_file_content()", 1]
Tue Jan 14 14:33:52 2020:["--->", 5, "efm-langserver", {"method": "textDocument/didOpen", "params": {"textDocument": {"uri": "file:///private/tmp/index.html", "version": 1, "languageId": "html", "text": "<html>\n  <body>\n    <ul>\n      <li></li>\n          <li></li>\n            <li></li>\n    </ul>\n  </body>\n</html>\n"}}}]
Tue Jan 14 14:33:52 2020:[{"response": {"data": {"path": "file:///private/tmp/index.html", "__data__": "vim-lsp", "filetype": "html", "server_name": "efm-langserver"}, "message": "textDocument/open sent"}}]
Tue Jan 14 14:33:52 2020:[{"response": {"data": {"path": "file:///private/tmp/index.html", "__data__": "vim-lsp", "server_name": "efm-langserver"}, "message": "not dirty"}}]
Tue Jan 14 14:33:52 2020:["<---(stderr)", 5, "efm-langserver", ["2020/01/14 14:33:52 efm-langserver: reading on stdin, writing on stdout", "2020/01/14 14:33:52 lint for languageId not supported: html", ""]]
Tue Jan 14 14:33:56 2020:[{"response": {"data": {"__data__": "vim-lsp", "server_name": "efm-langserver"}, "message": "server already started"}}]
Tue Jan 14 14:33:56 2020:[{"response": {"data": {"__data__": "vim-lsp", "init_result": {"id": 1, "result": {"capabilities": {"documentFormattingProvider": true, "documentSymbolProvider": true, "textDocumentSync": 1, "completionProvider": {"triggerCharacters": ["*"]}}}, "jsonrpc": "2.0"}, "server_name": "efm-langserver"}, "message": "lsp server already initialized"}}]
Tue Jan 14 14:33:56 2020:[{"response": {"data": {"__data__": "vim-lsp", "server_name": "efm-langserver"}, "message": "configuration sent"}}]
Tue Jan 14 14:33:56 2020:[{"response": {"data": {"path": "file:///private/tmp/index.html", "__data__": "vim-lsp", "server_name": "efm-langserver"}, "message": "already opened"}}]
Tue Jan 14 14:33:56 2020:[{"response": {"data": {"path": "file:///private/tmp/index.html", "__data__": "vim-lsp", "server_name": "efm-langserver"}, "message": "not dirty"}}]
Tue Jan 14 14:33:56 2020:["--->", 5, "efm-langserver", {"method": "textDocument/formatting", "on_notification": "---funcref---", "sync": 0, "params": {"options": {"insertSpaces": true, "tabSize": 2}, "textDocument": {"uri": "file:///private/tmp/index.html"}}}]
Tue Jan 14 14:33:56 2020:["<---(stderr)", 5, "efm-langserver", ["2020/01/14 14:33:56 format succeeded", ""]]
Tue Jan 14 14:33:56 2020:["<---", 5, "efm-langserver", {"response": {"id": 2, "result": [{"range": {"end": {"character": 0, "line": 1}, "start": {"character": 0, "line": 0}}, "newText": ""}], "jsonrpc": "2.0"}, "request": {"id": 2, "jsonrpc": "2.0", "method": "textDocument/formatting", "params": {"options": {"insertSpaces": true, "tabSize": 2}, "textDocument": {"uri": "file:///private/tmp/index.html"}}}}]
Tue Jan 14 14:33:56 2020:["s:build_cmd", "keepjumps keepalt b 1 | execute 'keepjumps normal! 1G0V1G$x'"]
Tue Jan 14 14:33:56 2020:["s:on_text_document_did_change()", 1]
Tue Jan 14 14:33:56 2020:["s:send_didchange_queue() will be triggered"]
Tue Jan 14 14:34:00 2020:["s:send_event_queue()"]
Tue Jan 14 14:34:00 2020:[{"response": {"data": {"__data__": "vim-lsp", "server_name": "efm-langserver"}, "message": "server already started"}}]
Tue Jan 14 14:34:00 2020:[{"response": {"data": {"__data__": "vim-lsp", "init_result": {"id": 1, "result": {"capabilities": {"documentFormattingProvider": true, "documentSymbolProvider": true, "textDocumentSync": 1, "completionProvider": {"triggerCharacters": ["*"]}}}, "jsonrpc": "2.0"}, "server_name": "efm-langserver"}, "message": "lsp server already initialized"}}]
Tue Jan 14 14:34:00 2020:[{"response": {"data": {"__data__": "vim-lsp", "server_name": "efm-langserver"}, "message": "configuration sent"}}]
Tue Jan 14 14:34:00 2020:[{"response": {"data": {"path": "file:///private/tmp/index.html", "__data__": "vim-lsp", "server_name": "efm-langserver"}, "message": "already opened"}}]
Tue Jan 14 14:34:00 2020:["s:update_file_content()", 1]
Tue Jan 14 14:34:00 2020:["--->", 5, "efm-langserver", {"method": "textDocument/didChange", "params": {"contentChanges": [{"text": "  <body>\n    <ul>\n      <li></li>\n          <li></li>\n            <li></li>\n    </ul>\n  </body>\n</html>\n"}], "textDocument": {"uri": "file:///private/tmp/index.html", "version": 2}}}]
Tue Jan 14 14:34:00 2020:[{"response": {"data": {"path": "file:///private/tmp/index.html", "__data__": "vim-lsp", "server_name": "efm-langserver"}, "message": "textDocument/didChange sent"}}]

Disable Linting for language

I have set up formatting for specific language (linting is done by separate LSP) and I am getting constant messages: lint for LanguageID not supported: <lang> logged. Is there a way to disable linting part and only keep format* configuration working for that language?

Cannot enable linting with eslint on JS files using native nvim lsp.

I'm using neovim's native LSP and I'm getting 2020/11/28 08:18:39 lint for LanguageID not supported: on the server logs. Notice that the LanguageID in the logs is empty. I tried tweaking the log level via the -loglevel cli option with no effect. How can I debug this?

Here's my configuration for reference:

lspconfig.efm.setup {
   cmd = {"efm-langserver", "-logfile", log_dir .. "/efm.log"},
   on_attach = on_attach(log_dir .. "/efm.log"),
   -- Fallback to .bashrc as a project root to enable LSP on loose files
   root_dir = lspconfig.util.root_pattern(".git/", ".bashrc"),
   -- Enable document formatting (other capabilities are off by default).
   init_options = {documentFormatting = true},
   settings = {
     rootMarkers = {".git/", ".bashrc"},
     languages = {
       javascript = {
        {
          lintCommand = "eslint -f unix --stdin",
          lintIgnoreExitCode = true,
          lintStdin = true,
        }
       },
     },
   },
 }

filetype: No filetypes defined, please define filetypes in setup() using neovim buildin LSP with nvim-lspconfig

I use the configuration file from the main repo verbatim. In my ~/.config/nvim/vim.init, I have:

lua << EOF
require "lspconfig".efm.setup { }
EOF

I have tried bash and Python files and nothing is happening. I tried running LspInfo and got this:

 Clients that match the filetype python: 
   
  Config: efm 
  	filetype: No filetypes defined, please define filetypes in setup(). 

However, at this point, I am a little lost. The filetypes seem to be defined fine since neovim can tell which file type I am editing -- and launches correctly pyright for Python files.

Any suggestion as to what I am doing wrong?

问下大佬 为什么我没安装成功

这是我的coc配置
"languageserver": {
  "golang": {
      "filetypes": ["go"],
      "command": "bingo",
      "args": ["--diagnostics-style=instant"],
      "rootPatterns": ["go.mod", ".vim/",".git/", ".hg/"]
},
  "efm": {
      "command": "efm-langserver",
      "args": [],
      "filetypes": ["vim", "eruby", "markdown"]
      }
    }
  }

报错信息:
屏幕快照 2019-03-25 下午7 33 33

Slow exit with neovim built-in lsp

Hi,

I noticed since setting up efm with built in neovim lsp that closing neovim takes some time (500ms-1sec), which was a bit strange to me. I enabled lsp logging, and tried exiting. In logs I noticed this:

[ INFO ] 2021-02-13T16:25:48+0100 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:1048 ]	"exit_handler"	{ {    _on_attach = <function 1>,    callbacks = <1>{},    cancel_request = <function 2>,    config = {      capabilities = {        callHierarchy = {          dynamicRegistration = false,          <metatable> = <2>{            __tostring = <function 3>          }        },        textDocument = {          codeAction = {            codeActionLiteralSupport = {              codeActionKind = {                valueSet = { "", "Empty", "QuickFix", "Refactor", "RefactorExtract", "RefactorInline", "RefactorRewrite", "Source", "SourceOrganizeImports", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" },                <metatable> = <table 2>              },              <metatable> = <table 2>            },            dynamicRegistration = false,            <metatable> = <table 2>          },          completion = {            completionItem = {              commitCharactersSupport = false,              deprecatedSupport = false,              documentationFormat = { "markdown", "plaintext" },              preselectSupport = false,              snippetSupport = false,              <metatable> = <table 2>            },            completionItemKind = {              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 },              <metatable> = <table 2>            },            contextSupport = false,            dynamicRegistration = false,            <metatable> = <table 2>          },          declaration = {            linkSupport = true,            <metatable> = <table 2>          },          definition = {            linkSupport = true,            <metatable> = <table 2>          },          documentHighlight = {            dynamicRegistration = false,            <metatable> = <table 2>          },          documentSymbol = {            dynamicRegistration = false,            hierarchicalDocumentSymbolSupport = true,            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 },              <metatable> = <table 2>            },            <metatable> = <table 2>          },          hover = {            contentFormat = { "markdown", "plaintext" },            dynamicRegistration = false,            <metatable> = <table 2>          },          implementation = {            linkSupport = true,            <metatable> = <table 2>          },          publishDiagnostics = {            relatedInformation = true,            tagSupport = {              valueSet = { 1, 2 },              <metatable> = <table 2>            },            <metatable> = <table 2>          },          references = {            dynamicRegistration = false,            <metatable> = <table 2>          },          rename = {            dynamicRegistration = false,            prepareSupport = true,            <metatable> = <table 2>          },          signatureHelp = {            dynamicRegistration = false,            signatureInformation = {              documentationFormat = { "markdown", "plaintext" },              <metatable> = <table 2>            },            <metatable> = <table 2>          },          synchronization = {            didSave = true,            dynamicRegistration = false,            willSave = false,            willSaveWaitUntil = false,            <metatable> = <table 2>          },          typeDefinition = {            linkSupport = true,            <metatable> = <table 2>          },          <metatable> = <table 2>        },        window = {          showDocument = {            support = false,            <metatable> = <table 2>          },          showMessage = {            messageActionItem = {              additionalPropertiesSupport = false,              <metatable> = <table 2>            },            <metatable> = <table 2>          },          workDoneProgress = true,          <metatable> = <table 2>        },        workspace = {          applyEdit = true,          configuration = true,          symbol = {            dynamicRegistration = false,            hierarchicalWorkspaceSymbolSupport = true,            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 },              <metatable> = <table 2>            },            <metatable> = <table 2>          },          workspaceFolders = true,          <metatable> = <table 2>        }      },      cmd = { "efm-langserver" },      filetypes = { "javascript", "javascriptreact" },      flags = {},      handlers = <table 1>,      init_options = {        documentFormatting = true,        <metatable> = <table 2>      },      log_level = 2,      message_level = 2,      name = "efm",      on_attach = <function 4>,      on_exit = <function 5>,      on_init = <function 6>,      root_dir = "/home/kristijan/code/myproject/api",      settings = {        languages = {          javascript = { <3>{              formatCommand = "./node_modules/.bin/prettier-eslint --stdin --single-quote --print-width 120",              formatStdin = true,              lintCommand = "./node_modules/.bin/eslint -f compact --stdin",              lintFormats = { "%f: line %l, col %c, %trror - %m", "%f: line %l, col %c, %tarning - %m" },              lintIgnoreExitCode = true,              lintStdin = true            } },          javascriptreact = { <table 3> },          <metatable> = <table 2>        },        rootMarkers = { ".git/" },        <metatable> = <table 2>      },      <metatable> = <table 2>    },    handlers = <table 1>,    id = 1,    initialized = true,    is_stopped = <function 7>,    messages = {      messages = {},      name = "efm",      progress = {},      status = {}    },    name = "efm",    notify = <function 8>,    offset_encoding = "utf-16",    request = <function 9>,    resolved_capabilities = {      call_hierarchy = false,      code_action = false,      completion = false,      declaration = false,      document_formatting = true,      document_highlight = false,      document_range_formatting = false,      document_symbol = false,      execute_command = false,      find_references = false,      goto_definition = true,      hover = false,      implementation = false,      rename = false,      signature_help = false,      signature_help_trigger_characters = {},      text_document_did_change = 1,      text_document_open_close = true,      text_document_save = false,      text_document_save_include_text = false,      text_document_will_save = false,      text_document_will_save_wait_until = false,      type_definition = false,      workspace_folder_properties = {        changeNotifications = true,        supported = true      },      workspace_symbol = false    },    rpc = {      handle = <userdata 1>,      notify = <function 10>,      pid = 122511,      request = <function 11>    },    server_capabilities = {      definitionProvider = true,      documentFormattingProvider = true,      textDocumentSync = 1,      workspace = {        workspaceFolders = {          changeNotifications = true,          supported = true        }      }    },    stop = <function 12>,    supports_method = <function 13>,    workspaceFolders = { {        name = "/home/kristijan/code/myproject/api",        uri = "file:///home/kristijan/code/myproject/api"      } },    workspace_did_change_configuration = <function 14>  } }
[ DEBUG ] 2021-02-13T16:25:48+0100 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:388 ]	"rpc.send.payload"	{  id = 2,  jsonrpc = "2.0",  method = "shutdown"}
[ DEBUG ] 2021-02-13T16:25:48+0100 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:489 ]	"decoded"	{  id = 2,  jsonrpc = "2.0",  result = vim.NIL}
[ DEBUG ] 2021-02-13T16:25:48+0100 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:388 ]	"rpc.send.payload"	{  jsonrpc = "2.0",  method = "exit"}
THIS ----> [ ERROR ] 2021-02-13T16:25:48+0100 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:455 ]	"rpc"	"efm-langserver"	"stderr"	'2021/02/13 16:25:48 jsonrpc2 handler: notification "exit" handling error: jsonrpc2: code -32601 message: method not supported: exit\n'

I'm not sure if that's causing the slowness, but I didn't see any similar error with other language servers. Here's my efm setup:

local nvim_lsp = require'lspconfig'

local eslint = {
  lintCommand = './node_modules/.bin/eslint -f compact --stdin',
  lintStdin = true,
  lintFormats = {'%f: line %l, col %c, %trror - %m', '%f: line %l, col %c, %tarning - %m'},
  lintIgnoreExitCode = true,
  formatCommand = './node_modules/.bin/prettier-eslint --stdin --single-quote --print-width 120',
  formatStdin = true,
}

nvim_lsp.efm.setup({
    init_options = { documentFormatting = true },
    root_dir = nvim_lsp.util.root_pattern('.git/'),
    filetypes = {'javascript', 'javascriptreact'},
    settings = {
      rootMarkers = {'.git/'},
      languages = {
        javascript = {eslint},
        javascriptreact = {eslint},
      }
    }
})

Other information:

  • System: Manjaro Linux
  • Neovim version: NVIM v0.5.0-dev+1085-g52397aaa0 (latest master)
  • efm-langserver commit: cac0b90

"undefined: strings.ReplaceAll" on Debian buster

Hi,

I encountered the issue while setting up coc.nvim.
To reproduce:

$ sudo apt install golang
$ go get github.com/mattn/efm-langserver
# github.com/mattn/efm-langserver/langserver
go/src/github.com/mattn/efm-langserver/langserver/handler.go:152:14: undefined: strings.ReplaceAll
go/src/github.com/mattn/efm-langserver/langserver/handler.go:277:13: undefined: strings.ReplaceAll
go/src/github.com/mattn/efm-langserver/langserver/handler.go:334:13: undefined: strings.ReplaceAll
$ go version
go version go1.11.6 linux/amd64
$ uname -srvo
Linux 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20) GNU/Linux

Question: Need help with format

Is there a reference sheet which I can use to understand and use %f, %l and other formats?

I am using a linter that emits message in this form:

Emojis should be wrapped in <span>. [Warning/jsx-a11y/accessible-emoji]

Is there a way to parse "Warning" out of it but combine both of its sides to make the message appear as

Emojis should be wrapped in <span>. [jsx-a11y/accessible-emoji]

and to tag it as a warning?

I tried %m [%tarning/%m but it is wrong as the second %m overrides the first one.

didChange with stdin = false specifies the filename of the (potentially unsaved) file

Hi! My use case is running shellcheck(1) with efm-langserver (using the nvim-lsp client). I noticed that after I made a change to my document the returned diagnostics did not match the new content, but the old one (reference: nvim-lua/diagnostic-nvim#40).

The reason is: nvim-lsp sends a textDocument/didChange whenever the user makes a change. This does not mean that the document is saved.

My configuration is essentially copied from the README:

# Cut down version of https://github.com/mattn/efm-langserver.
version: 2

tools:
  sh-shellcheck: &sh-shellcheck
    lint-command: 'shellcheck -f gcc -x'
    lint-formats:
      - '%f:%l:%c: %trror: %m'
      - '%f:%l:%c: %tarning: %m'
      - '%f:%l:%c: %tote: %m'

languages:
  sh:
    - <<: *sh-shellcheck

I traced the shellcheck invocation made by efm-langserver before and after the edit of a shell file:

shellcheck -f gcc -x /home/aktau/tmp/glop.sh # When opening file
shellcheck -f gcc -x /home/aktau/tmp/glop.sh # After editing, but the file isn't saved yet so this is identical to before.

Reading the code I also noticed that f.Text is only used when stdin is false. This means that I'd need to use shellcheck in stdin mode to get this to work. A couple of notes:

  • It would be better to switch the shellcheck example in the README to use stdin (-).
  • I think it would be a good idea to check how other language servers fix this (or, for example, syntastic, which also uses shellcheck). For example, it may make sense to just pass /dev/stdin instead of the filename for all tools on *nix operating systems. Or to create a temporary file (some tools may require a seekable file, or for Windows this may be necessary).

Providing binary releases

Hello,

do you think it would be possible to provide binary releases so the project can be used without go installed? (I do not know how much effort is behind it).

Can't get formatting or linting working python

Been trying now for a while to get formatting and linting working for lua and python through lsp-config in neovim.
I have the following table

      {
        on_attach = on_attach,
        cmd = {'efm-langserver', '-logfile', '/tmp/efm.log', '-loglevel', '5'},
        init_options = {documentFormatting = true},
        filetypes = {"lua", "python"},
        settings = {
            rootMarkers = {".git/"},
            languages = {
                lua = {
                    formatCommand = "lua-format -i",
                    formatStdin = true,
                },
                python = {
                    flake8 = {
                        lintCommand =  'flake8 --stdin-display-name ${INPUT} -',
                        lintStdin =  true,
                        lintFormats = {'%f = %l:%c: %m'}
                    },
                    yapf = {
                        formatCommand =  'yapf --quiet',
                        formatStdin =  true,
                    },
                    isort =  {
                        formatCommand =  'isort --quiet -',
                        formatStdin =  true,
                    },
                },
            },
        },
    },

which I'm passing to require('lspconfig')['efm'].setup.

Looking into the log file the lines which might give some insights into what's wrong are:

2021/03/22 15:02:57 jsonrpc2 handler: notification "workspace/didChangeConfiguration" handling error: json: cannot unmarshal object into Go struct field Config.settings.languages of type []langserver.Language

and

2021/03/22 15:02:57 lint for LanguageID not supported: lua

same thing for python and formatting.

panic: runtime error: slice bounds out of range [:-1]

Hi there, thank you very much for this cool project!

I noticed with a certain config, the server panics when starting up efm for Python files. In my local tests, it only happens if I try to use this script as a lint-command: https://github.com/fsouza/vimfiles/blob/main/langservers/bin/blackd-format

Here's the stacktrace:

panic: runtime error: slice bounds out of range [:-1]

goroutine 18 [running]:
github.com/mattn/efm-langserver/langserver.(*file).wordat(0xc0001119e0, 0x13, 0x4f, 0x0, 0x1)
        /users/fsouza/.go/pkg/mod/github.com/mattn/[email protected]/langserver/handler.go:134 +0x2ed
github.com/mattn/efm-langserver/langserver.(*langhandler).lint(0xc000160120, 0xc000114b00, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0)
        /users/fsouza/.go/pkg/mod/github.com/mattn/[email protected]/langserver/handler.go:340 +0xc55
github.com/mattn/efm-langserver/langserver.(*langhandler).linter(0xc000160120)
        /users/fsouza/.go/pkg/mod/github.com/mattn/[email protected]/langserver/handler.go:191 +0x9c
created by github.com/mattn/efm-langserver/langserver.newhandler
        /users/fsouza/.go/pkg/mod/github.com/mattn/[email protected]/langserver/handler.go:82 +0x13f

I can try to create a small reproducer if this helps, but I was wondering if we should simply return an empty string in that handler when currPos doesn't change in the loop? Something like:

diff --git a/langserver/handler.go b/langserver/handler.go
index 6869872..4d2f159 100644
--- a/langserver/handler.go
+++ b/langserver/handler.go
@@ -131,6 +131,9 @@ func (f *File) WordAt(pos Position) string {
                }
                prevCls = currCls
        }
+       if currPos < 0 {
+               return ""
+       }
        return string(utf16.Decode(chars[prevPos:currPos]))
 }

Can't format handlebars files

I have a formatter for handlebars files setup using the Nvim LSP config.

When I save the file, I get the following error:

2021/02/23 11:48:53 jsonrpc2: <— error #22: textDocument/formatting: {“code”:0,”message”:”format for LanguageID not supported: html.handlebars”,”data”:null}

The config looks like this:

ember_template_lint = {
  lintCommand = "./node_modules/.bin/ember-template-lint --filename /foo/bar < ${INPUT}",
  formatCommand = "./node_modules/.bin/prettier --parser=glimmer --write --stdin --stdin-filepath ${INPUT}",
  formatStdin = true,
  lintStdin = true,
  rootMarkers = {'package.json'},
}

lspconfig.efm.setup {
  on_attach = function(client)
    client.resolved_capabilities.document_formatting = true
    client.resolved_capabilities.goto_definition = false

    custom_on_attach(client)
  end,
  cmd = {'efm-langserver', '-logfile', '/tmp/efm.log', '-loglevel', '5'},
  root_dir = lspconfig.util.root_pattern('.git'),
  init_options = {
    document_formatting = true,
    codeAction = true
  },
  settings = {
    languages = {
      ["html.handlebars"] = { ember_template_lint }
    }
  },
  filetypes = {
    "html.handlebars",
  },
}

panic: invalid memory address or nil pointer dereference when linting svelte files

FWIW it works fine with other file types.

[ ERROR ] 2021-04-23T10:48:02+0100 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:457 ]   "rpc"   "/home/me/.local/share/nvim/lspinstall/efm/./efm-langserver"     "stderr"        "2021/04/23 10:48:02 eslint_d --fix-to-stdout --stdin --stdin-filename=/home/me/projects/svelte-course/src/App.svelte: \n"
[ ERROR ] 2021-04-23T10:48:02+0100 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:457 ]   "rpc"   "/home/me/.local/share/nvim/lspinstall/efm/./efm-langserver"     "stderr"        "panic: runtime error: invalid memory address or nil pointer dereference\n[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x56df26]\n\ngoroutine 18 [running]:\ngithub.com/mattn/efm-langserver/langserver.(*langHandler).linter.func1(0xc0000b4000, 0x5efcd8, 0xc000104000, 0xc000022c80, 0x35)\n\t/home/me/.local/share/nvim/lspinstall/efm/pkg/mod/github.com/mattn/[email protected]/langserver/handler.go:250 +0x1c6\ncreated by github.com/mattn/efm-langserver/langserver.(*langHandler).linter\n\t/home/me/.local/share/nvim/lspinstall/efm/pkg/mod/github.com/mattn/[email protected]/langserver/handler.go:233 +0xde\n"

Add LICENSE file

The README says LICENSE is MIT but the LICENSE itself is missing in the repo.

Support for dynamic code actions

Hey,

I've been experimenting with neovim's LSP which got me into using this language server (great work btw) for https://github.com/mantoni/eslint_d.js. It's been working nicely so far, but the one thing I've been missing is the ability to invoke a single quick fix provided by ESLint. It has also been mentioned in #86 (comment) that the author could not get code actions to work.

I am aware that one can use the formatCommand to apply all fixes this way, but this:

  1. Does not allow applying fixes selectively (only a specific fix)
  2. Does not inform how many problems will be fixed. It's more of a shoot fire aim approach
  3. I could not get it to work alongside https://github.com/fsouza/prettierd - I could either get prettier formatting or ESLint autofix.

I've been thinking of adding support for code actions to this language server and to later get it working in eslint_d. So far, I have noticed that there is some support for code actions (the Command struct), but I believe it only supports a known static set of commands provided in the language configuration.

Would you be willing to add support for getting a list of code actions from a given command? I know this is a broad topic, and I'm willing to help

EDIT: for anyone looking for eslint-disable commands support, looks like it is supported by https://github.com/jose-elias-alvarez/nvim-lsp-ts-utils which I have started using instead of efm, at least when it comes to ESLint

Format not working

I'm using Neovim's built-in LSP support to run ./node_modules/.bin/prettier on TypeScript files. Checking the logs, it seems to be working internally and newText is properly generated, and even the format succeeded message appears. However my files are not being formatted, and logs mention a $cancelRequest with the same ID of the textDocument/formatting request.

Support InitializationOptions at InitializeParams

Hey,
it would be amazing if you could support the initializationOptions field of the InitializationParms on the initialization of the server.
Having a global and central configuration file might has its advantages. But often (at least for me) you have to alternate the linter and formatter depending on the project you are working on. It would be simply nice to have this part of the protocol implemented as well.
Thanks for reading and I'm looking forward to the feedback. 🙏

Consider a Homebrew installer

hi - a quick comment.:

Homebrew is the go-to package installer for macOS, so if you'd like to increase adoption of your package, I'd recommend writing an installer and mentioning it in the docs.

flake8 through NVIM settings

Hi just an FYI, I couldn't get the flake8 and mypy to work when settings were passed through efm.setup as described here, but everything worked fine when I passed settings through the yaml file.

Enjoying the LSP thus far, thanks!

ERROR: can not read configuration: yaml: line 13: did not find expected key

I have the following error when ttrying to use efm-langserver + cocn.vim + neovim on Arch Linux:

can not read configuration: yaml: line 13: did not find expected key

Version information:

  • vim version: NVIM v0.4.3
  • node version: v10.19.0
  • coc.nvim version: 0.0.75-89c0c2380b
  • term: xterm-256color
  • platform: linux
  • efm-langserver: v0.0.9 (update: tested v0.0.10, same error)

cocn.vim configuration (~/.config/nvim/coc-settings.jso):

    // Viml, Yaml, Markdown
    "efm": {
      "command": "efm-langserver",
      "args": [],
      "filetypes": ["vim", "markdown", "yaml"]
    },

efm-langserver configuration (~/.config/efm-langserver/config.yaml):

version: 2

tools:
  vim-vint: &vim-vint
    lint-command: 'vint -'
    lint-stdin: true

  markdown-markdownlint: &markdown-markdownlint
    lint-command: 'markdownlint -s -c /home/rnp/.config/markdownlint.json'
    lint-stdin: true
    lint-formats:
      - '%f: %l: %m'

   yaml-yamllint: &yaml-yamllint
    lint-command: 'yamllint -f parsable -'
    lint-stdin: true

languages:
  vim:
    - <<: *vim-lint

  markdown:
    - <<: *markdown-markdownlint

  yaml:
    - <<: *yaml-yamllint

Help - Can't make basic setup with NeoVim for linting/diagnostics

Hey guys,
it was for a long time on my ToDo list. Now I started to migrate for using this general purpose language server as my primary linting and formatting tool within NeoVim. But unfortunately I do already fail for the first linter shellcheck (I tried others, but also without success). I tried now a while and searched for help. But I just don't get it working. Therefore I'm now sharing my current state here and hope someone can spot the mistake.

As I stated I'm using the NeoVim built-in language server client. In addition I use the nvim-lspconfig plugin.
First my binary versions:

  • nvim: v0.5.0-dev+1012-gfe1ebea33
  • efm-langserver: 0.0.26-1
  • shellcheck: 0.7.1

In my NeoVim configuration I have the following Lua snippet:

local shellcheck = {
 lintCommand = "shellcheck -f gcc -x -",
 lintStdin = true,
 lintFormats = {"%f=%l:%c: %trror: %m", "%f=%l:%c: %tarning: %m", "%f=%l:%c: %tote: %m"}
}

require('lspconfig').efm.setup({
 cmd = {"efm-langserver", "-logfile", "/tmp/efm.log", "-loglevel", "1" },
 settings = {
   languages = {
     sh = { shellcheck },
   }
 }
})

The test script I use is the following:

#!/bin/bash
var='foo  bar'
echo $var

Running shellcheck in the shell looks like that:

$ /bin/cat ./test.sh | shellcheck -f gcc -x -
-:3:6: note: Double quote to prevent globbing and word splitting. [SC2086]

Now I open the the file with NeoVim. Here some command output:

  • :echo &ft: sh
  • :lua print(vim.inspect(#vim.lsp.buf_get_clients())): 1
  • :lua vim.lsp.diagnostic.set_loclist() + :echo len(getloclist(0)): 0
  • :lua print(vim.inspect(vim.lsp.buf_get_clients()[1])):
    output
    {
    _on_attach = <function 1>,
    callbacks = <1>{
    ["client/registerCapability"] = <function 2>,
    ["window/logMessage"] = <function 3>,
    ["window/showMessage"] = <function 4>,
    ["workspace/configuration"] = <function 5>
    },
    cancel_request = <function 6>,
    config = {
    capabilities = {
    callHierarchy = {
    dynamicRegistration = false,
    = <2>{
    __tostring = <function 7>
    }
    },
    textDocument = {
    codeAction = {
    codeActionLiteralSupport = {
    codeActionKind = {
    valueSet = { "", "Empty", "QuickFix", "Refactor", "RefactorExtract", "RefactorInline", "RefactorRewrite", "Source", "SourceOrganizeImports", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" },
    = <table 2>
    },
    = <table 2>
    },
    dynamicRegistration = false,
    = <table 2>
    },
    completion = {
    completionItem = {
    commitCharactersSupport = false,
    deprecatedSupport = false,
    documentationFormat = { "markdown", "plaintext" },
    preselectSupport = false,
    snippetSupport = false,
    = <table 2>
    },
    completionItemKind = {
    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 },
    = <table 2>
    },
    contextSupport = false,
    dynamicRegistration = false,
    = <table 2>
    },
    declaration = {
    linkSupport = true,
    = <table 2>
    },
    definition = {
    linkSupport = true,
    = <table 2>
    },
    documentHighlight = {
    dynamicRegistration = false,
    = <table 2>
    },
    documentSymbol = {
    dynamicRegistration = false,
    hierarchicalDocumentSymbolSupport = true,
    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 },
    = <table 2>
    },
    = <table 2>
    },
    hover = {
    contentFormat = { "markdown", "plaintext" },
    dynamicRegistration = false,
    = <table 2>
    },
    implementation = {
    linkSupport = true,
    = <table 2>
    },
    publishDiagnostics = {
    relatedInformation = true,
    tagSupport = {
    valueSet = { 1, 2 },
    = <table 2>
    },
    = <table 2>
    },
    references = {
    dynamicRegistration = false,
    = <table 2>
    },
    rename = {
    dynamicRegistration = false,
    prepareSupport = true,
    = <table 2>
    },
    signatureHelp = {
    dynamicRegistration = false,
    signatureInformation = {
    documentationFormat = { "markdown", "plaintext" },
    = <table 2>
    },
    = <table 2>
    },
    synchronization = {
    didSave = true,
    dynamicRegistration = false,
    willSave = false,
    willSaveWaitUntil = false,
    = <table 2>
    },
    typeDefinition = {
    linkSupport = true,
    = <table 2>
    },
    = <table 2>
    },
    window = {
    showDocument = {
    support = false,
    = <table 2>
    },
    showMessage = {
    messageActionItem = {
    additionalPropertiesSupport = false,
    = <table 2>
    },
    = <table 2>
    },
    workDoneProgress = true,
    = <table 2>
    },
    workspace = {
    applyEdit = true,
    configuration = true,
    symbol = {
    dynamicRegistration = false,
    hierarchicalWorkspaceSymbolSupport = true,
    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 },
    = <table 2>
    },
    = <table 2>
    },
    workspaceFolders = true,
    = <table 2>
    }
    },
    cmd = { "efm-langserver" },
    flags = {},
    handlers = <table 1>,
    init_options = vim.empty_dict(),
    log_level = 2,
    message_level = 2,
    name = "efm",
    on_attach = <function 8>,
    on_exit = <function 9>,
    on_init = <function 10>,
    root_dir = "/tmp/tmp.2hNc8BEJhu",
    settings = {
    languages = {
    sh = { {
    lintCommand = "shellcheck -f gcc -x -",
    lintFormats = { "%f=%l:%c: %trror: %m", "%f=%l:%c: %tarning: %m", "%f=%l:%c: %tote: %m" },
    lintStdin = true
    } },
    = <table 2>
    },
    = <table 2>
    },
    = <table 2>
    },
    handlers = <table 1>,
    id = 1,
    initialized = true,
    is_stopped = <function 11>,
    messages = {
    messages = {},
    name = "efm",
    progress = {},
    status = {}
    },
    name = "efm",
    notify = <function 12>,
    offset_encoding = "utf-16",
    request = <function 13>,
    resolved_capabilities = {
    call_hierarchy = false,
    code_action = false,
    completion = false,
    declaration = false,
    document_formatting = false,
    document_highlight = false,
    document_range_formatting = false,
    document_symbol = false,
    execute_command = false,
    find_references = false,
    goto_definition = true,
    hover = false,
    implementation = false,
    rename = false,
    signature_help = false,
    signature_help_trigger_characters = {},
    text_document_did_change = 1,
    text_document_open_close = true,
    text_document_save = false,
    text_document_save_include_text = false,
    text_document_will_save = false,
    text_document_will_save_wait_until = false,
    type_definition = false,
    workspace_folder_properties = {
    changeNotifications = true,
    supported = true
    },
    workspace_symbol = false
    },
    rpc = {
    handle = <userdata 1>,
    notify = <function 14>,
    pid = 1359845,
    request = <function 15>
    },
    server_capabilities = {
    definitionProvider = true,
    textDocumentSync = 1,
    workspace = {
    workspaceFolders = {
    changeNotifications = true,
    supported = true
    }
    }
    },
    stop = <function 16>,
    supports_method = <function 17>,
    workspaceFolders = { {
    name = "/tmp/tmp.2hNc8BEJhu",
    uri = "file:///tmp/tmp.2hNc8BEJhu"
    } },
    workspace_did_change_configuration = <function 18>
    }

The log file get created but is empty.


Thanks for any help in advance! 🙏

Panic when closing

I'm not sure if this is a neovim or efm issue, but when I close neovim with an efm-langserver attached to it I get the following message: Client 1 quit with exit code 2 and signal 0.

In the lsp logging I find these message everytime I close:

[ ERROR ] 2021-04-09T08:52:48+0200 ] ...e/tools/nvim/head/share/nvim/runtime/lua/vim/lsp/rpc.lua:457 ]	"rpc"	"efm-langserver"	"stderr"	"2021/04/09 08:52:48 jsonrpc2 handler: sending response 3: jsonrpc2: connection is closed\n2021/04/09 08:52:48 efm-langserver: connections closed\n"
[ ERROR ] 2021-04-09T08:52:48+0200 ] ...e/tools/nvim/head/share/nvim/runtime/lua/vim/lsp/rpc.lua:457 ]	"rpc"	"efm-langserver"	"stderr"	"panic: send on closed channel\n\n"
[ ERROR ] 2021-04-09T08:52:48+0200 ] ...e/tools/nvim/head/share/nvim/runtime/lua/vim/lsp/rpc.lua:457 ]	"rpc"	"efm-langserver"	"stderr"	"goroutine 33 [running]:\ngithub.com/mattn/efm-langserver/langserver.(*langHandler).lintRequest.func1()\n\tgithub.com/mattn/efm-langserver/langserver/handler.go:202 +0x5d\ncreated by time.goFunc\n\ttime/sleep.go:180 +0x45\n"

Is this an efm issue? (I don't know much about go).

Prettier not Adding Semicolon

Nvim 0.5.5
OS: Mac 11.2.3


So I am getting close on setting up efm for formatting my typescript files. The only issue I am having is its not adding semi colons, even thought my .prettierrc has semi = true.

image

Here is my config

local prettierFormat = {formatCommand = './node_modules/.bin/prettier --stdin-filepath ${INPUT}', formatStdin = true}

local eslintFormat = {
  lintCommand = './node_modules/.bin/eslint -f unix --stdin --stdin-filename ${INPUT}',
  lintIgnoreExitCode = true,
  lintStdin = true,
  lintFormats = {'%f:%l:%c: %m'},
  formatCommand = './node_modules/.bin/eslint --fix-dry-run --stdin --stdin-filename=${INPUT}',
  formatStdin = true
}

-- ~/.local/share/nvim/lspinstall/efm
require'lspconfig'.efm.setup {
  -- cmd = {'efm-langserver'},
  cmd = {'/Users/jcostanzo/.local/share/nvim/lspinstall/efm/efm-langserver'},
  -- cmd = {'efm-langserver', '-logfile', '/tmp/efm.log', '-loglevel', '5'},
  init_options = {documentFormatting = true},
  filetypes = {'lua', 'typescriptreact', 'typescript'},
  settings = {
    rootMarkers = {'.git/'},
    languages = {
      lua = {luaFormat},
      typescriptreact = {prettierFormat, eslintFormat},
      typescript = {prettierFormat, eslintFormat}
    }
  }
}

cmd('autocmd BufWritePre *.lua lua vim.lsp.buf.formatting_sync(nil, 1500)')
cmd('autocmd BufWritePre *.tsx lua vim.lsp.buf.formatting_sync(nil, 1500)')
cmd('autocmd BufWritePre *.ts lua vim.lsp.buf.formatting_sync(nil, 1500)')
cmd('autocmd BufWritePre *.jsx lua vim.lsp.buf.formatting_sync(nil, 1500)')
cmd('autocmd BufWritePre *.js lua vim.lsp.buf.formatting_sync(nil, 1500)')

Here is my tsserver setup

local on_attach = require'compe'.on_attach

require'lspconfig'.tsserver.setup {
  filetypes = {'javascript', 'javascriptreact', 'javascript.jsx', 'typescript', 'typescriptreact', 'typescript.tsx'},
  on_attach = on_attach,
  root_dir = require('lspconfig/util').root_pattern('package.json', 'tsconfig.json', 'jsconfig.json', '.git'),
  settings = {documentFormatting = false}
}

Could it be that efm is id 2 and tsserver is overriding?

trim spaces on left

I think you should trim space on the left for each line.
I was trying to use efm with standard and here are the kind of output I got:

> standard -v /Users/me/Documents/prj/my-api/lib/app.js: 
standard: Use JavaScript Standard Style (https://standardjs.com)
standard: Run `standard --fix` to automatically fix some problems.
  /Users/me/Documents/prj/my-api/lib/app.js:4:1: Expected indentation of 2 spaces but found 8. (indent)
  /Users/me/Documents/prj/my-api/lib/app.js:5:1: Expected indentation of 4 spaces but found 2. (indent)
  /Users/me/Documents/prj/my-api/lib/app.js:6:1: Expected indentation of 2 spaces but found 4. (indent)
  /Users/me/Documents/prj/my-api/lib/app.js:8:1: Expected indentation of 2 spaces but found 4. (indent)

The linter only work if you use " %f:%l:%c: %m" for lint-formats

It also could be an option from errorformat

If you could provide some troubleshooting process for this kind of bug or better debug logs (adding if the entry was valid) I think it could help a lot of people to debug their linter.
I can make a PR to tell people to try to parse their linter output with errorformat i you want (but i can't do much more cause i don't know go 😢 ).

pylint: need column offset configuration option

First off, I love this tool! It's got big dreams and I'd like it to keep getting better! This is issue 1 of 2 related to pylint.

pylint uses 0 indexes for columns, not 1 indexes. In efm, the current lint_offset configuration only works for rows, so it's probably necessary to add support for columns as well. If this isn't fixed, all linting messages will be one column behind where they should be (except for the 0's; they have nowhere backward to go!).

Example error messages (0-indexed):

file.py:13:0: C0116: Missing function or method docstring (missing-function-docstring)
file.py:27:0: R0902: Too many instance attributes (8/7) (too-many-instance-attributes)
file.py:40:8: W0612: Unused variable 'response' (unused-variable)
file.py:55:4: E0102: method already defined line 36 (function-redefined)
file.py:71:4: E0602: Undefined variable 'url' (undefined-variable)
file.py:6:0: W0611: Unused Final imported from typing (unused-import)

Screenshot of editor:

image

Notice how the error message next to def hello is one column behind?

Global initialization options vs local capabilities

The initialization options (i.e. init_options in here https://github.com/mattn/efm-langserver#configuration-for-neovim-buildin-lsp-with-nvim-lspconfig) are global (i.e. you specify globally for efm config whether it supports document formatting, for example) however the actual capability is local to the language.

More concretely:

I use efm to format lua AND to lint go code. I DO want the documentFormatting capability to be true for the lua LSP server, however I want the same capability to be false for the go/efm LSP server, since I also use gopls and I want that one to handle the formatting, not both. The problem is, I can only set that setting once per efm config, not for each language individually.

What am I missing? Doesn't it make more sense to have those capabilities defined locally (and even better, inferred - i.e., if I define a format command, then turn on documentFormatting capability for THAT particular language)?

now it cannot be installed with `go get`

$ go get github.com/mattn/efm-langserver
# github.com/mattn/efm-langserver/langserver
go/src/github.com/mattn/efm-langserver/langserver/handler.go:502:3: not enough arguments to return
go/src/github.com/mattn/efm-langserver/langserver/handler.go:502:11: h.handleTextDocumentCompletion undefined (type *langHandler has no field or method handleTextDocumentCompletion)

It looks like it has compile-error...

Vint not working

Using coc.vim I was noticing that the linting was not matching up with what I had received when I just ran vint on my vimrc and in fact I was not receiving any linting. I then tested what would happen if I piped from vint the langserver command (like so vint .vimrc | efm-langserver) and I received nothing but the two following lines.
2020/01/15 13:00:32 efm-langserver: reading on stdin, writing on stdout
2020/01/15 13:00:33 efm-langserver: connections closed

When I run vint on the file directly however I receive the following, so I know that it is not due to a lack of linting by vint.
.vimrc:99:28: Use robust operators ==#or==?instead of== (see Google VimScript Style Guide (Matching))
.vimrc:143:3: autocmd should execute in an augroup or execute with a group (see :help :autocmd)
.vimrc:222:1: autocmd should execute in an augroup or execute with a group (see :help :autocmd)

I am new to both coc.vim and emf-langserver and therefore could be doing something totally wrong or overlooking something obvious.

Wrong initialize options

I got

2019/02/06 15:02:07 efm-langserver: reading on stdin, writing on stdout
[Trace - 3:02:07 PM] Received response 'initialize - (0)' in 27ms.
Result: {
    "capabilities": {
        "textDocumentSync": 1,
        "completionProvider": {
            "triggerCharacters": null
        }
    }
}

in language server output, it should set completionProvider to null if the language server not support it.

Can't get to use this language server for eslint

Hello! I'm trying to switch from diagnostic-languageserver to efm-langserver but I can't get it to work properly. I'm trying to make eslint work, but with no success. With diagnostic-languageserver it works and error messages is displayed, but with efm-langserver no. I have eslint and eslint_d installed globally and both is working ok. Also using neovim with lspconfig on the latest commit on master. I'm using this dotfiles for base config: https://github.com/lukas-reineke/dotfiles. efm-langserver is installed using go get and I can spawn it from terminal.

This is my config so far:

local root_markers = { ".git/" }

local eslint = {
  -- lintCommand = "eslint_d -f unix --stdin",
  lintCommand = "eslint -f unix --stdin",
  lintStdin = true,
  lintIgnoreExitCode = true
}

local languages = {
  javascript = { eslint },
  javascriptreact = { eslint },
  typescript = { eslint },
  typescriptreact = { eslint }
}

require("lspconfig").efm.setup({
  on_attach = on_attach,
  cmd = { "efm-langserver" },
  root_dir = require("lspconfig").util.root_pattern(unpack(root_markers)),
  settings = {
    rootMarkers = root_markers,
    languages = languages
  },
  filetypes = vim.tbl_keys(languages)
})

Tried everything and nothing works. I don't know if I'm missing something. Thanks a lot!

undefined: strings.ReplaceAll

# github.com/mattn/efm-langserver/langserver
../go/src/github.com/mattn/efm-langserver/langserver/handler.go:272:10: undefined: strings.ReplaceAll

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.