<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Fido on Emacs@ Dyerdwelling</title><image><url/><title>Fido on Emacs@ Dyerdwelling</title><link>https://www.emacs.dyerdwelling.family/tags/fido/</link><width>32</width><height>32</height></image><link>https://www.emacs.dyerdwelling.family/tags/fido/</link><description>Recent content in Fido on Emacs@ Dyerdwelling</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>captainflasmr@gmail.com (James Dyer)</managingEditor><webMaster>captainflasmr@gmail.com (James Dyer)</webMaster><lastBuildDate>Fri, 05 Sep 2025 10:06:00 +0100</lastBuildDate><atom:link href="https://www.emacs.dyerdwelling.family/tags/fido/index.xml" rel="self" type="application/rss+xml"/><item><title>Customizing Emacs Completion: From Fido's Fuzzy Matching to Literal Substring</title><link>https://www.emacs.dyerdwelling.family/emacs/20250905100614-emacs--customizing-emacs-completion-from-fidos-fuzzy-matching-to-literal-substring-search/</link><pubDate>Fri, 05 Sep 2025 10:06:00 +0100</pubDate><author>James Dyer</author><guid>https://www.emacs.dyerdwelling.family/emacs/20250905100614-emacs--customizing-emacs-completion-from-fidos-fuzzy-matching-to-literal-substring-search/</guid><description>&lt;p>For my completion framework, I&amp;rsquo;m currently using &lt;code>fido-mode&lt;/code>, and more recently, &lt;code>fido-vertical-mode&lt;/code>. However, I&amp;rsquo;m scratching yet another itch in my ongoing quest to be more efficient in Emacs, specifically to jump to files more quickly. I explored this in a previous post where I enhanced the &lt;code>recentf&lt;/code> functionality to work through completing-read in a predictable order, but what about the completing-read interface itself?&lt;/p>
&lt;figure>&lt;img src="https://www.emacs.dyerdwelling.family/emacs/20250905100614-emacs--Customizing-Emacs-Completion:-From-Fido%27s-Fuzzy-Matching-to-Literal-Substring-Search.jpg" width="100%">
&lt;/figure>
&lt;p>This happens to me often in Emacs, there is a subconscious functional annoyance which eventually bubbles to the surface and this case the surface bubble revolves around fido&amp;rsquo;s fuzzy matching behaviour. Simply put, I don&amp;rsquo;t like it!&lt;/p>
&lt;p>While it can be helpful for discovering files and commands you partially remember, sometimes you know exactly what you&amp;rsquo;re looking for and want a more literal, predictable search experience, in fact for me now, I would say it is not just sometimes, but always!. The fuzzy matching is finding too many candidates when I type in a few characters and really I want a contiguous input string to be literally matched.&lt;/p>
&lt;p>This post chronicles my journey from fido&amp;rsquo;s flex matching to a custom setup that provides literal substring matching, perfect for when you know what you want and just want to type it directly.&lt;/p>
&lt;p>Hang on a sec, can&amp;rsquo;t I just change the completion style?, this should be easy!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-elisp" data-lang="elisp">&lt;span style="display:flex;">&lt;span>(setq completion-styles &lt;span style="color:#f92672">&amp;#39;&lt;/span>(&lt;span style="color:#a6e22e">substring&lt;/span> basic))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>But that has no effect!, boooo!&lt;/p>
&lt;p>Anyways, that was a quick attempt at a fix, in the meantime lets explore flex a little bit more and &lt;code>icomplete&lt;/code> (which is the underpinning completion technology of fido) and see if we cam come up with a robust solution.&lt;/p>
&lt;p>Fido-mode use what&amp;rsquo;s called &amp;ldquo;flex&amp;rdquo; completion by default. This means that when you type &lt;code>abc&lt;/code>, it will match files like &lt;code>a_long_b_filename_c.txt&lt;/code> because it finds the letters a, b, and c in that order, even with other characters between them.&lt;/p>
&lt;p>While this flexibility is powerful, it can be frustrating when you want to search for a specific substring. If you&amp;rsquo;re looking for a file named &lt;code>project-abc-config.txt&lt;/code>, you might expect typing &lt;code>abc&lt;/code> to prioritize that match, but flex matching might show you &lt;code>a_big_collection.txt&lt;/code> first instead.&lt;/p>
&lt;p>So back to my initial attempt at a fix by setting the &lt;code>completion-styles&lt;/code> variable. The &lt;code>substring&lt;/code> style matches your input as a contiguous block anywhere within candidates, while &lt;code>basic&lt;/code> does prefix matching. This seemed like exactly what I wanted, I just need to find a way to set it and to make it stick.&lt;/p>
&lt;p>After some digging into the source code, I found the culprit in &lt;code>icomplete.el&lt;/code>. The &lt;code>icomplete--fido-mode-setup&lt;/code> function contains the following:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-elisp" data-lang="elisp">&lt;span style="display:flex;">&lt;span>(defun icomplete--fido-mode-setup ()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;Setup &lt;/span>&lt;span style="color:#e6db74">`fido-mode&amp;#39;&lt;/span>&lt;span style="color:#e6db74">&amp;#39;s minibuffer.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> (when (and icomplete-mode (icomplete-simple-completing-p))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">;; ... other settings ...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> (setq-local completion-styles &lt;span style="color:#f92672">&amp;#39;&lt;/span>(flex) &lt;span style="color:#75715e">; This line forces flex!&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> completion-flex-nospace &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">;; ... more settings ...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> )))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This function runs every time you enter the minibuffer, forcibly overriding any &lt;code>completion-styles&lt;/code> setting you might have configured. This explains why my &lt;code>setq&lt;/code> had no effect, fido was resetting it on every use!&lt;/p>
&lt;p>Rather than fight fido&amp;rsquo;s opinionated behaviour, I could instead switch to &lt;code>icomplete-vertical-mode&lt;/code>, which provides a similar interface but respects the standard completion configuration.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-elisp" data-lang="elisp">&lt;span style="display:flex;">&lt;span>(icomplete-vertical-mode &lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">;; scroll list rather than rotating&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(setq icomplete-scroll &lt;span style="color:#66d9ef">t&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">;; Make completion case-insensitive&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(setq completion-ignore-case &lt;span style="color:#66d9ef">t&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(setq read-file-name-completion-ignore-case &lt;span style="color:#66d9ef">t&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(setq read-buffer-completion-ignore-case &lt;span style="color:#66d9ef">t&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(with-eval-after-load &lt;span style="color:#e6db74">&amp;#39;icomplete&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> (setq completion-styles &lt;span style="color:#f92672">&amp;#39;&lt;/span>(&lt;span style="color:#a6e22e">substring&lt;/span> basic partial-completion emacs22)))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This gave me the literal substring matching I wanted and I think I have managed to set up everything else to the way fido comes out of the box.&lt;/p>
&lt;p>However, there was one more hurdle.&lt;/p>
&lt;p>By default, &lt;code>icomplete-vertical-mode&lt;/code> requires you to explicitly select a completion before submitting with &lt;code>C-m&lt;/code> (Enter) which is a keybinding I had grown accustomed to using in fido. This adds an extra confirmation step that fido-mode doesn&amp;rsquo;t have. There is a way around this however and that is to adapt to the keybinding &lt;code>C-j&lt;/code> which typically is more of a do literal action then exit type of thing, where C-m is more of just a simple Enter/action. I am willing to adapt to this keybinding.&lt;/p>
&lt;p>So this works pretty well for me really, but can I not just get &lt;code>completion-styles&lt;/code> to stick for fido?, even though I have a solution I really want to see if I can adjust fido&amp;rsquo;s default functionality.&lt;/p>
&lt;p>Well simply I used an advice function to wrap around the original fido setup function and set up the &lt;code>completion-styles&lt;/code> local variable after fido has done its thing:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-elisp" data-lang="elisp">&lt;span style="display:flex;">&lt;span>(defun my-fido-completion-styles-advice (&lt;span style="color:#66d9ef">&amp;amp;rest&lt;/span> _args)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;Override completion styles after fido setup.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> (when (and fido-mode (icomplete-simple-completing-p))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> (setq-local completion-styles &lt;span style="color:#f92672">&amp;#39;&lt;/span>(&lt;span style="color:#a6e22e">substring&lt;/span> basic partial-completion))))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(advice-add &lt;span style="color:#e6db74">&amp;#39;icomplete--fido-mode-setup&lt;/span> :after &lt;span style="color:#a6e22e">#&amp;#39;&lt;/span>my-fido-completion-styles-advice)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now I have two options for using completion in Emacs the way I want it and now I can find files, or anything else for that matter much more quickly.&lt;/p>
&lt;p>This journey taught me several important lessons about Emacs customization:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Read the source&lt;/strong>: When configuration variables don&amp;rsquo;t seem to work as expected, the source code often reveals why.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Local vs. global settings&lt;/strong>: Fido uses &lt;code>setq-local&lt;/code> to override settings per-buffer, which is why global &lt;code>setq&lt;/code> calls don&amp;rsquo;t work.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>There&amp;rsquo;s always another way&lt;/strong>: Emacs&amp;rsquo; flexibility means there are usually multiple approaches to achieving the same goal.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>While fido-mode&amp;rsquo;s fuzzy matching is excellent for discovery and exploration, I just wanted the predictability of literal substring matching and with a small advice function, you can have the best of both worlds!&lt;/p></description></item></channel></rss>