Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork280
An asynchronous linter plugin for Neovim complementary to the built-in Language Server Protocol support.
License
mfussenegger/nvim-lint
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
An asynchronous linter plugin for Neovim (>= 0.9.5) complementary to thebuilt-in Language Server Protocol support.
Withale we already got an asynchronous linter, why write yet another one?
Becauseale also includes its own language server client.
nvim-lint instead has a more narrow scope: It spawns linters, parses theiroutput, and reports the results via thevim.diagnostic module.
nvim-lint complements the built-in language server client for languages wherethere are no language servers, or where standalone linters provide betterresults.
- Requires Neovim >= 0.9.5
nvim-lintis a regular plugin and can be installed via the:h packagesmechanism or via a plugin manager.
For example:
git clone \ https://github.com/mfussenegger/nvim-lint.git~/.config/nvim/pack/plugins/start/nvim-lint- If usingvim-plug:
Plug 'mfussenegger/nvim-lint' - If usingpacker.nvim:
use 'mfussenegger/nvim-lint'
Configure the linters you want to run per file type. For example:
require('lint').linters_by_ft= {markdown= {'vale'},}
To get thefiletype of a buffer you can run:= vim.bo.filetype.Thefiletype can also be a compoundfiletype. For example, if you have a bufferwith afiletype likeyaml.ghaction, you can use eitherghaction,yaml orthe fullyaml.ghaction as key in thelinters_by_ft table and the linterwill be picked up in that buffer. This is useful for linters likeactionlint in combination withvim.filetype patterns like[".*/.github/workflows/.*%.yml"] = "yaml.ghaction",
Then setup aautocmd to trigger linting. For example:
auBufWritePost*luarequire('lint').try_lint()
or with Lua auto commands:
vim.api.nvim_create_autocmd({"BufWritePost"}, {callback=function()-- try_lint without arguments runs the linters defined in `linters_by_ft`-- for the current filetyperequire("lint").try_lint()-- You can call `try_lint` with a linter name or a list of names to always-- run specific linters, independent of the `linters_by_ft` configurationrequire("lint").try_lint("cspell")end,})
Some linters require a file to be saved to disk, others support lintingstdininput. For such linters you could also define a more aggressiveautocmd, forexample on theInsertLeave orTextChanged events.
If you want to customize how the diagnostics are displayed, read:help vim.diagnostic.config.
There is a generic linter calledcompiler that uses themakeprg anderrorformat options of the current buffer.
Other dedicated linters that are built-in are:
You can register custom linters by adding them to thelinters table, butplease consider contributing a linter if it is missing.
require('lint').linters.your_linter_name= {cmd='linter_cmd',stdin=true,-- or false if it doesn't support content input via stdin. In that case the filename is automatically added to the arguments.append_fname=true,-- Automatically append the file name to `args` if `stdin = false` (default: true)args= {},-- list of arguments. Can contain functions with zero arguments that will be evaluated once the linter is used.stream=nil,-- ('stdout' | 'stderr' | 'both') configure the stream to which the linter outputs the linting result.ignore_exitcode=false,-- set this to true if the linter exits with a code != 0 and that's considered normal.env=nil,-- custom environment table to use with the external process. Note that this replaces the *entire* environment, it is not additive.parser=your_parse_function}
Instead of declaring the linter as a table, you can also declare it as afunction which returns the linter table in case you want to dynamicallygenerate some of the properties.
your_parse_function can be a function which takes three arguments:
outputbufnrlinter_cwd
Theoutput is the output generated by the linter command.The function must return a list of diagnostics as specified in:help diagnostic-structure.
You can override the environment that the linting process runs in by settingtheenv key, e.g.
env= { ["FOO"]="bar"}
Note that this completely overrides the environment, it does not add newenvironment variables. The one exception is that thePATH variable will bepreserved if it is not explicitly set.
You can generate a parse function from a Lua pattern, from anerrorformator forSARIF using the functions in thelint.parser module:
parser=require("lint.parser").for_sarif()
The function takes an optional argument:
skeleton: Default values for the diagnostics
parser=require('lint.parser').from_errorformat(errorformat)
The function takes two arguments:errorformat andskeleton (optional).
Creates a parser function from a pattern.
parser=require('lint.parser').from_pattern(pattern,groups,severity_map,defaults,opts)
The function allows to parse the linter's output using a pattern which can be either:
- A Lua pattern. See
:help lua-pattern. - A LPEG pattern object. See
:help vim.lpeg. - A function (
fun(line: string):string[]). It takes one parameter - a linefrom the linter output and must return a string array with the matches. Thearray should be empty if there was no match.
The groups specify the result format of the pattern.Available groups:
lnumend_lnumcolend_colmessagefileseveritycode
The order of the groups must match the order of the captures within the pattern.An example:
localpattern='[^:]+:(%d+):(%d+):(%w+):(.+)'localgroups= {'lnum','col','code','message'}
The captures in the pattern correspond to the group at the same position.
A mapping from severity codes to diagnostic codes
default_severity= {['error']=vim.diagnostic.severity.ERROR,['warning']=vim.diagnostic.severity.WARN,['information']=vim.diagnostic.severity.INFO,['hint']=vim.diagnostic.severity.HINT,}
The defaults diagnostic values
defaults= {["source"]="mylint-name"}
Additional options
lnum_offset: Added tolnum. Defaults to 0end_lnum_offset: Added toend_lnum. Defaults to 0end_col_offset: offset added toend_col. Defaults to-1, assumingthat the end-column position is exclusive.
You can import a linter and modify its properties. An example:
localphpcs=require('lint').linters.phpcsphpcs.args= {'-q',-- <- Add a new parameter here'--report=json','-'}
Some linters are defined as function for lazy evaluation of some properties.In this case, you need to wrap them like this:
localoriginal=require("lint").linters.terraform_validaterequire("lint").linters.terraform_validate=function()locallinter=original()linter.cmd="my_custom"returnlinterend
You can also post-process the diagnostics produced by a linter by wrapping it.For example, to change the severity of all diagnostics created bycspell:
locallint=require("lint")lint.linters.cspell=require("lint.util").wrap(lint.linters.cspell,function(diagnostic)diagnostic.severity=vim.diagnostic.severity.HINTreturndiagnosticend)
See:help vim.diagnostic.config.
If you want to have different settings per linter, you can get thenamespacefor a linter viarequire("lint").get_namespace("linter_name"). An example:
localns=require("lint").get_namespace("my_linter_name")vim.diagnostic.config({virtual_text=true },ns)
You can see which linters are running withrequire("lint").get_running().To include the running linters in the status line you could format them like this:
locallint_progress=function()locallinters=require("lint").get_running()if#linters==0thenreturn""endreturn""..table.concat(linters,",")end
Running tests requiresbusted.
Seeneorocks orUsing Neovim as Lua interpreter withLuarocks for installation instructions.
busted tests/
API docs is generated usingvimcats:
vimcats -t -f lua/lint.lua lua/lint/parser.lua > doc/lint.txtAbout
An asynchronous linter plugin for Neovim complementary to the built-in Language Server Protocol support.
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Sponsor this project
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.