Add inline-comments to ignore rules, or lookup rule documentation online.
Some LSPs provide code actions for that – this plugin adds commands for linters and LSPs that don't.
- Features
- Supported sources
- Installation
- Configuration
- Customize builtin sources
- Limitations
- API
- Credits
- Look up official rule documentation, falling back to a web search if the source does not have rule documentation.
- Add inline-comments to ignore rules like
// eslint disable-next-line some-rule
. Supports previous line, same line, and enclosing lines. - Suppress formatting with via ignore comments of the respective formatter, such
as
// prettier-ignore
. - QoL: auto-select a rule if it is the only one in the current line; if the line has no diagnostic, search forward to the next line that does.
- Includes built-in support for various linters and formatters. No plugin configuration required if you only need to use built-in sources.
- Customizing built-in sources or adding your own sources is easy. PRs to add more built-ins are welcome.
You easily add a custom source via the plugin configuration. Though, please consider making a PR to add support for a source if it is missing.
Rule data for built-in support of linters and formatters
LTeX
Lua Diagnostics.
Pyright
Ruff
basedpyright
biome
clang-tidy
eslint
markdownlint
pylint
quick-lint-js
selene
shellcheck
stylelint
stylelintplus
ts
tsserver
typescript
yamllint
- LTeX
- Lua Diagnostics.
- Pyright
- Ruff
- alex
- basedpyright
- biome
- clang-tidy
- codespell
- editorconfig-checker
- eslint
- pylint
- selene
- shellcheck
- spellwarn
- stylelint
- stylelintplus
- ts
- tsserver
- typescript
- vale-ls
- vale
- woke
- yamllint
Requirements
- nvim 0.10+
- Diagnostics provided by a source that supports Neovim's built-in diagnostics system. (nvim's built-in LSP client, efm-langserver or nvim-lint are such sources.)
-- lazy.nvim
{ "chrisgrieser/nvim-rulebook" },
-- packer
use { "chrisgrieser/nvim-rulebook" }
You can use the commands via lua functions:
vim.keymap.set("n", "<leader>ri", function() require("rulebook").ignoreRule() end)
vim.keymap.set("n", "<leader>rl", function() require("rulebook").lookupRule() end)
vim.keymap.set("n", "<leader>ry", function() require("rulebook").yankDiagnosticCode() end)
vim.keymap.set({ "n", "x" }, "<leader>rf", function() require("rulebook").suppressFormatter() end)
Alternatively, you can use the :Rulebook
ex-command:
:Rulebook ignoreRule
:Rulebook lookupRule
:Rulebook yankDiagnosticCode
:Rulebook suppressFormatter
Note that :Rulebook suppressFormatter
only supports normal mode. To add
formatter-ignore comments for a line range, you need to use the lua function
require("rulebook").suppressFormatter()
from visual mode.
The .setup()
call is optional. You only need to add a config when you want to
add or customize sources.
When adding your own source, you must add the exact, case-sensitive
source name, for example, clang-tidy
, not clang
.
require("rulebook").setup = ({
-- if no diagnostic is found in current line, search this many lines forward
forwSearchLines = 10,
ignoreComments = {
shellcheck = {
comment = "# shellcheck disable=%s",
location = "prevLine",
multiRuleIgnore = true,
multiRuleSeparator = ",",
},
-- ... (full list of sources with builtin support can be found in the README)
yourCustomSource = { -- exact, case-sensitive source-name
-- `%s` will be replaced with rule-id
comment = "// disabling-comment %s",
---@type "prevLine"|"sameLine"|"encloseLine"
location = "sameLine",
-- whether multiple rules can be ignored with one comment, defaults to `false`
multiRuleIgnore = true,
-- separator for multiple rule-ids, defaults to ", "
multiRuleSeparator = ",",
}
-- if location is "encloseLine", needs to be a list of two strings
anotherCustomSource = {
comment = {
"// disable-rule %s",
"// enable-rule %s",
},
location = "encloseLine",
}
},
ruleDocs = {
selene = "https://kampfkarren.github.io/selene/lints/%s.html"
-- ... (full list of supported sources can be found in the README)
-- Search URL when no documentation definition is available for a
-- diagnostic source. `%s` will be replaced with the diagnostic source & code.
-- Default is the DDG "Ducky Search" (automatically opening first result).
fallback = "https://duckduckgo.com/?q=%s+%%21ducky&kl=en-us",
-- the value of the rule documentations accept either a string or a function
-- * if a string, `%s` will be replaced with rule-id
-- * if a function, takes a `:h diagnostic-structure` as argument & return a url
yourCustomSource = "https://my-docs/%s.hthml",
anotherCustomSource = function(diag)
-- ...
return url
end,
}
suppressFormatter = {
lua = {
-- normal mode
ignoreBlock = "-- stylua: ignore",
location = "prevLine",
-- visual mode
ignoreRange = { "-- stylua: ignore start", "-- stylua: ignore start" },
},
}
})
The plugin uses vim.ui.select, so the appearance of the rule selection can be customized by using a UI-plugin like dressing.nvim.
Built-in sources be customized by overwriting them in the configuration:
-- example: use `disable-line` instead of the default `disable-next-line` for eslint
require("rulebook").setup = {
ignoreComments = {
eslint = {
comment = "// eslint-disable-line %s",
location = "sameLine",
},
},
}
- The diagnostics have to contain the necessary data, that is a diagnostic code
and diagnostic
source. Most
LSPs and most linters configured for
nvim-lint
/efm
do that, but some diagnostic sources do not (for example,efm
with incorrectly definederrorformat
). Please open an issue at the diagnostics provider to fix such issues. - This plugin does not hook into
vim.lsp.buf.code_action
, but provides its own selector.
The function require("rulebook").hasDocs(diag)
, expects a diagnostic object
and returns a boolean whether nvim-rulebook
documentation for the respective
diagnostic available. One use case for this is to add a visual indicator if
there is a rule lookup available for a diagnostic (see
vim.diagnostic.config).
vim.diagnostic.config {
virtual_text = {
suffix = function(diag) return require("rulebook").hasDocs(diag) and "  " or "" end,
},
}
In my day job, I am a sociologist studying the social mechanisms underlying the digital economy. For my PhD project, I investigate the governance of the app economy and how software ecosystems manage the tension between innovation and compatibility. If you are interested in this subject, feel free to get in touch.
I also occasionally blog about vim: Nano Tips for Vim