<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title><![CDATA[0xpebbles.org]]></title>
    <link><![CDATA[http://blog.0xpebbles.org]]></link>
    <description><![CDATA[0xpebbles blog]]></description>
    <lastBuildDate>Fri, 09 Apr 2021 08:37:24 +0200</lastBuildDate>
    <pubDate>Fri, 09 Apr 2021 08:37:24 +0200</pubDate>
    <language>en</language>

<!-- 20141219 -->    <item>
      <title>Better filebrowser for mutt serving MH mailbox</title>
      <link>http://blog.0xpebbles.org/Better-filebrowser-for-mutt-serving-MH-mailbox</link>
      <pubDate>19 Dec 2014 00:00:00 +0000</pubDate>
      <content:encoded><![CDATA[

  

<p>
<b>Mutt</b> has it's strong sides and also weak sides. One of the weak ones is the file browser, that isn't really designed for actual <i>browsing</i>, as it
only displays one level of the file hierarchy at a time. If not entering a path directly, actual browsing is done by:
</p>

<ul>
<li>either typing a subpath, then using the browser again on the partial path</li>
<li>or one can tell <b>mutt</b> up front about the folders in existance using the <b>mailboxes</b> command (and also automatically populate that, as shown 
<a href="http://dev.mutt.org/trac/wiki/ConfigTricks#Buildingalistofmailboxesonthefly">here</a> and <a href="http://dev.mutt.org/trac/wiki/MuttFaq/Maildir">here</a>),
and then use the <i>Mailboxes</i>-view of the browser, which is a flat list</li>
</ul>

<p>
The problem is that both ways are frustrating to use with an ever growing mailbox.
The former makes it hard to see which folders and subfolders have unread mail and to get some overview over the hierarchy in general. The latter is a flat list, which
is hard to find anything in if you have a lot of nodes. There is a patchset for <b>mutt</b> adding a sidebar for browsing, but suffers from the same problem.
</p>

<p>
Some mail setups don't face those problems as they aren't file-system heavy, or use indexers. However, I'm used to MH as a mailstore, and like to drop/filter my mail
into many folders and subfolders, the old-school way. So, I decided to come up with some own solution, hooking up <b>vim</b> as a filebrowser. Note, the scripts below work with MH, only,
and require nmh to be accessible.
</p>

<p>
Add this "pretty" macro to your .muttrc. What it does is running nmh's <b>flists</b> command, uses the output to build a dummy directory tree under /tmp with number of unread
emails (summed up towards the root), then lets <b>vim</b> do the folder browsing. Once a folder is picked, it hands it back to <b>mutt</b>:<br>
</p>

<style type="text/css">
<!--
pre.muttrc { font-family: monospace; color: #dadada; background-color: #000000; }
.Comment { color: #626262; }
.Constant { color: #87afff; font-weight: bold; }
.Special { color: #00d700; font-weight: bold; } 
.Identifier { color: #ffd700; }
.Statement { color: #ff8700; font-weight: bold; }
.PreProc { color: #008787; }
.Type { color: #d7d787; }
-->
</style>
<pre class='muttrc'>
<span class="Comment"># own filebrowser</span> 
<span class="Statement">set</span> <span class="Identifier">wait_key</span>=<span class="Constant">no</span> 
<span class="Statement">macro</span> <span class="Identifier">index</span>,<span class="Identifier">pager</span> <span class="Type">b</span> <span class="Type">'</span><span class="Special">\</span> 
	<span class="PreProc">&lt;</span><span class="PreProc">shell-escape</span><span class="PreProc">&gt;</span><span class="Special">\</span> 
	if [ -d /tmp/mailbox_tree_mirror ]; then rm -r /tmp/mailbox_tree_mirror; fi;<span class="Special">\</span> 
	flists -alpha -recurse <span class="Special">|\</span> 
		sed -E &quot;s@^(.*) has *([0-9]+) .*@\1/\2@&quot; <span class="Special">|\</span> 
		sed -E &quot;s@[+ ]*(/[0-9]+)\$@\1@&quot; <span class="Special">|\</span> 
		awk &quot;<span class="Special">\</span> 
			BEGIN{FS=<span class="Special">\&quot;</span>/<span class="Special">\&quot;</span>}<span class="Special">\</span> 
			{s=<span class="Special">\&quot;\&quot;</span>;for(i=1;i&lt;NF;++i){s=s<span class="Special">\&quot;</span>/<span class="Special">\&quot;</span>\$i;u[s]+=\$NF}}<span class="Special">\</span> 
			END{for(i in u){split(i,d);s=p=<span class="Special">\&quot;\&quot;</span>;for(j in d){if(d[j]){s=s<span class="Special">\&quot;</span>/<span class="Special">\&quot;</span>d[j];p=p<span class="Special">\&quot;</span>/<span class="Special">\&quot;</span>d[j]<span class="Special">\&quot;</span> (<span class="Special">\&quot;</span>u[s]<span class="Special">\&quot;</span>)<span class="Special">\&quot;</span>}}print p}}&quot; <span class="Special">|\</span> 
		while read l; do mkdir -p &quot;/tmp/mailbox_tree_mirror/<span class="Special">$l</span>&quot;; done;<span class="Special">\</span> 
	(cd /tmp/mailbox_tree_mirror/ &amp;&amp; vim -S ~/.mutt/browse_files.vim .);<span class="Special">\</span> 
	<span class="Special">&lt;enter&gt;</span><span class="Special">\</span> 
	<span class="PreProc">&lt;</span><span class="PreProc">enter-command</span><span class="PreProc">&gt;</span><span class="Special">\</span> 
	<span class="Statement">source</span> /tmp/mailbox_tree_mirror/pick<span class="Special">\</span> 
	<span class="Special">&lt;enter&gt;</span><span class="Type">'</span>
</pre>

<p>
The macro is bound to <b>b</b>, and makes some assumptions about some paths. Adapt as needed.
</p>

<p>
Starting <b>vim</b> sources a file I put in ~/.muttrc called browse_files.vim, which
works with either <i>netrw</i> (usually comes with <b>vim</b>) or <i>NERDTree</i>:
</p>

<style type="text/css">
<!--
pre.vim { font-family: monospace; color: #dadada; background-color: #000000; }
.String { color: #8787ff; }
.Normal { color: #dadada; }
-->
</style>
<pre class='vim'>
<span class="Comment">&quot; This folder browser depends on either netrw or NERDTree</span>
<span class="Comment">&quot;</span> <span class="PreProc">Usage:</span>
<span class="Comment">&quot;   - use with muttrc macro building a dummy image of the mailbox hierarchy, then using vim as browser on it</span>
<span class="Comment">&quot;   - browse with vim; gm (go mailbox) is mapped to select inbox and return to mutt</span>

<span class="Statement">fu</span>! SwitchToMailboxInMutt<span class="Special">()</span>
<span class="Comment">	&quot; hack to get path and write to file, so mutt can source it</span>
	:<span class="Statement">silent</span> !<span class="Statement">print</span> push \'<span class="Statement">&lt;change-folder&gt;</span>`span class="Statement">pwd</span>|sed <span class="String">'s@^/.*tmp/mailbox_tree_mirror/@=@'</span>|sed <span class="Statement">-</span>E <span class="String">'s@ \([0-9]+\)(/|$)@/@g'</span>|sed <span class="Statement">-</span>E <span class="String">'s@( )@\&lt;quote-char\&gt;\1@'</span><span class="Statement">g</span>`'\<span class="Statement">&lt;</span><span class="Statement">return</span>\<span class="Statement">&gt;</span> <span class="Statement">&gt;</span> /tmp/mailbox_tree_mirror/pick
	:<span class="Statement">q</span>!
<span class="Statement">endf</span>


<span class="Statement">function</span>! AddMuttSyntaxHL<span class="Special">(</span>parent<span class="Special">)</span>
	<span class="Statement">exec</span> <span class="String">'syn match muttUnreadSel # ([0-9]\+)/# containedin='</span><span class="Statement">.</span><span class="Identifier">a:parent</span><span class="Statement">.</span><span class="String">'Dir'</span>
	<span class="Statement">syn</span> <span class="Type">match</span> <span class="Type">muttUnreadCnt</span> <span class="String">#(</span><span class="String">[0-9]</span><span class="String">\+)#</span>   <span class="Special">containedin=</span>muttUnreadSel
	<span class="Statement">syn</span> <span class="Type">match</span> <span class="Type">muttUnread0</span>   <span class="String">#(0)#</span>         <span class="Special">containedin=</span>muttUnreadCnt
	<span class="Statement">hi</span> <span class="Statement">link</span> <span class="Type">muttUnreadSel</span> <span class="Type">Ignore</span>
	<span class="Statement">hi</span> <span class="Statement">link</span> <span class="Type">muttUnreadCnt</span> <span class="Type">Number</span>
	<span class="Statement">hi</span> <span class="Statement">link</span> <span class="Type">muttUnread0</span>   <span class="Type">Comment</span>
<span class="Statement">endf</span>


<span class="Statement">function</span>! ApplyMuttNERDTreeBindings<span class="Special">()</span>
<span class="Comment">	&quot; Remove clutter and hook into syntax - call syntax setter directly,</span>
<span class="Comment">	&quot; as NT hijacks netrw, and thus is kinda delay-loaded, anyways (IIUC).</span>
	<span class="Statement">let</span> <span class="Identifier">g:NERDTreeMinimalUI</span><span class="Statement">=</span><span class="Constant">1</span>
	<span class="Statement">call</span> <span class="Normal">AddMuttSyntaxHL</span><span class="Special">(</span><span class="String">'NERDTree'</span><span class="Special">)</span>

<span class="Comment">	&quot; hide files, jump to first folder entry</span>
	:<span class="Statement">normal</span> F
	<span class="Statement">call</span> <span class="Identifier">cursor</span><span class="Special">(</span><span class="Identifier">line</span><span class="Special">(</span><span class="String">'.'</span><span class="Special">)</span><span class="Statement">+</span><span class="Constant">4</span><span class="Special">)</span>

<span class="Comment">	&quot; gm picks this directory</span>
	<span class="Statement">map</span> gm cd<span class="Special">&lt;</span><span class="Special">CR</span><span class="Special">&gt;</span>:call SwitchToMailboxInMutt()<span class="Special">&lt;</span><span class="Special">CR</span><span class="Special">&gt;</span>
<span class="Statement">endf</span>


<span class="Statement">function</span>! ApplyMuttNetrwBindings<span class="Special">()</span>
<span class="Comment">	&quot; Hook into syntax, needs to happen after netrw's syntax is fully loaded.</span>
	<span class="Statement">autocmd</span> <span class="Type">FileType</span> netrw <span class="Statement">call</span> <span class="Normal">AddMuttSyntaxHL</span><span class="Special">(</span><span class="String">'netrw'</span><span class="Special">)</span>

<span class="Comment">	&quot; Use tree mode, only, and hide all files</span>
	<span class="Statement">let</span> <span class="Identifier">g:netrw_liststyle</span><span class="Statement">=</span><span class="Constant">3</span>
	<span class="Statement">let</span> <span class="Identifier">g:netrw_list_hide</span><span class="Statement">=</span><span class="String">'.*[^/]$'</span>

<span class="Comment">	&quot; gm picks this directory - long macro b/c of toggle-behaviour of netrw's browser, didn't find a way to get path under cursor</span>
	<span class="Statement">map</span> gm <span class="Special">&lt;</span><span class="Special">CR</span><span class="Special">&gt;</span>:let s=b:netrw_curdir<span class="Special">&lt;</span><span class="Special">CR</span><span class="Special">&gt;&lt;</span><span class="Special">CR</span><span class="Special">&gt;</span>:if(strlen(b:netrw_curdir)&gt;strlen(s))\|let s=b:netrw_curdir\|endif<span class="Special">&lt;</span><span class="Special">CR</span><span class="Special">&gt;</span>:exec 'cd '.fnameescape(s)<span class="Special">&lt;</span><span class="Special">CR</span><span class="Special">&gt;</span>:call SwitchToMailboxInMutt()<span class="Special">&lt;</span><span class="Special">CR</span><span class="Special">&gt;</span>
<span class="Statement">endf</span>


<span class="Statement">if</span> &amp;ft <span class="Statement">==#</span> <span class="String">&quot;nerdtree&quot;</span>
	<span class="Statement">call</span> <span class="Normal">ApplyMuttNERDTreeBindings</span><span class="Special">()</span>
<span class="Statement">else</span>
	<span class="Statement">call</span> <span class="Normal">ApplyMuttNetrwBindings</span><span class="Special">()</span>
<span class="Statement">endif</span>

</pre>

<p>
That's it - instead of having to deal with <b>mutt</b>'s browser, I now hit <b>b</b>, browse and when I found the folder I want to browse to, hit <b>gm</b> in vim (goto mailbox), and
I'm back in <b>mutt</b>. Also, I get a quick overview of all my folders and the unread emails, even in color!
</p>

<div class="tc"><img src="/media/mutt-folder-browser.gif" alt="mutt/mh with vim folder browser"/></div>

]]></content:encoded>
    </item>




  </channel>
</rss>

