chrisgrieser/nvim-rulebook

github github
plugindiagnosticscomment
stars 65
issues 0
subscribers 2
forks 1
CREATED

2023-09-21

UPDATED

3 days ago


nvim-rulebook 📖

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

  • 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.
  • QoL: auto-select a rule if it is the only one in the current line; if the line has no diagnostic, search forward up to the next line that does.
  • Includes built-in support for various linters. Zero 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.

Supported Sources

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 the supported linters

Rule Lookup

  • LTeX
  • Lua Diagnostics.
  • Pyright
  • Ruff
  • biome
  • clang-tidy
  • eslint
  • markdownlint
  • pylint
  • quick-lint-js
  • selene
  • shellcheck
  • stylelint
  • stylelintplus
  • ts
  • tsserver
  • typescript
  • yamllint

Add Ignore Comment

Installation

This plugin requires diagnostics provided by a source that supports Neovim's built-in diagnostics system. (nvim's built-in LSP client or nvim-lint are such sources.)

In addition, nvim 0.10 is required.

-- lazy.nvim
{
    "chrisgrieser/nvim-rulebook",
    keys = {
        { "<leader>ri", function() require("rulebook").ignoreRule() end },
        { "<leader>rl", function() require("rulebook").lookupRule() end },
        { "<leader>ry", function() require("rulebook").yankDiagnosticCode() end },
    }
},
-- packer
use { "chrisgrieser/nvim-rulebook" }

-- in your config
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)

Configuration

The configuration is optional. You only need to add a config when you want to customize a source or add custom sources.

When adding your own source, you must add the exact, case-sensitive source-name. (for example, clang-tidy, not clang).

require("rulebook").setup = ({
    ignoreComments = {
        selene = {
            comment = "-- selene: allow(%s)",
            location = "prevLine",
        },
        -- ... (full list of supported sources can be found in the README)

        yourCustomSource = { -- exact, case-sensitive source-name
            comment = "// disabling-comment %s", -- %s will be replaced with rule-id
            location = "prevLine", -- "prevLine"|"sameLine"|"encloseLine"
        }

        -- 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 and must 
        -- return a url
        yourCustomSource = "https://my-docs/%s.hthml",
        anotherCustomSource = function(diag)
            -- ...
            return url
        end,
    }

    -- if no diagnostic is found in current line, search this many lines forward
    forwSearchLines = 10,

    -- whether to yank to `+` or `"`
    yankDiagnosticCodeToSystemClipboard = true,
})

The plugin uses vim.ui.select, so the appearance of the rule selection can be customized by using a UI-plugin like dressing.nvim.

Customize Built-in Sources

Built-in sources be customized by overwriting them in the configuration:

-- use `disable-line` instead of the default `disable-next-line` for eslint
require("rulebook").setup = {
    ignoreComments = {
        eslint = {
            comment = "// eslint-disable-line %s",
            location = "sameLine",
        },
    },
}

Limitations

  • 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 do that, but some diagnostic sources do not (for example efm-langserver with incorrectly defined errorformat). 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.

API

Availability of Rule Lookup

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,
    },
}

Credits

About Me
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.

Blog
I also occasionally blog about vim: Nano Tips for Vim

Profiles