TL;DR
Open cargo info
in Vim or neovim for the package under the cursor using these 4 lines of Lua.
Cargo info
Rust 1.82 was released a couple of days ago.
It’s packed with improvements, but one in particular caught my eye.
Cargo now has a info
sub-command.
It displays details about a package in the registry from the comfort of your terminal.
Here is an example:
$ cargo info lazy_static
lazy_static #macro #lazy #static
A macro for declaring lazily evaluated statics in Rust.
version: 1.5.0
license: MIT OR Apache-2.0
rust-version: unknown
documentation: https://docs.rs/lazy_static
repository: https://github.com/rust-lang-nursery/lazy-static.rs
crates.io: https://crates.io/crates/lazy_static/1.5.0
features:
spin = [dep:spin]
spin_no_std = [spin]
note: to see how you depend on lazy_static, run `cargo tree --invert --package lazy_static@1.5.0`
Vim and neovim generally composes well with other terminal tools.
So how can we easily integrate cargo info
and neovim
?
Demo
The goal is to press a key and display the cargo info
for the crate under the cursor in a Cargo.toml
file.
Like this:
Introducing keywordprg
In the above demonstration, we press K
over a crates name. Then neovim executes the program set in keywordprg
, appending the work under the cursor. So if the cursor is on lazy_static
[dev-dependencies]
iai = "0.1"
insta = "1.40.0"
lazy_static = "1.5.0"
# ^ cursor is here when we press K
mktemp = "0.5"
and keywordprg
is set to cargo info
, the command cargo info lazy_static
is executed in a new terminal.
We can further improve this.
Since we want a fast answer (without checking the remote repository), let’s use cargo info --offline
.
And we would like pretty colors, let’s force that using --color=always
.
We only want to alter keywordprg
when a Cargo.toml
file is edited, because it makes no sense to call cargo info
in a Python file.
We can use a ftplugin
for toml files for that1, so that the plugin is only loaded and executed when a toml file is executed.
Furthermore we can change the setting only when opening a file named “Cargo.toml”, instead of changing it for every toml file.
We can put the necessary configuration in ~/.config/nvim/ftplugin/toml.lua
2, like so:
if vim.endswith(vim.fn.bufname(), "Cargo.toml") then
vim.opt_local.keywordprg = "cargo info --color=always --offline"
end
-- Add chars that are often part of keys, especially in rust crates
-- (https://toml.io/en/v1.0.0#keys)
vim.opt_local.iskeyword:append "-"
The Lua code above also changes the iskeyword
preference.
This is so that tokio-test
is considered as one word (a “keyword” in Vim parlance), instead of two (tokio
and test
).
With this set, doing K
on tokio-test
will behave properly, because tokio-test
is passed to the command, instead of just tokio
.
One final note: the above configuration was the only thing sourced in the demo. All the rest is default, vanilla, neovim 0.10.2. And this does not even require recent neovim features, it has been supported in Vim for many years.
Learnings
Obviously this could be further refined.
Other options could be passed to cargo info
, like -v
to make it more verbose and list dependencies.
Some more scripting could add useful features to further improve the integration.
For this particular problem, there are even a full plugin with many more features.
But the point is to showcase a simple and robust integration3, applicable in a wide variety of contexts.
In particular when the use case is too niche, a full plugin is too costly to write and maintain for the benefits it provides.
Let’s highlight the takeaways from this post that are applicable in a wide variety of contexts.
First, a number of Neovim commands can do something with the keyword under the cursor.
Adjusting what counts as a keyword boundary is often, but not always, done in the syntax file of a particular language.
Or you may just want to make a different trade off and set your own iskeyword
value.
Second, the K
mapping is often used to look up a word in a documentation (it is set to open man pages by default).
It even works in visual mode, looking up the selected text.
And arbitrary Vim or shell commands can be used, instead of the default :Man
.
Please do read the corresponding parts of the Vim manual linked in this section to learn more. Next time, you may come up with your own quick integration between Vim and another tool. Happy hacking!
EDIT 2024-10-22: Clarify why we use nvim settings instead of a plugin like crates.nvim
To keep the example simple, we don’t clean-up the local preferences that are set here. See the documentation for best practices when sharing ftplugins. ↩︎
It’s also possible to do this in Vimscript instead of Lua. ↩︎
Thanks to @dpom@fosstodon.org for pointing out that crates.nvim has that feature already. ↩︎
Liked this post? Subscribe:
Discussions
This blog does not host comments, but you can reply via email or participate in one of the discussions below: