<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Cargo on Clément Joly – Open-Source, Rust &amp; SQLite</title><link>https://joly.pw/tags/cargo/</link><description>Recent content in Cargo on Clément Joly – Open-Source, Rust &amp; SQLite</description><image><title>Clément Joly – Open-Source, Rust &amp; SQLite</title><url>https://joly.pw/images/open-graph-home-original.png</url><link>https://joly.pw/images/open-graph-home-original.png</link></image><generator>Hugo -- 0.154.3</generator><language>en</language><copyright>Clément Joly</copyright><lastBuildDate>Wed, 11 Mar 2026 03:32:38 +0000</lastBuildDate><atom:link href="https://joly.pw/tags/cargo/index.xml" rel="self" type="application/rss+xml"/><item><title>Cargo Info in Neovim, or How Simple Features Go a Long Way</title><link>https://joly.pw/blog/cargo-info-in-neovim/</link><pubDate>Mon, 21 Oct 2024 22:39:34 +0100</pubDate><guid>https://joly.pw/blog/cargo-info-in-neovim/</guid><description>Integrate Vim and Cargo info with just a few lines of Lua using keywordprg.</description><content:encoded><![CDATA[



  
  
  
  

  <div class="alert alert-tldr">
    <p class="alert-heading">
      ⚡
      
        TL;DR
      
    </p>
    <p>Open <code>cargo info</code> in Vim or neovim for the package under the cursor using <a href="#introducing-keywordprg">these 4 lines of Lua</a>.</p>
  </div>



<h2 id="cargo-info">Cargo info</h2>
<p><a href="https://blog.rust-lang.org/2024/10/17/Rust-1.82.0.html#whats-in-1820-stable">Rust 1.82</a> was released a couple of days ago.
It’s packed with improvements, but one in particular caught my eye.
Cargo now has a <code>info</code> sub-command.
It displays details about a package in the registry from the comfort of your terminal.
Here is an example:</p>
<pre tabindex="0"><code>$ 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`
</code></pre><p>Vim and neovim generally composes well with other terminal tools.
So how can we easily integrate <code>cargo info</code> and <code>neovim</code>?</p>
<h2 id="demo">Demo</h2>
<p>The goal is to press a key and display the <code>cargo info</code> for the crate under the cursor in a <code>Cargo.toml</code> file.
Like this:</p>
<div id="demo3"></div>
<script>
AsciinemaPlayer.create("/blog/cargo-info-in-neovim/demo.json", document.getElementById('demo3'), {
"idleTimeLimit":  1 ,"poster": "npt:3","preload":  1 ,"speed": "1.5",
});
</script>
<noscript><blockquote><p>To run this asciicast without javascript, use <code>asciinema play https://joly.pw/blog/cargo-info-in-neovim/demo.json</code> with <a href="https://asciinema.org/">Asciinema</a></p></blockquote></noscript>

<h2 id="introducing-keywordprg">Introducing <code>keywordprg</code></h2>
<p>In the above demonstration, we press <a href="https://neovim.io/doc/user/various.html#K"><code>K</code></a> over a crates name. Then neovim executes the program set in <a href="https://neovim.io/doc/user/options.html#'keywordprg'"><code>keywordprg</code></a>, appending the work under the cursor. So if the cursor is on <code>lazy_static</code></p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span>[<span style="color:#e06c75">dev-dependencies</span>]
</span></span><span style="display:flex;"><span><span style="color:#e06c75">iai</span> = <span style="color:#98c379">&#34;0.1&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#e06c75">insta</span> = <span style="color:#98c379">&#34;1.40.0&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#e06c75">lazy_static</span> = <span style="color:#98c379">&#34;1.5.0&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#7f848e">#   ^ cursor is here when we press K</span>
</span></span><span style="display:flex;"><span><span style="color:#e06c75">mktemp</span> = <span style="color:#98c379">&#34;0.5&#34;</span>
</span></span></code></pre></div><p>and <code>keywordprg</code> is set to <code>cargo info</code>, the command <code>cargo info lazy_static</code> is executed in a new terminal.</p>
<p>We can further improve this.
Since we want a fast answer (without checking the remote repository), let’s use <code>cargo info --offline</code>.
And we would like pretty colors, let’s force that using <code>--color=always</code>.</p>
<p>We only want to alter <code>keywordprg</code> when a <code>Cargo.toml</code> file is edited, because it makes no sense to call <code>cargo info</code> in a Python file.
We can use a <a href="https://neovim.io/doc/user/usr_41.html#ftplugin"><code>ftplugin</code></a> for toml files for that<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, 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 <code>~/.config/nvim/ftplugin/toml.lua</code><sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>, like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#c678dd">if</span> <span style="color:#e06c75">vim.endswith</span>(<span style="color:#e06c75">vim.fn</span>.<span style="color:#e06c75">bufname</span>(), <span style="color:#98c379">&#34;Cargo.toml&#34;</span>) <span style="color:#c678dd">then</span>
</span></span><span style="display:flex;"><span>  <span style="color:#e06c75">vim.opt_local</span>.<span style="color:#e06c75">keywordprg</span> <span style="color:#56b6c2">=</span> <span style="color:#98c379">&#34;cargo info --color=always --offline&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#c678dd">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#7f848e">-- Add chars that are often part of keys, especially in rust crates</span>
</span></span><span style="display:flex;"><span><span style="color:#7f848e">-- (https://toml.io/en/v1.0.0#keys)</span>
</span></span><span style="display:flex;"><span><span style="color:#e06c75">vim.opt_local</span>.<span style="color:#e06c75">iskeyword</span>:<span style="color:#e06c75">append</span> <span style="color:#98c379">&#34;-&#34;</span>
</span></span></code></pre></div><p>The Lua code above also changes the <a href="https://neovim.io/doc/user/options.html#'iskeyword'"><code>iskeyword</code></a> preference.
This is so that <code>tokio-test</code> is considered as one word (a “keyword” in Vim parlance), instead of two (<code>tokio</code> and <code>test</code>).
With this set, doing <code>K</code> on <code>tokio-test</code> will behave properly, because <code>tokio-test</code> is passed to the command, instead of just <code>tokio</code>.</p>
<p>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.</p>
<h2 id="learnings">Learnings</h2>
<p>Obviously this could be further refined.
Other options could be passed to <code>cargo info</code>, like <code>-v</code> 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 href="https://github.com/saecki/crates.nvim">a full plugin</a> with many more features.
But the point is to showcase a simple and robust integration<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>, 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.</p>
<p>Let’s highlight the takeaways from this post that are applicable in a wide variety of contexts.</p>
<p>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 <code>iskeyword</code> value.</p>
<p>Second, the <a href="https://neovim.io/doc/user/various.html#K"><code>K</code></a> 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 <code>:Man</code>.</p>
<p>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!</p>




  
  
  
  

  <div class="alert alert-edit">
    <p class="alert-heading">
      ✏
      
        Edit
      
    </p>
    <p>2024-10-22: Clarify why we use nvim settings instead of a plugin like <a href="https://github.com/saecki/crates.nvim">crates.nvim</a></p>
  </div>



<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>To keep the example simple, we don’t clean-up the local preferences that are set here. See the <a href="https://neovim.io/doc/user/usr_41.html#ftplugin">documentation</a> for best practices when sharing ftplugins.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>It’s also possible to do this in Vimscript instead of Lua.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Thanks to <a href="https://fosstodon.org/@dpom">@dpom@fosstodon.org</a> <a href="https://fosstodon.org/@dpom/113347670141692005">for pointing out</a> that crates.nvim has that feature already.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item></channel></rss>