efm-langserver
General purpose Language Server that can use specified error message format generated from specified command. This is useful for editing code with linter.
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
.
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,
"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.
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
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
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'
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
html:
- <<: *html-prettier
javascript:
- <<: *javascript-eslint
json:
- <<: *json-fixjson
- <<: *json-jq
# - <<: *json-prettier
lua:
- <<: *lua-lua-format
make:
- <<: *make-checkmake
markdown:
- <<: *markdown-markdownlint
- <<: *markdown-pandoc
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
}
}
}
}
vim-lsp
Configuration foraugroup 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.
coc.nvim
Configuration forcoc-settings.json
// languageserver
"languageserver": {
"efm": {
"command": "efm-langserver",
"args": [],
// custom config path
// "args": ["-c", "/path/to/your/config.yaml"],
"filetypes": ["vim", "eruby", "markdown", "yaml"]
}
},
elgot
Configuration forAdd to eglot-server-programs with major mode you want.
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
`(markdown-mode . ("efm-langserver"))))
neovim builtin LSP with nvim-lspconfig
Configuration forinit.vim
lua << EOF
require "lspconfig".efm.setup {
init_options = {documentFormatting = true},
settings = {
rootMarkers = {".git/"},
languages = {
lua = {
{formatCommand = "lua-format -i", formatStdin = true}
}
}
}
}
EOF
- be sure to declare
languages
as a 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"}
}
- install supported formatters
efm does not include formatters for any languages, you must install these manually, e.g.
- lua: LuaFormatter
- python: yapf isort
- etc...
Supported Lint tools
- vint for Vim script
- markdownlint-cli for Markdown
Installation
go install github.com/mattn/efm-langserver@latest
Homebrew
brew install efm-langserver
License
MIT
Author
Yasuhiro Matsumoto (a.k.a. mattn)