efm-langserver: 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, <metatable> = <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” }, <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” }, 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 } }, <metatable> = <table 2> }, <metatable> = <table 2> }, <metatable> = <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! 🙏
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 15
Thanks for the kind hint! I’ll definitely give this a try to see if I can make it work this way. But in the end I would highly prefer to not have this configuration file. Especially because I need the update settings functionality to alternate linters and formatters on project basis.
I’m glad you managed to resolve your issue. 🤗
Ok I fixed it, found an unmarshal error in the log. Thanks again for your help!
I had
lintFormats = '%f:%l:%c: %m'
in a linter for a different language. Changing it tolintFormats = { '%f:%l:%c: %m' }
fixed it.Alright.Thanks for you help. I must admit that I can’t tell what the exact issue was. But NeoVim still lacks in propagating Lua syntax errors in vim scripts. 😑 But it works now and I’m super happy and excited to use this language server now! 🥳
@weilbith I had similar issues in getting a linter to work with markdown (same error msg anyways). I ended up having no configurations within the nvim setup
But made sure the configurations were specified in
$HOME/.config/efm-langserver/config.yaml
. Not sure if you can make efm-langserver use spellcheck through such a config file, YMMV.I also noticed you can try to increase the log level. I set it arbitrarily to 10 (as opposed to 1, that I saw in an example), which gave more information than just “languageID not supported”.