<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Colas.Nahaboo.net - emacs</title>
    <subtitle>Colas Nahaboo personal site, with discussions about programming code, web and computing topics, surfing and SUPing, and various musings.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://colas.nahaboo.net/tags/emacs/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://colas.nahaboo.net"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-08-13T00:00:00+00:00</updated>
    <id>https://colas.nahaboo.net/tags/emacs/atom.xml</id>
    <entry xml:lang="en">
        <title>gr: emacs-friendly grep of whole projects from anywhere</title>
        <published>2026-08-13T00:00:00+00:00</published>
        <updated>2026-08-13T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/code/gr-grep-the-whole-project-from-anywhere/"/>
        <id>https://colas.nahaboo.net/code/gr-grep-the-whole-project-from-anywhere/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/code/gr-grep-the-whole-project-from-anywhere/">&lt;p&gt;I just added &lt;strong&gt;gr&lt;/strong&gt; to my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ColasNahaboo/colas-bash-lib&quot;&gt;colas-bash-lib&lt;/a&gt; collection. It is one of the essential tools I use under emacs.&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The problem&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-problem&quot; aria-label=&quot;Anchor link for: the-problem&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I am always somewhere deep in a project, and I want to search the whole project, not just the current directory, and quickly go to found hits inside emacs, ignoring ancillary data inside &lt;code&gt;.git&lt;/code&gt; dirs and similar.&lt;/p&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;The solution&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-solution&quot; aria-label=&quot;Anchor link for: the-solution&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;gr&lt;/code&gt; walks up from the current directory until it finds a &lt;strong&gt;mark&lt;/strong&gt; — a file or directory named &lt;code&gt;.git&lt;/code&gt;, &lt;code&gt;.hg&lt;/code&gt;, &lt;code&gt;.jj&lt;/code&gt;, &lt;code&gt;.ugrep&lt;/code&gt; or &lt;code&gt;.gr&lt;/code&gt;, indicating the root of the current project — and runs &lt;code&gt;ug&lt;/code&gt; (ugrep, a better grep) recursively from there. So from anywhere in the tree:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;~/src/foo/sub/sub$ gr max_connections&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;config/app.conf:12:4:MaxConnections = 100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;src/server.go:45:1:maxConnections := ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The output is the classic &lt;code&gt;file:line:column:line&lt;/code&gt; format of compiler errors understood by emacs, with &lt;code&gt;-I&lt;/code&gt; skipping binaries and &lt;code&gt;--color=never&lt;/code&gt; keeping it clean for piping.&lt;/p&gt;
&lt;h2 id=&quot;emacs&quot;&gt;Emacs&lt;a class=&quot;zola-anchor&quot; href=&quot;#emacs&quot; aria-label=&quot;Anchor link for: emacs&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The whole thing is designed to play with emacs compile mode. &lt;code&gt;gr&lt;/code&gt; prints the header &lt;code&gt;gr: Entering directory \&lt;/code&gt;...&#39;&lt;code&gt;— in the exact format emacs expects, and only when it actually changes directory — so the relative paths in the output resolve correctly. Then it is just&lt;/code&gt;M-x compile&lt;code&gt;followed by&lt;/code&gt;next-error&lt;code&gt;(Ctrl-x&lt;/code&gt;) to jump from match to match through the whole project. The precise header matters: emacs is confused by anything that does not follow its convention.&lt;/p&gt;
&lt;p&gt;A tip: I mapped F1/F2/F3 for easy use of emacs compile mode:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;; compile: f1 search / f2 next hit / Shift-f2 previous hit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(global-set-key [f1] &amp;#39;compile)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(global-set-key [f2] &amp;#39;next-error)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(global-set-key (kbd &amp;quot;&amp;lt;S-f2&amp;gt;&amp;quot;) &amp;#39;previous-error)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;custom-marks&quot;&gt;Custom marks&lt;a class=&quot;zola-anchor&quot; href=&quot;#custom-marks&quot; aria-label=&quot;Anchor link for: custom-marks&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For a non-git project — or to define a sub-project root inside a monorepo — just place a &lt;code&gt;.gr&lt;/code&gt; (or &lt;code&gt;.ugrep&lt;/code&gt;) marker there and &lt;code&gt;gr&lt;/code&gt; stops at it. Extra mark names are added with &lt;code&gt;GR_MARKS&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export GR_MARKS=&amp;#39;svn cvs bzr fossil vscode env&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;why-i-like-it&quot;&gt;Why I like it&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-i-like-it&quot; aria-label=&quot;Anchor link for: why-i-like-it&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;One command, from anywhere&lt;/strong&gt;: no need to know where the repo root is.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Searches everything&lt;/strong&gt;, tracked or not — which &lt;code&gt;git grep&lt;/code&gt; can&#39;t do.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Emacs-ready output&lt;/strong&gt;: browse and jump to the matches instead of eyeballing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fast&lt;/strong&gt;: it is &lt;code&gt;ug&lt;/code&gt; under the hood, so no &lt;code&gt;grep -r&lt;/code&gt; slowness.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;installation-usage-and-more-info&quot;&gt;Installation, Usage, and more info&lt;a class=&quot;zola-anchor&quot; href=&quot;#installation-usage-and-more-info&quot; aria-label=&quot;Anchor link for: installation-usage-and-more-info&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ColasNahaboo/colas-bash-lib&quot;&gt;github.com/ColasNahaboo/colas-bash-lib&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;AI co-written: don&#39;t like, don&#39;t use.&lt;/p&gt;
</content>
        
    </entry>
</feed>
