With Neovim and null-ls
plugin we can make code formatting work like a charm, as I stated in My Neovim Revamp previously. While I was happily enjoying it, I did some tweaking for a little more convenience, such as:
Format on save.
Customize formatter.
Format conditionally in runtime.
Let’s get right into it.
Format on save
This is plain easy if you check out the wiki of null-ls
. According to this part, all you need is copy&paste the code into your own config.
Customize ruff&stylua
Formatters supported by null-ls
all have defaults, like arguments. Sometimes we want to add more options, and that’s when extra_args
comes in handy.
For instance, I’m using ruff
for Python formatting to replace isort
, so customization becomes:
require("null-ls").builtins.formatting.ruff.with({
extra_args = { "--select", "I" }
})
And for Lua, I want stylua
to use spaces instead of tabs, so I did:
require("null-ls").builtins.formatting.stylua.with({
extra_args = { "--indent-type", "Spaces" }
})
In addition, you can replace default arguments totally with args
, by following the config instruction here.
BTW, I found a few tricks regarding tabs&spaces:
In Neovim:
Use
:retab
to replace tabs with spaces(number of spaces defined bytabstop
).Use
:set list
to show tabs marking as>
and trailing spaces as-
.
In Shell:
Use
sed
to convert tabs to spaces in a bunch of files at one time.On Linux:
sed -i "s/\t//g" /path/to/files
.On macOS:
sed -i "" "s/\t//g" /path/to/files
. Here-i
stands for extension rather than in-place editing.
Format conditionally
Auto-formatting is sweet, but what if I don’t want it? When I’m reading some source code or working on a shared project, I want things kept as they were.
Toggling formatters on&off can be annoying, is there a smarter way?
Yes, there sure is. Turns out null-ls
has a runtime_condition
setting to force it to check whether a formatter should run for the current buffer.
Essentially, you just need to add a function to determine if formatting is needed:
require("null_ls").builtins.formatting.black.with({
runtime_condition = function(params)
return string.match(params.bufname, "source") == nil
end,
})
I keep all source code projects in ~/projects/source
. Based on the above config black
will check if current file belongs under this particular path, and if it is, no auto-formatting will be performed.
Just like this, you can easily split things up with a suitable condition statement in Lua. For reference of how to better write it, see:
Hope these tips can be helpful :)