emacs/var/elfeed/db/data/41/41313b8c144a56a4e58e72756e33e754d48fbfcd
2022-01-03 12:49:32 -06:00

87 lines
9.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<p>I dont know about you, but I like to monitor my Emacs configuration to see if
it is growing out of control due to my penchant for experimenting with ELisp and
new packages. This led me to a simple question: why not have a command that can
produce a summary of the installed packages? Specifically, I want to know the
total number of packages installed and Id like to list the packages for every
archive set up in <code class="language-plaintext highlighter-rouge">package-archives</code>.</p>
<div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">mu-package-report</span> <span class="p">()</span>
<span class="s">"Report total package counts grouped by archive."</span>
<span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
<span class="p">(</span><span class="nv">package-refresh-contents</span><span class="p">)</span>
<span class="p">(</span><span class="nv">mu--display-package-report</span>
<span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">arch-pkgs</span> <span class="p">(</span><span class="nv">mu--archive-packages</span><span class="p">))</span>
<span class="p">(</span><span class="nv">counts</span> <span class="p">(</span><span class="nv">seq-sort-by</span> <span class="nf">#'</span><span class="nb">cdr</span> <span class="nf">#'</span><span class="nb">&gt;</span> <span class="p">(</span><span class="nv">mu--archive-counts</span> <span class="nv">arch-pkgs</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">by-arch</span> <span class="p">(</span><span class="nv">seq-group-by</span> <span class="nf">#'</span><span class="nb">car</span> <span class="nv">arch-pkgs</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">concat</span>
<span class="p">(</span><span class="nb">format</span> <span class="s">"Total packages: %s\n\n"</span> <span class="p">(</span><span class="nb">apply</span> <span class="nf">#'</span><span class="nb">+</span> <span class="p">(</span><span class="nb">mapcar</span> <span class="nf">#'</span><span class="nb">cdr</span> <span class="nv">counts</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">mapconcat</span>
<span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">archive</span><span class="p">)</span>
<span class="p">(</span><span class="nv">concat</span> <span class="s">"• "</span>
<span class="p">(</span><span class="nb">format</span> <span class="s">"%s (%s)"</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">archive</span><span class="p">)</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">archive</span><span class="p">))</span>
<span class="s">": "</span>
<span class="p">(</span><span class="nv">mapconcat</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">ap-pair</span><span class="p">)</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">ap-pair</span><span class="p">))</span>
<span class="p">(</span><span class="nv">alist-get</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">archive</span><span class="p">)</span> <span class="nv">by-arch</span><span class="p">)</span>
<span class="s">", "</span><span class="p">)))</span>
<span class="nv">counts</span>
<span class="s">"\n\n"</span><span class="p">)))))</span>
</code></pre></div></div>
<p>Now, lets unpack it.</p>
<p>I want my report buffer to be displayed in a new window, so this is what
<code class="language-plaintext highlighter-rouge">mu--display-package-report</code> does:</p>
<div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">mu--display-package-report</span> <span class="p">(</span><span class="nv">output</span><span class="p">)</span>
<span class="s">"Display OUTPUT in a popup buffer."</span>
<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">buffer-name</span> <span class="s">"*package-report*"</span><span class="p">))</span>
<span class="p">(</span><span class="nv">with-help-window</span> <span class="nv">buffer-name</span>
<span class="p">(</span><span class="nv">with-current-buffer</span> <span class="nv">buffer-name</span>
<span class="p">(</span><span class="nv">visual-line-mode</span> <span class="mi">1</span><span class="p">)</span>
<span class="p">(</span><span class="nv">erase-buffer</span><span class="p">)</span>
<span class="p">(</span><span class="nv">insert</span> <span class="nv">output</span><span class="p">)</span>
<span class="p">(</span><span class="nv">goto-char</span> <span class="p">(</span><span class="nv">point-min</span><span class="p">))))))</span>
</code></pre></div></div>
<p>Next, I want to know from which archive (e.g., GNU ELPA) a package is coming to
my system:</p>
<div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">mu--archive-packages</span> <span class="p">()</span>
<span class="s">"Return a list of (archive . package) cons cells."</span>
<span class="p">(</span><span class="nv">seq-reduce</span>
<span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">res</span> <span class="nc">package</span><span class="p">)</span>
<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">archive</span> <span class="p">(</span><span class="nv">package-desc-archive</span>
<span class="p">(</span><span class="nb">cadr</span> <span class="p">(</span><span class="nv">assq</span> <span class="nc">package</span> <span class="nv">package-archive-contents</span><span class="p">))))</span>
<span class="p">(</span><span class="nv">pkg</span> <span class="p">(</span><span class="nb">symbol-name</span> <span class="nc">package</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">push</span> <span class="p">(</span><span class="nb">cons</span> <span class="nv">archive</span> <span class="nv">pkg</span><span class="p">)</span> <span class="nv">res</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">mapcar</span> <span class="nf">#'</span><span class="nb">car</span> <span class="nv">package-alist</span><span class="p">)</span>
<span class="no">nil</span><span class="p">))</span>
</code></pre></div></div>
<p>This is nice because now I can also have the number of packages for every archive.</p>
<div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">mu--archive-counts</span> <span class="p">(</span><span class="nv">arch-pkgs</span><span class="p">)</span>
<span class="s">"Return a list of cons cells from alist ARCH-PKGS.
The cars are package archives, the cdrs are the number of
packages installed from each archive."</span>
<span class="p">(</span><span class="nv">seq-reduce</span>
<span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">counts</span> <span class="nv">key</span><span class="p">)</span>
<span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nb">cons</span> <span class="nv">key</span> <span class="p">(</span><span class="nb">+</span> <span class="mi">1</span> <span class="p">(</span><span class="nb">or</span> <span class="p">(</span><span class="nb">cdr</span> <span class="p">(</span><span class="nb">assoc</span> <span class="nv">key</span> <span class="nv">counts</span><span class="p">))</span> <span class="mi">0</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">assoc-delete-all</span> <span class="nv">key</span> <span class="nv">counts</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">mapcar</span> <span class="nf">#'</span><span class="nb">car</span> <span class="nv">arch-pkgs</span><span class="p">)</span>
<span class="no">nil</span><span class="p">))</span>
</code></pre></div></div>
<p>The rest of the code in <code class="language-plaintext highlighter-rouge">mu-package-report</code> deals with formatting the output.
For example, I am using <code class="language-plaintext highlighter-rouge">seq-sort-by</code> to have the archive with the highest
number of packages on top. As for the <code class="language-plaintext highlighter-rouge">mapconcat</code> producing the actual bullet
points, the Emacs community came to the rescue on <a href="https://emacs.stackexchange.com/questions/65088/format-alist-into-bullet-points">Emacs Stack
Exchange</a>.</p>
<p>Finally, this is how <kbd>M-x mu-package-report RET</kbd> looks like:</p>
<div style="text-align: center; padding-top: 5px; padding-bottom: 5px;">
<a href="https://raw.githubusercontent.com/manuel-uberti/manuel-uberti.github.io/master/images/package-report.png" target="_blank">
<img src="https://www.manueluberti.eu/images/package-report.png" />
</a>
</div>