{"id":13409930,"url":"https://github.com/chrisgrieser/nvim-rulebook","last_synced_at":"2025-04-09T07:07:43.881Z","repository":{"id":196154278,"uuid":"694711361","full_name":"chrisgrieser/nvim-rulebook","owner":"chrisgrieser","description":"Add inline-comments to ignore rules, or lookup rule documentation online.","archived":false,"fork":false,"pushed_at":"2025-03-25T13:02:53.000Z","size":202,"stargazers_count":85,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-02T04:09:11.483Z","etag":null,"topics":["ignore-diagnostic","linter-plugin","nvim-plugin"],"latest_commit_sha":null,"homepage":"","language":"Lua","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/chrisgrieser.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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://www.paypal.me/ChrisGrieser","ko_fi":"pseudometa"}},"created_at":"2023-09-21T14:38:06.000Z","updated_at":"2025-04-01T21:16:25.000Z","dependencies_parsed_at":"2023-09-21T20:17:36.121Z","dependency_job_id":"5828fd35-a507-4fc4-be2f-3dc223e35d32","html_url":"https://github.com/chrisgrieser/nvim-rulebook","commit_stats":{"total_commits":223,"total_committers":2,"mean_commits":111.5,"dds":0.004484304932735439,"last_synced_commit":"bc5e3874a9870709ec91152f9efce6dad49ca862"},"previous_names":["chrisgrieser/nvim-rule-breaker"],"tags_count":0,"template":false,"template_full_name":"chrisgrieser/nvim-pseudometa-plugin-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisgrieser%2Fnvim-rulebook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisgrieser%2Fnvim-rulebook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisgrieser%2Fnvim-rulebook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisgrieser%2Fnvim-rulebook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chrisgrieser","download_url":"https://codeload.github.com/chrisgrieser/nvim-rulebook/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247994121,"owners_count":21030050,"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":["ignore-diagnostic","linter-plugin","nvim-plugin"],"created_at":"2024-07-30T20:01:04.099Z","updated_at":"2025-04-09T07:07:43.874Z","avatar_url":"https://github.com/chrisgrieser.png","language":"Lua","funding_links":["https://www.paypal.me/ChrisGrieser","https://ko-fi.com/pseudometa","https://ko-fi.com/Y8Y86SQ91'"],"categories":["LSP","Lua"],"sub_categories":["(requires Neovim 0.5)","Diagnostics"],"readme":"\u003c!-- LTeX: enabled=false --\u003e\n# nvim-rulebook 📖\n\u003c!-- LTeX: enabled=true --\u003e\n\u003ca href=\"https://dotfyle.com/plugins/chrisgrieser/nvim-rulebook\"\u003e\u003cimg\nalt =\"badge\" src=\"https://dotfyle.com/plugins/chrisgrieser/nvim-rulebook/shield\"/\u003e\u003c/a\u003e\n\nAdd inline-comments to ignore rules, or lookup rule documentation online.\n\nSome LSPs provide code actions for that – this plugin adds commands for linters\nand LSPs that don't.\n\n\u003c!-- toc --\u003e\n\n- [Features](#features)\n- [Supported sources](#supported-sources)\n\t* [Rule lookup](#rule-lookup)\n\t* [Add ignore comment](#add-ignore-comment)\n\t* [Suppress formatting](#suppress-formatting)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Configuration](#configuration)\n\t* [Base configuration](#base-configuration)\n\t* [Customize built-in sources](#customize-built-in-sources)\n\t* [Correctly configured diagnostic providers](#correctly-configured-diagnostic-providers)\n- [API: Availability of rule lookup](#api-availability-of-rule-lookup)\n- [Credits](#credits)\n\n\u003c!-- tocstop --\u003e\n\n## Features\n- Look up official rule documentation, falling back to a web search if the\n  source does not have rule documentation.\n- Add inline-comments to ignore rules like `// eslint disable-next-line\n  some-rule`. Supports previous line, same line, and enclosing lines.\n- Suppress formatting with via ignore comments of the respective formatter, such\n  as `// prettier-ignore`.\n- Quality-of-life: auto-select a rule if it is the only one in the current line;\n  if the line has no diagnostic, search forward to the next line that does.\n- Includes built-in support for various linters and formatters. No plugin\n  configuration required if you only need to use built-in sources.\n- Customizing built-in sources or adding your own sources is easy. PRs to add\n  more built-ins are welcome.\n\n## Supported sources\nYou easily add a custom source via the [plugin configuration](#configuration).\nHowever, please consider making a PR to add support for a source if it is\nmissing.\n\n[Rule data for built-in support of linters and formatters](./lua/rulebook/data)\n\n\u003c!-- INFO use `just update-readme` to automatically update this section --\u003e\n\u003c!-- auto-generated: start --\u003e\n### Rule lookup\n- `LTeX`\n- `Lua Diagnostics.`\n- `Pyright`\n- `Ruff`\n- `ansible-lint`\n- `basedpyright`\n- `biome`\n- `clang-tidy`\n- `eslint`\n- `ltex_plus`\n- `markdownlint`\n- `pylint`\n- `quick-lint-js`\n- `selene`\n- `shellcheck`\n- `stylelint`\n- `stylelintplus`\n- `swiftlint`\n- `ts`\n- `tsserver`\n- `typescript`\n- `yamllint`\n\n### Add ignore comment\n- [LTeX](https://valentjn.github.io/ltex/advanced-usage.html)\n- [Lua Diagnostics.](https://luals.github.io/wiki/annotations/#diagnostic)\n- [Pyright](https://microsoft.github.io/pyright/#/comments)\n- [Ruff](https://docs.astral.sh/ruff/linter/#error-suppression)\n- [alex](https://github.com/get-alex/alex#control)\n- [ansible-lint](https://ansible.readthedocs.io/projects/lint/usage/#muting-warnings-to-avoid-false-positives)\n- [basedpyright](https://microsoft.github.io/pyright/#/comments)\n- [biome](https://biomejs.dev/linter/#ignore-code)\n- [clang-tidy](https://clang.llvm.org/extra/clang-tidy/#suppressing-undesired-diagnostics)\n- [codespell](https://github.com/codespell-project/codespell/issues/1212#issuecomment-1721152455)\n- [editorconfig-checker](https://github.com/editorconfig-checker/editorconfig-checker#excluding-lines)\n- [eslint](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1)\n- [ltex_plus](https://valentjn.github.io/ltex/advanced-usage.html)\n- [markdownlint](https://github.com/DavidAnson/markdownlint#configuration)\n- [pylint](https://pylint.readthedocs.io/en/latest/user_guide/messages/message_control.html)\n- [selene](https://kampfkarren.github.io/selene/usage/filtering.html#allowingdenying-lints-for-an-entire-file)\n- [shellcheck](https://www.shellcheck.net/wiki/Ignore)\n- [spellwarn](https://github.com/ravibrock/spellwarn.nvim#usage)\n- [stylelint](https://stylelint.io/user-guide/ignore-code/)\n- [stylelintplus](https://stylelint.io/user-guide/ignore-code/)\n- [swiftlint](https://realm.github.io/SwiftLint/#Disable-rules-in-code)\n- [ts](https://www.typescriptlang.org/)\n- [tsserver](https://www.typescriptlang.org/)\n- [typescript](https://www.typescriptlang.org/)\n- [vale-ls](https://vale.sh/docs/topics/config/#markup-based-configuration)\n- [vale](https://vale.sh/docs/topics/config/#markup-based-configuration)\n- [woke](https://docs.getwoke.tech/ignore/#in-line-and-next-line-ignoring)\n- [yamllint](https://yamllint.readthedocs.io/en/stable/disable_with_comments.html)\n\u003c!-- auto-generated: end --\u003e\n\n\u003c!-- TODO: auto-generate this section as well? --\u003e\n### Suppress formatting\n- [stylua](https://github.com/JohnnyMorganz/StyLua#ignoring-parts-of-a-file)\n- [prettier](https://prettier.io/docs/en/ignore.html)\n- [black](https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#ignoring-sections)\n  / [ruff](https://docs.astral.sh/ruff/formatter/#format-suppression)\n- [clang-format](https://clang.llvm.org/docs/ClangFormatStyleOptions.html#disabling-formatting-on-a-piece-of-code)\n\n## Installation\n**Requirements**\n- nvim 0.10+\n- Diagnostics provided by a source that supports Neovim's built-in diagnostics\n  system. (nvim's built-in LSP client,\n  [efm-langserver](https://github.com/mattn/efm-langserver) or\n  [nvim-lint](https://github.com/mfussenegger/nvim-lint) are such sources.)\n\n```lua\n-- lazy.nvim\n{ \"chrisgrieser/nvim-rulebook\" },\n\n-- packer\nuse { \"chrisgrieser/nvim-rulebook\" }\n```\n\n## Usage\nYou can use the commands via lua functions:\n\n```lua\nvim.keymap.set(\"n\", \"\u003cleader\u003eri\", function() require(\"rulebook\").ignoreRule() end)\nvim.keymap.set(\"n\", \"\u003cleader\u003erl\", function() require(\"rulebook\").lookupRule() end)\nvim.keymap.set(\"n\", \"\u003cleader\u003ery\", function() require(\"rulebook\").yankDiagnosticCode() end)\nvim.keymap.set({ \"n\", \"x\" }, \"\u003cleader\u003erf\", function() require(\"rulebook\").suppressFormatter() end)\n```\n\nAlternatively, you can use the `:Rulebook` ex-command:\n\n```vim\n:Rulebook ignoreRule\n:Rulebook lookupRule\n:Rulebook yankDiagnosticCode\n:Rulebook suppressFormatter\n```\n\nNote that `:Rulebook suppressFormatter` only supports normal mode. To add\nformatter-ignore comments for a line range, you need to use the lua function\n`require(\"rulebook\").suppressFormatter()` from visual mode.\n\n## Configuration\n\n### Base configuration\nThe `.setup()` call is optional. You only need to add a config when you want to\nadd or customize sources.\n\nWhen adding your own source, you must add the exact, case-sensitive\nsource name, for example, `clang-tidy`, not `clang`.\n\n```lua\nrequire(\"rulebook\").setup = ({\n\t-- if no diagnostic is found in current line, search this many lines forward\n\tforwSearchLines = 10,\n\n\tignoreComments = {\n\t\tshellcheck = {\n\t\t\tcomment = \"# shellcheck disable=%s\",\n\t\t\tlocation = \"prevLine\",\n\t\t\tmultiRuleIgnore = true,\n\t\t\tmultiRuleSeparator = \",\",\n\t\t},\n\t\t-- ... (full list of sources with builtin support can be found in the README)\n\n\t\tyourCustomSource = { -- exact, case-sensitive source-name\n\t\t\t-- `%s` will be replaced with rule-id\n\t\t\tcomment = \"// disabling-comment %s\",\n\n\t\t\t---@type \"prevLine\"|\"sameLine\"|\"encloseLine\"\n\t\t\tlocation = \"sameLine\",\n\n\t\t\t-- whether multiple rules can be ignored with one comment, defaults to `false`\n\t\t\tmultiRuleIgnore = true,\n\n\t\t\t-- separator for multiple rule-ids, defaults to \", \"\n\t\t\tmultiRuleSeparator = \",\",\n\t\t}\n\n\t\t-- if location is \"encloseLine\", needs to be a list of two strings\n\t\tanotherCustomSource = {\n\t\t\tcomment = { \n\t\t\t\t\"// disable-rule %s\", \n\t\t\t\t\"// enable-rule %s\",\n\t\t\t},\n\t\t\tlocation = \"encloseLine\",\n\t\t}\n\t},\n\n\truleDocs = {\n\t\tselene = \"https://kampfkarren.github.io/selene/lints/%s.html\"\n\t\t-- ... (full list of supported sources can be found in the README)\n\n\t\t-- Search URL when no documentation definition is available for a\n\t\t-- diagnostic source. `%s` will be replaced with the diagnostic source \u0026 code.\n\t\t-- Default is the DDG \"Ducky Search\" (automatically opening first result).\n\t\tfallback = \"https://duckduckgo.com/?q=%s+%%21ducky\u0026kl=en-us\",\n\n\t\t-- the value of the rule documentations accept either a string or a function\n\t\t-- * if a string, `%s` will be replaced with rule-id\n\t\t-- * if a function, takes a `:h diagnostic-structure` as argument \u0026 return a url\n\t\tyourCustomSource = \"https://my-docs/%s.hthml\",\n\t\tanotherCustomSource = function(diag)\n\t\t\t-- ...\n\t\t\treturn url\n\t\tend,\n\t}\n\n\tsuppressFormatter = {\n\t\tlua = {\n\t\t\t-- normal mode\n\t\t\tignoreBlock = \"-- stylua: ignore\",\n\t\t\tlocation = \"prevLine\",\n\n\t\t\t-- visual mode\n\t\t\tignoreRange = { \"-- stylua: ignore start\", \"-- stylua: ignore start\" },\n\t\t},\n\t}\n})\n```\n\nThe plugin uses\n[vim.ui.select](https://neovim.io/doc/user/lua.html#vim.ui.select()), so the\nappearance of the rule selection can be customized by using a UI-plugin like\n[dressing.nvim](https://github.com/stevearc/dressing.nvim).\n\n### Customize built-in sources\nBuilt-in sources be customized by overwriting them in the configuration:\n\n```lua\n-- example: use `disable-line` instead of the default `disable-next-line` for eslint\nrequire(\"rulebook\").setup = {\n\tignoreComments = {\n\t\teslint = {\n\t\t\tcomment = \"// eslint-disable-line %s\",\n\t\t\tlocation = \"sameLine\",\n\t\t},\n\t},\n}\n```\n\n### Correctly configured diagnostic providers\nThe plugin requires that the diagnostic providers (the LSP or a\nlinter-integration tool like `nvim-lint` or `efm`) provide the **source and code\nfor the diagnostic**. In case of a linter integration tool, this requires the\ncorrect configuration for the respective linter. For example, when using `efm`\nto integrate `markdownlint`, the [`%n` item is required to parse the diagnostic\ncode](https://neovim.io/doc/user/quickfix.html#errorformat):\n\n```lua\nrequire(\"nvim-lspconfig\").efm.setup({\n\tfiletypes = { \"markdown\" },\n\tsettings = { \n\t\tlanguages = {\n\t\t\tmarkdown = {\n\t\t\t\t{\n\t\t\t\t\tlintSource = \"markdownlint\",\n\t\t\t\t\tlintCommand = \"markdownlint $'{INPUT}'\",\n\t\t\t\t\tlintStdin = false,\n\t\t\t\t\tlintIgnoreExitCode = true,\n\t\t\t\t\tlintFormats = { \n\t\t\t\t\t\t\"%f:%l:%c MD%n/%m\", \n\t\t\t\t\t\t\"%f:%l MD%n/%m\"\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n}\n```\n\n## API: Availability of rule lookup\nThe function `require(\"rulebook\").hasDocs(diag)`, expects a diagnostic object\nand returns a boolean whether `nvim-rulebook` documentation for the respective\ndiagnostic available. One use case for this is to add a visual indicator if\nthere is a rule lookup available for a diagnostic (see\n[vim.diagnostic.config](https://neovim.io/doc/user/diagnostic.html#vim.diagnostic.config())).\n\n```lua\nvim.diagnostic.config {\n\tvirtual_text = {\n\t\tsuffix = function(diag) return require(\"rulebook\").hasDocs(diag) and \"  \" or \"\" end,\n\t},\n}\n```\n\n## Credits\nIn my day job, I am a sociologist studying the social mechanisms underlying the\ndigital economy. For my PhD project, I investigate the governance of the app\neconomy and how software ecosystems manage the tension between innovation and\ncompatibility. If you are interested in this subject, feel free to get in touch.\n\nI also occasionally blog about vim: [Nano Tips for Vim](https://nanotipsforvim.prose.sh)\n\n- [Website](https://chris-grieser.de/)\n- [Mastodon](https://pkm.social/@pseudometa)\n- [ResearchGate](https://www.researchgate.net/profile/Christopher-Grieser)\n- [LinkedIn](https://www.linkedin.com/in/christopher-grieser-ba693b17a/)\n\n\u003ca href='https://ko-fi.com/Y8Y86SQ91' target='_blank'\u003e\u003cimg height='36'\nstyle='border:0px;height:36px;' src='https://cdn.ko-fi.com/cdn/kofi1.png?v=3'\nborder='0' alt='Buy Me a Coffee at ko-fi.com' /\u003e\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisgrieser%2Fnvim-rulebook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchrisgrieser%2Fnvim-rulebook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisgrieser%2Fnvim-rulebook/lists"}