Null-ls¶
The jose-elias-alvarez/null-ls.nvim
plugin, although not essential to the operation of the IDE, is definitely one to have in your configuration. It allows you to use language server features to insert LSPs dedicated to diagnostics, formatting, and other operations.
Null-ls aims to simplify the creation, sharing, and setting up of LSP sources. It enables improved performance by eliminating any external processes.
Plugin Insertion¶
Inserting the plugin consists of editing the file custom/plugins/init.lua
and creating a new configuration file custom/plugins/null-ls.lua
. The code to be inserted into init.lua is as follows:
["jose-elias-alvarez/null-ls.nvim"] = {
after = "nvim-lspconfig",
config = function()
require("custom.plugins.null-ls")
end,
},
As also evidenced by the code, the entry must be made after the neovim/nvim-lspconfig plugin. The configuration function is then called and our configuration file null-ls.lua is requested.
LSP Installation Required¶
For proper operation, language servers must be installed separately with Mason. For installation, one can use the interface callable with the command :Mason
, or installation from statusline with the command :MasonInstall name_lsp
, e.g.:
:MasonInstall markdownlint
The LSPs to be installed are prettierd
, markdownlint
and stylua
. The first two LSPs will provide formatting and diagnostic capabilities for Markdown code, while the third provides support for formatting Lua code.
Markdownlint setting
For optimal use of the linter, a rc
configuration file must be placed in your home directory; detailed instructions are available at the end of this document.
Creating null-ls.lua¶
Once we have installed the necessary language servers, we can move on to creating the custom/plugins/null-ls.lua
file. To do this we can simply use our NvChad:
nvim ~/.config/nvim/lua/custom/plugins/null-ls.lua
We copy the code below, bring ourselves into our IDE making sure we are in the NORMAL state, and with the p (paste) key we insert it. Then we simply save it and close with the :wq
command.
local present, null_ls = pcall(require, "null-ls")
if not present then
return
end
local b = null_ls.builtins
local sources = {
-- format html and markdown
b.formatting.prettierd.with { filetypes = { "html", "yaml", "markdown" } },
-- markdown diagnostic
b.diagnostics.markdownlint,
-- Lua formatting
b.formatting.stylua,
}
local augroup = vim.api.nvim_create_augroup("LspFormatting", {})
local on_attach = function(client, bufnr)
if client.supports_method "textDocument/formatting" then
vim.api.nvim_clear_autocmds { group = augroup, buffer = bufnr }
vim.api.nvim_create_autocmd("BufWritePre", {
group = augroup,
buffer = bufnr,
callback = function()
-- on 0.8, you should use vim.lsp.buf.format({ bufnr = bufnr }) instead
vim.lsp.buf.formatting_sync()
end,
})
end
end
null_ls.setup {
debug = true,
sources = sources,
on_attach = on_attach,
}
Once the changes are finished, to instruct NvChad we have to perform a :PackerSync
. It is advisable to exit the editor and re-enter before doing the sync.
LSP sources¶
The part of the null-ls.lua configuration file where we can intervene with any changes is as follows:
local sources = {
-- format html and markdown
b.formatting.prettierd.with { filetypes = { "html", "yaml", "markdown" } },
-- markdown diagnostic
b.diagnostics.markdownlint,
-- Lua formatting
b.formatting.stylua,
}
Our local sources are set up using the b.formatting
and b.diagnostic
functions provided by null-ls followed by our chosen LSPs. For a complete list of the functions included in the plugin, see the Project Page.
For formatting Markdown documents you also have other LSPs available. The setting used here provides excellent support but, for a complete list, you can consult the Dedicated Page.
Markdownlint setting¶
Markdownlint works by comparing the code we write with rules set by the project that can be found at this page.
Once activated each time a Markdown file is modified and the editor return in NORMAL mode, a message should appear in the middle part of the statusline. This first informs us of the check with diagnostic markdown
, and once the check is finished the message of errors found: diagnostic (0%)
. The percentage refers to the number of errors found and not to the progress in the file.
The rules set by markdownlint
are very stringent and include, for example, a maximum line length of 80 words, which in writing documentation may not be adequate. To get around these limitations, it is possible to change the settings passed to the executable by placing a rc
file in the workspace_directory for a project-level override, or in one's home for a user-level override. The file should be named .markdownlintrc
if placed in your own home or .markdownlint.jsonc
if placed in the project's workspace_directory. For working on a fork of the Rocky documentation, the first solution is preferable as it does not interfere with the Git repository.
The comments are explanatory of the checks performed by the various rules. In particular, the MD013 rule on maximum line length (customizable length), if not modified, is particularly tedious. The MD033 rule is needed to avoid warnings when entering keyboard keys <kbd>
and can be integrated in array form with other keys. The MD025 rule prevents the interpretation of the title, present in the frontmatter, of generating the H1
double header error. The MD046 rule changes the default (consistent) to fenced. This is because in the documentation on Rocky Linux admonitions (indent) are commonly used with block codes (fenced), which would give an inconsistency error.
The complete excellently commented example can be found on the related pages.
Here, then, is the proposed .markdownlintrc
file:
{
// Default state for all rules
"default": true,
// MD007/ul-indent - Unordered list indentation
"MD007": {
// Spaces for indent
"indent": 4,
// Whether to indent the first level of the list
"start_indented": true,
// Spaces for first level indent (when start_indented is set)
"start_indent": 4
},
// MD013/line-length - Line length
"MD013": {
// Number of characters
"line_length": 480,
// Number of characters for headings
"heading_line_length": 80,
// Number of characters for code blocks
"code_block_line_length": 280,
// Include code blocks
"code_blocks": true,
// Include tables
"tables": true,
// Include headings
"headings": true,
// Include headings
"headers": true,
// Strict length checking
"strict": false,
// Stern length checking
"stern": false
},
// MD033/no-inline-html - Inline HTML
"MD033": {
// Allowed elements
"allowed_elements": ["kbd"]
},
// MD025/single-title/single-h1 - Multiple top-level headings in the same document
"MD025": {
// Heading level
"level": 1,
// RegExp for matching title in front matter
"front_matter_title": "^\\s*title\\s*[:=]"
},
// MD046/code-block-style - Code block style
"MD046": {
// Block style
"style": "fenced"
}
}
The inclusion of the file should eliminate flags regarding aspects of code control that we want or need to include to write documentation on Rocky Linux. These exceptions would otherwise violate the default rules.
In summary, although not indispensable, the null-ls plugin makes a significant contribution to our documentation work. If installed, it will help to write correct and consistent code.
Author: Franco Colussi
Contributors: Steven Spencer