{"id":13898129,"url":"https://github.com/iamcco/diagnostic-languageserver","last_synced_at":"2025-05-16T10:07:53.548Z","repository":{"id":41432396,"uuid":"175437531","full_name":"iamcco/diagnostic-languageserver","owner":"iamcco","description":"diagnostic language server integrate with linters","archived":false,"fork":false,"pushed_at":"2024-08-30T04:55:39.000Z","size":137,"stargazers_count":427,"open_issues_count":26,"forks_count":29,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-09T05:04:53.808Z","etag":null,"topics":["coc","diagnostic","linter","lsp","neovim","vim"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iamcco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":"https://github.com/iamcco/markdown-preview.nvim#buy-me-a-coffee-%EF%B8%8F"}},"created_at":"2019-03-13T14:29:47.000Z","updated_at":"2025-04-06T05:13:29.000Z","dependencies_parsed_at":"2022-08-10T02:23:10.872Z","dependency_job_id":"fc0078de-b8c2-4ef6-a70b-42f1a1f6a49f","html_url":"https://github.com/iamcco/diagnostic-languageserver","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamcco%2Fdiagnostic-languageserver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamcco%2Fdiagnostic-languageserver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamcco%2Fdiagnostic-languageserver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamcco%2Fdiagnostic-languageserver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iamcco","download_url":"https://codeload.github.com/iamcco/diagnostic-languageserver/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254509476,"owners_count":22082891,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coc","diagnostic","linter","lsp","neovim","vim"],"created_at":"2024-08-06T18:04:06.051Z","updated_at":"2025-05-16T10:07:48.540Z","avatar_url":"https://github.com/iamcco.png","language":"TypeScript","funding_links":["https://github.com/iamcco/markdown-preview.nvim#buy-me-a-coffee-%EF%B8%8F"],"categories":["TypeScript"],"sub_categories":[],"readme":"# diagnostic-languageserver\n\n\u003e General purpose Language Server that integrate with\n\u003e linter to support diagnostic features\n\n## Main features\n\n- diagnostic with linters\n- document format\n\n**screenshot with neovim and coc**\n![image](https://user-images.githubusercontent.com/5492542/54487533-15590b80-48d2-11e9-8cba-7e58c0edcf6f.png)\n\n## Install\n\n``` bash\nyarn global add diagnostic-languageserver\n```\n\n\u003e make sure your yarn's global bin path is include in `PATH`\n\n\u003e for example `export PATH=\"$(yarn global bin):$PATH\"`\n\n## Config \u0026 Document\n\nlanguageserver config:\n\n``` jsonc\n{\n  \"languageserver\": {\n    \"dls\": {\n      \"command\": \"diagnostic-languageserver\",\n      \"args\": [\"--stdio\", \"--log-level\", \"2\"],\n      \"filetypes\": [ \"sh\", \"email\" ], // filetypes that you want to enable this lsp\n      \"initializationOptions\": {\n        \"linters\": {\n          ...\n        },\n        \"filetypes\": {\n          ...\n        },\n        \"formatters\": {\n          ...\n        },\n        \"formatFiletypes\": {\n          ...\n        }\n      }\n    }\n  }\n}\n```\n\n`linters` field:\n\n```jsonc\n{\n  \"linterName\": {                                    // linter name, for example: vint\n    \"command\": \"shellcheck\",                         // linter command\n    \"rootPatterns\": [],                              // root patterns, default empty array\n    \"isStdout\": true,                                // use stdout output, default true\n    \"isStderr\": false,                               // use stderr output, default false\n    \"debounce\": 100,                                 // debounce time\n    \"onSaveOnly\": false,                             // linter is triggered only when file is saved\n    \"args\": [ \"--format=gcc\", \"-\"],                  // args\n    \"offsetLine\": 0,                                 // offsetline\n    \"offsetColumn\": 0,                               // offsetColumn\n    \"sourceName\": \"shellcheck\",                      // source name\n    \"ignore\": [\".git\", \"dist/\"]                      // ignore pattern same as `.gitignore`\n                                                     // don't forget to add `rootPatterns` when using `ignore`\n                                                     // it need workspace to filter\n\n    // Using regular expressions:\n    \"formatLines\": 1,                                // how much lines for formatPattern[0] to match\n    \"formatPattern\": [\n      \"^([^:]+):(\\\\d+):(\\\\d+):\\\\s+([^:]+):\\\\s+(.*)$\",  // line match pattern (javascript regex)\n      {\n        \"sourceName\": 1,                             // diagnostic file use match group 1. Will default to the file being linted.\n        \"sourceNameFilter\": true,                    // Display diagnostics only for the current file.\n                                                     // Only works when sourceName is defined and when it contains either an absolute\n                                                     // or relative path to the file being linted. Defaults to false.\n        \"line\": 2,                                   // diagnostic line use match group 2\n        \"column\": 3,                                 // diagnostic column use match group 3\n        \"endLine\": 2,                                // diagnostic end line use match group 2. Will default to group from `line`\n        \"endColumn\": 3,                              // diagnostic end column use match group 3. Will default to group from `column`\n        \"message\": [5],                              // message to display use match group 5\n        \"security\": 4                                // security to use match group 4, ignore if linter do not support security\n      }\n    ],\n\n    // Using JSON:\n    \"parseJson\": {\n      \"errorsRoot\": \"[0].messages\",                  // dot separated path. Will default to whatever JSON is output\n                                                     // for more information see examples at https://lodash.com/docs/#get\n                                                     // %filepath will be replaced with full path to the file (like in `args`)\n\n      // All of these support lodash.get syntax.\n      \"sourceName\": \"file\",                          // propert that contains the `file`. Will default to the file being linted.\n      \"sourceNameFilter\": true,                      // Display diagnostics only for the current file.\n                                                     // Only works when sourceName is defined and when it contains either an absolute\n                                                     // or relative path to the file being linted. Defaults to false.\n      \"line\": \"line\",                                // property that contains the `line`\n      \"column\": \"column\",                            // property that contains the `column`\n      \"endLine\": \"endLine\",                          // property that contains the `endLine`. Will default to `line`\n      \"endColumn\": \"endColumn\",                      // property that contains the `endColumn`. Will default to `column`\n      \"security\": \"severity\",                        // property that contains the `security`\n      \"message\": \"${message} [${code}]\",             // message to display\n    },\n\n    \"securities\": {                                  // security keys, ignore if linter do not support security\n      \"error\": \"error\",                              // [key: string]?: \"error\" | \"warning\" | \"info\" | \"hint\"\n      \"warning\": \"warning\",\n      \"note\": \"info\"\n    },\n    \"requiredFiles\": [                               // only run linter if any of these files exist. option\n      \".shellcheckrc\",\n      \"shellcheckrc\"\n    ]\n  }\n}\n```\n\n`filetypes` field:\n\n```jsonc\n{\n  \"sh\": \"linterName\",                          // filetype: linterName or linterName[]\n  \"*\": \"linterName\"                            // `*` is for all filetypes\n}\n```\n\n`formatters` field:\n\n```jsonc\n  \"dartfmt\": {                                 // formatter name\n    \"command\": \"dartfmt\",                      // format command\n    \"args\": [ \"--fix\" ],                       // args\n    \"rootPatterns\": [],                        // root patterns, default empty array\n    \"isStdout\": true,                          // use stdout output, default true\n    \"isStderr\": false,                         // use stderr output, default false\n    \"doesWriteToFile\": false,                  // use if formatter doesn't support stdio. should be paired with `%file`\n    \"requiredFiles\": [                         // only run formatter if any of these files exist. optional\n      \".run_dartfmt\",\n    ],\n    \"ignoreExitCode\": false,                   // ignore exit code. default false: exit code \u003e 0 will not change the file.\n                                               // some formatter may exit with code \u003e 0 so you need set it to true or number[]\n                                               // exit code array that you want to ignore.\n    \"ignore\": [\".git\", \"dist/\"]                // ignore pattern same as `.gitignore`\n                                               // don't forget to add `rootPatterns` when using `ignore`\n                                               // it need workspace to filter\n  }\n```\n\n`formatFiletypes` field:\n\n```jsonc\n{\n  \"dart\": \"dartfmt\",                          // filetype: formatterName or formatterName[]\n  \"*\": \"linterName\"                           // `*` is for all filetypes\n}\n```\n\n## Args additional syntax\n\n`args: [\"%text\", \"%filename\", \"%relativepath\", \"%file\", \"%filepath\", \"%dirname\", \"%tempfile\"]`\n\n- `%filename` will replace with basename of file\n- `%text` will replace with file content\n- `%file` will replace with full path to the file and not use stdio\n- `%filepath` will replace with full path to the file\n- `%relativepath` will replace with relative path of file\n- `%dirname` will replace with dirname of file\n- `%tempfile` will replace with the full path to a temporary file written with the contents\n  of the document and not use stdio; this file will automatically be deleted when the\n  command completes\n\n## How to config a new linter\n\n[shellcheck](https://github.com/koalaman/shellcheck) for example:\n\nfile `test.sh`:\n\n``` sh\n#!/usr/bin/env bash\n\necho `ls -al`\n```\n\nthen:\n\n```bash\nshellcheck --format=gcc test.sh\n```\n\noutput:\n\n```text\nt.sh:3:6: warning: Quote this to prevent word splitting. [SC2046]\nt.sh:3:6: note: Useless echo? Instead of 'echo $(cmd)', just use 'cmd'. [SC2005]\nt.sh:3:6: note: Use $(...) notation instead of legacy backticked `...`. [SC2006]\n```\n\nwrite pattern to match the line for `line` `column` `message` `security`:\n\n```javascript\nconst line = \"t.sh:3:6: warning: Quote this to prevent word splitting. [SC2046]\"\nconst formatPattern = \"^[^:]+:(\\\\d+):(\\\\d+):\\\\s+([^:]+):\\\\s+(.*)$\"\nconst match = line.match(new RegExp(formatPattern))\nconsole.log(match)\n```\n\noutput:\n\n``` jsonc\n{\n  0: \"t.sh:3:6: warning: Quote this to prevent word splitting. [SC2046]\"\n  1: \"3\"\n  2: \"6\"\n  3: \"warning\"\n  4: \"Quote this to prevent word splitting. [SC2046]\"\n}\n```\n\nso you got:\n\n- `line`: `match[1]`\n- `column`: `match[2]`\n- `message`: `match[4]`\n- `security`: `match[3]`\n\nand your `formatPattern` field will be:\n\n```jsonc\n\"formatPattern\": [\n  \"^[^:]+:(\\\\d+):(\\\\d+):\\\\s+([^:]+):\\\\s+(.*)$\",    // line match pattern (javascript regex)\n  {\n    \"line\": 1,                                     // diagnostic line use match group 1\n    \"column\": 2,                                   // diagnostic column use match group 2\n    \"message\": [4],                                // message to display use match group 4\n    \"security\": 3                                  // security to use match group 3, ignore if linter do not support security\n  }\n]\n```\n\n\u003e **Notes**\n\u003e if the linter's message for per issue more then one line, you have to set the `formatLines` to fill your pattern,\n\u003e and you can view the languagetool pattern for example which `formatLines = 2`\n\n## Example with [coc.nvim](https://github.com/neoclide/coc.nvim)\n\n\u003e Each LSP client should support `initializationOptions` option,\n\u003e all you need for `diagnostic-languageserver` is put the config in `initializationOptions` option.\n\n1. [shellcheck](https://github.com/koalaman/shellcheck) for shell\n2. [languagetool](https://github.com/languagetool-org/languagetool) for grammer check\n3. more [Linters](https://github.com/iamcco/diagnostic-languageserver/wiki/Linters) config example.\n\ncoc-settings.json:\n\n\u003e you can use this extension https://github.com/iamcco/coc-diagnostic\n\n``` jsonc\n{\n  \"languageserver\": {\n    \"dls\": {\n      \"command\": \"diagnostic-languageserver\",\n      \"args\": [\"--stdio\"],\n      \"filetypes\": [ \"sh\", \"email\", \"dart\" ],\n      \"initializationOptions\": {\n        \"linters\": {\n          \"shellcheck\": {\n            \"command\": \"shellcheck\",\n            \"debounce\": 100,\n            \"args\": [ \"--format=gcc\", \"-\"],\n            \"offsetLine\": 0,\n            \"offsetColumn\": 0,\n            \"sourceName\": \"shellcheck\",\n            \"formatLines\": 1,\n            \"formatPattern\": [\n              \"^[^:]+:(\\\\d+):(\\\\d+):\\\\s+([^:]+):\\\\s+(.*)$\",\n              {\n                \"line\": 1,\n                \"column\": 2,\n                \"message\": 4,\n                \"security\": 3\n              }\n            ],\n            \"securities\": {\n              \"error\": \"error\",\n              \"warning\": \"warning\",\n              \"note\": \"info\"\n            }\n          },\n          \"languagetool\": {\n            \"command\": \"languagetool\",\n            \"debounce\": 200,\n            \"args\": [\"-\"],\n            \"offsetLine\": 0,\n            \"offsetColumn\": 0,\n            \"sourceName\": \"languagetool\",\n            \"formatLines\": 2,\n            \"formatPattern\": [\n              \"^\\\\d+?\\\\.\\\\)\\\\s+Line\\\\s+(\\\\d+),\\\\s+column\\\\s+(\\\\d+),\\\\s+([^\\\\n]+)\\nMessage:\\\\s+(.*)$\",\n              {\n                \"line\": 1,\n                \"column\": 2,\n                \"message\": [4, 3]\n              }\n            ],\n          }\n        },\n        \"formatters\": {\n          \"dartfmt\": {\n            \"command\": \"dartfmt\",\n            \"args\": [ \"--fix\" ],\n          }\n        },\n        \"filetypes\": {\n          \"sh\": \"shellcheck\",\n          \"email\": \"languagetool\"\n        },\n        \"formatFiletypes\": {\n          \"dart\": \"dartfmt\"\n        }\n      }\n    }\n  }\n}\n```\n\n## TODO\n\n- [x] local node_modules linter support like eslint or textlint\n- [x] diagnostic severity\n- [x] root pattern\n- [x] document format\n\n## References\n\n- inspired by [efm-langserver](https://github.com/mattn/efm-langserver)\n\n### Buy Me A Coffee ☕️\n\n![btc](https://img.shields.io/keybase/btc/iamcco.svg?style=popout-square)\n\n![image](https://user-images.githubusercontent.com/5492542/42771079-962216b0-8958-11e8-81c0-520363ce1059.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiamcco%2Fdiagnostic-languageserver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiamcco%2Fdiagnostic-languageserver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiamcco%2Fdiagnostic-languageserver/lists"}