<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Alex's Adventures on the Infobahn - code</title><link href="https://www.bennee.com/~alex/" rel="alternate"></link><link href="https://www.bennee.com/~alex/blog/tag/code/feed" rel="self"></link><id>https://www.bennee.com/~alex/</id><updated>2012-07-24T15:09:00+01:00</updated><subtitle>the wanderings of a supposed digital native</subtitle><entry><title>Many ways to skin a GNU</title><link href="https://www.bennee.com/~alex/blog/2012/07/24/many-ways-to-skin-a-gnu/" rel="alternate"></link><published>2012-07-24T15:09:00+01:00</published><updated>2012-07-24T15:09:00+01:00</updated><author><name>alex</name></author><id>tag:www.bennee.com,2012-07-24:/~alex/blog/2012/07/24/many-ways-to-skin-a-gnu/</id><summary type="html">&lt;p&gt;It's time for another examination of Emacs LISP and a selection of ways to solve the same problem. In this case it's the behaviour of the &lt;em&gt;etags-select&lt;/em&gt; package. This handy function will present a selection table when it finds multiple definitions of the same tag. This is handy if your …&lt;/p&gt;</summary><content type="html">&lt;p&gt;It's time for another examination of Emacs LISP and a selection of ways to solve the same problem. In this case it's the behaviour of the &lt;em&gt;etags-select&lt;/em&gt; package. This handy function will present a selection table when it finds multiple definitions of the same tag. This is handy if your global TAGs file contains reference to multiple binaries that might have a common code heritage. It even provides a handy function &lt;em&gt;etags-select-find-tag-at-point&lt;/em&gt; which will check &lt;em&gt;point&lt;/em&gt; to see if that is a tag. However if &lt;em&gt;point&lt;/em&gt; is on a blank line I'd prefer it to just prompt me for a tag name.&lt;/p&gt;
&lt;p&gt;First version:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
(defun my-naive-find-tag ()
  &amp;quot;Find at point or fall back&amp;quot;
  (interactive)
  (unless (etags-select-find-tag-at-point)
    (etags-select-find-tag)))
&lt;/pre&gt;
&lt;p&gt;Unfortunately this fails rather badly. I naively assumed &lt;em&gt;etags-select-find-tag-at-point&lt;/em&gt; would return &lt;em&gt;'nil&lt;/em&gt; on failure. Instead it bombs out with an error because &lt;em&gt;etags-select-find&lt;/em&gt; expects a parameter and when &lt;em&gt;find-tag-default&lt;/em&gt; fails it errors out.&lt;/p&gt;
&lt;p&gt;Second version:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
(defun my-working-find-tag()
  &amp;quot;Find tag and call etags-select-find-tag-at-point if it will work&amp;quot;
  (interactive)
  (if (find-tag-default)
      (etags-select-find-tag-at-point)
    (etags-select-find-tag)))
&lt;/pre&gt;
&lt;p&gt;This works by checking &lt;em&gt;find-tag-default&lt;/em&gt; will work before calling &lt;em&gt;etags-select-find-tag-at-point&lt;/em&gt;. Of course there is some duplication here because &lt;em&gt;find-tag-default&lt;/em&gt; will get called again once I know it will work. Dissatisfied I asked the &lt;a class="reference external" href="%20http://stackoverflow.com/questions/11578723/whats-the-best-way-in-elisp-to-trap-an-error-case"&gt;stackoverflow&lt;/a&gt; community for suggestions. The first solution is to simply trap the error case.&lt;/p&gt;
&lt;p&gt;Third version:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
(defun my-try-except-find-tag()
  &amp;quot;Find at point or fall to etags-select-find-tag on error&amp;quot;
  (interactive)
  (unless (ignore-errors (or (etags-select-find-tag-at-point) 't))
    (etags-select-find-tag)))
&lt;/pre&gt;
&lt;p&gt;This works by utilising deep lisp black magic to stop the error propagating and returning a 'nil if it does. The &lt;em&gt;(or (etags-select-find-tag-at-point) 't)&lt;/em&gt; line is to ensure a successful call returns something so we don't then fall through. Interestingly the comments around &lt;em&gt;subr.el&lt;/em&gt; mentions some of the keywords used may be redefined by common lisp.&lt;/p&gt;
&lt;p&gt;Forth version:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
(defun my-efficent-find-tag()
  &amp;quot;Find tag at point, caching find-tag-default&amp;quot;
  (interactive)
  (let ((ftd (find-tag-default)))
    (flet ((find-tag-default () ftd))
      (if (find-tag-default)
          (etags-select-find-tag-at-point)
        (etags-select-find-tag)))))
&lt;/pre&gt;
&lt;p&gt;While I expected something like &lt;em&gt;ignore-errors&lt;/em&gt; to exist this demonstrates the flexibility of dynamic languages like Emacs Lisp. The key is the use of &lt;em&gt;flet&lt;/em&gt; to redefine &lt;em&gt;find-tag-default&lt;/em&gt; so when it gets executed again inside &lt;em&gt;etags-select-find-tag-at-point&lt;/em&gt; it simply returns the cached value.&lt;/p&gt;
&lt;p&gt;So as usual with these posts I try to invite feedback. Which of these forms do you prefer? Would you solve the problem another way? Have you just learnt something new about Emacs Lisp?&lt;/p&gt;
</content><category term="geek"></category><category term="code"></category><category term="elisp"></category><category term="emacs"></category></entry><entry><title>completion-ignored-extensions</title><link href="https://www.bennee.com/~alex/blog/2011/04/13/completion-ignored-extensions/" rel="alternate"></link><published>2011-04-13T16:27:00+01:00</published><updated>2011-04-13T16:27:00+01:00</updated><author><name>alex</name></author><id>tag:www.bennee.com,2011-04-13:/~alex/blog/2011/04/13/completion-ignored-extensions/</id><summary type="html">&lt;p&gt;I've been using the rather spiffy &lt;a class="reference external" href="http://www.emacswiki.org/emacs/LustyExplorer"&gt;Lusty Explorer&lt;/a&gt; for some time for my buffer and file finding. However it (I thought) had a rather annoying bug where I could never tab directly into some of the repositories I was hacking on. Eventually I figured out that the problem was down …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I've been using the rather spiffy &lt;a class="reference external" href="http://www.emacswiki.org/emacs/LustyExplorer"&gt;Lusty Explorer&lt;/a&gt; for some time for my buffer and file finding. However it (I thought) had a rather annoying bug where I could never tab directly into some of the repositories I was hacking on. Eventually I figured out that the problem was down to the way I name them.&lt;/p&gt;
&lt;p&gt;My naming scheme for any repository is generally to add the version control extension to the directory. This is more for my benefit than emacs as it's quite capable of working this out for itself in any given repo. However it turns out that Lusty was being a good emacs citizen and using the variable &lt;em&gt;completion-ignored-extensions&lt;/em&gt; which included the pattern &amp;quot;.git/&amp;quot; and duly hiding my repo directories from completion. In fact there are a number of patterns in there which should probably be more specific. I wrote this to fix the problem:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
(setq completion-ignored-extensions
      (mapcar '(lambda (ext)
                 (if (string-equal &amp;quot;/&amp;quot; (substring ext -1 nil))
                     (concat &amp;quot;^&amp;quot; ext)
                   ext)) completion-ignored-extensions))
&lt;/pre&gt;
&lt;p&gt;It still seems a little ugly to me so given the &lt;a class="reference external" href="http://www.bennee.com/~alex/blog/2010/08/10/looping-in-lisp/"&gt;last time I berated elisp's style&lt;/a&gt; gained so many useful suggestions I'd welcome improvements.&lt;/p&gt;
</content><category term="geek"></category><category term="code"></category><category term="elisp"></category><category term="emacs"></category><category term="examples"></category></entry><entry><title>Code Insomnia</title><link href="https://www.bennee.com/~alex/blog/2010/08/27/code-insomnia/" rel="alternate"></link><published>2010-08-27T06:14:00+01:00</published><updated>2010-08-27T06:14:00+01:00</updated><author><name>alex</name></author><id>tag:www.bennee.com,2010-08-27:/~alex/blog/2010/08/27/code-insomnia/</id><summary type="html">&lt;p&gt;It's very rare programs are ever complete, let alone perfect. I pulled a fairly late session night to push a release out at work. Hopefully testing have a chance to raise any major clangers before I go on holiday for the next month. However the combination of late night coding …&lt;/p&gt;</summary><content type="html">&lt;p&gt;It's very rare programs are ever complete, let alone perfect. I pulled a fairly late session night to push a release out at work. Hopefully testing have a chance to raise any major clangers before I go on holiday for the next month. However the combination of late night coding plus fretting meant I didn't really sleep well. While I may have technically entered &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Rapid_eye_movement_sleep"&gt;REM&lt;/a&gt; sleep dreaming about code and architectural deficiencies in your code isn't the most refreshing way to let your brain unwind. I eventually gave up and got up. It's been a while since I heard Farming Today.&lt;/p&gt;
</content><category term="geek"></category><category term="code"></category><category term="holiday"></category><category term="insomnia"></category></entry><entry><title>Looping in LISP</title><link href="https://www.bennee.com/~alex/blog/2010/08/10/looping-in-lisp/" rel="alternate"></link><published>2010-08-10T09:04:00+01:00</published><updated>2010-08-10T09:04:00+01:00</updated><author><name>alex</name></author><id>tag:www.bennee.com,2010-08-10:/~alex/blog/2010/08/10/looping-in-lisp/</id><summary type="html">&lt;p&gt;Loops are a fairly important part of any programming language and fairly fundamental to a language that is purported to be all about manipulating lists. However it's not something I use that often in my .emacs code so I thought it might be useful to discuss the various options with …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Loops are a fairly important part of any programming language and fairly fundamental to a language that is purported to be all about manipulating lists. However it's not something I use that often in my .emacs code so I thought it might be useful to discuss the various options with some examples.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; I run emacs on a number of machines, each with a different set of sound sets. I want to set up set up a valid sound for erc but I don't want an overly verbose set of cases depending on what machine I'm on. Instead a given a list of sound files I want a function that will return the first one that actually exists.&lt;/p&gt;
&lt;p&gt;This problem can be easily generalised into return the first valid path from a list of paths.&lt;/p&gt;
&lt;div class="section" id="first-version-pure-emacs-lisp"&gt;
&lt;h2&gt;First version: pure emacs lisp&lt;/h2&gt;
&lt;pre class="literal-block"&gt;
; the 'elisp' way
(defun find-valid-file-elisp-way (list-of-files)
  &amp;quot;Go though a list of files and return the first one that is present&amp;quot;
  (let (r '())
    (mapc '(lambda (f)
             (if (file-exists-p f) (add-to-list 'r f)))
          list-of-files)
    (car r)))
&lt;/pre&gt;
&lt;p&gt;First impressions aren't good. The lisp parenthesis do seem to get in the way of making what is happening clear. However it's using one of common &lt;a class="reference external" href="http://www.gnu.org/s/emacs/manual/html_node/elisp/Mapping-Functions.html"&gt;mapping functions&lt;/a&gt; you see a lot of in lisp. A mapping function essentially takes a list, applies a function to each element of the list and eventually returns a result. The most common of the mapping functions is &lt;em&gt;mapcar&lt;/em&gt; which returns a modified list as a result. In this case that isn't what we want so we use &lt;em&gt;mapc&lt;/em&gt; where the only value that is built up is the result &lt;em&gt;r&lt;/em&gt; as we identify each valid file. The final return value is just the first entry in that list. This does mean we have processed the whole list of alternatives which is sub-optimal.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="second-version-common-lisp-version"&gt;
&lt;h2&gt;Second version: Common Lisp Version&lt;/h2&gt;
&lt;pre class="literal-block"&gt;
(defun find-valid-file-clisp-way (list-of-files)
  &amp;quot;Go though a list of files and return the first one that is present&amp;quot;
  (loop for path in list-of-files
        until (file-exists-p path)
        finally return path))
&lt;/pre&gt;
&lt;p&gt;This version probably is the easiest to read for people familiar with other programming languages. The intention of the code jumps out at you. However the actual implementation is done with a macro. If you look at the help for &lt;em&gt;loop&lt;/em&gt; you'll see it can take a number of different forms - follow that to the code and you'll see a fairly complex elisp implementation. However to my mind still easier to follow than the pure elisp version with mapc.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="third-version-using-the-dolist-macro"&gt;
&lt;h2&gt;Third Version: Using the dolist macro&lt;/h2&gt;
&lt;pre class="literal-block"&gt;
; using 'cl-macs
(defun find-valid-file-dolist-way (list-of-files)
  &amp;quot;Go though a list of files and return the first one that is present&amp;quot;
  (dolist (f list-of-files)
    (if (file-exists-p f)
        (return f))))
&lt;/pre&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;This is yet another version using an LISP macro but this one has considerably less potential forms to cause confusion. It's fairly comprehensible what is going on and even follows the traditional parenthesis happy form. It also takes advantage of the common LISP &lt;em&gt;return&lt;/em&gt; to early return from the loop when we detect a valid file. If it makes it to the end of the list it evaluates the 3rd optional form to calculate the result which in this case will be 'nil.&lt;/div&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;So what do you think? What version do you prefer? Where does the balance lie between writing code is LISPy ways and for code comprehension? Are there any other ways to solve this particular problem? I'll be looking forward to your comments.&lt;/p&gt;
&lt;/div&gt;
</content><category term="geek"></category><category term="code"></category><category term="elisp"></category><category term="emacs"></category><category term="examples"></category><category term="lisp"></category></entry></feed>