<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>emacs &amp;mdash; Sebastian Wiesner</title>
    <link>https://swsnr.writeas.com/tag:emacs</link>
    <description>System engineer for satellite mission planning. Gnome. Rust. Arch.  </description>
    <pubDate>Sat, 09 May 2026 13:27:24 +0000</pubDate>
    <image>
      <url>https://i.snap.as/9knB2j11.jpg</url>
      <title>emacs &amp;mdash; Sebastian Wiesner</title>
      <link>https://swsnr.writeas.com/tag:emacs</link>
    </image>
    <item>
      <title>Reproduce bugs in emacs -Q</title>
      <link>https://swsnr.writeas.com/reproduce-bugs-in-emacs-q?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[emacs&#xA;&#xA;  Please reproduce this issue in emacs -Q.&#xA;&#xA;This is a sentence you will often read when you report bugs in Emacs packages; it&#39;s often a quick reply from a developer and goes with no further explanation or even the slightest clue on what you’re supposed to do.  If you ever found yourself in that situation then this post is for you: I’ll explain what it means to “reproduce a bug in emacs -Q”, how to do that properly, and why developers ask you for this.&#xA;&#xA;!--more--&#xA;&#xA;How do you reproduce a bug in emacs -Q? &#xA;&#xA;emacs -Q provides a “pure” Emacs session which loads no packages and absolutely no configuration files.&#xA;&#xA;----&#xA;There is also emacs -q which will make Emacs ignore your init  (e.g. ~/.emacs or ~/.emacs.d/init.el) and packages that you installed with the built-in packages, but still load code from the global Emacs site which includes Emacs extensions that you installed with the system’s package manager (e.g. apt-get).  As such this option is insufficient to reproduce bugs because there may still be packages that infer.&#xA;----&#xA;&#xA;To start one open a terminal window and type emacs -Q.  On OS X use the slightly more convoluted command open --new -a Emacs.app --args -Q to start a fresh GUI Emacs. &#xA;&#xA;Now initialise Emacs’ package system with M-x package-initialize.  Normally this happens in your init file but since emacs -Q doesn’t load it you need to do that explicitly.  If you omit this step you can’t access your installed packages in emacs -Q so it’s a pretty important one.&#xA;&#xA;On OS X you should also run M-x exec-path-from-shell-initialize now, provided that you installed [exec-path-from-shell] in your Emacs.  This ensures that your $PATH in Emacs is correct, i.e. that you have access to the same executables as in your terminal.&#xA;&#xA;Eventually enable the buggy package by following its setup instructions. You should now manually execute the commands that you copied to your init file when you installed the package in your Emacs.  For instance, if you’d like to reproduce a bug in [Flycheck] you should now type M-x global-flycheck-mode to enable Flycheck.&#xA;&#xA;Now you’re ready to reproduce the bug, simply by following the same steps that triggered the bug in your normal Emacs session.  For instance, if you’d like to show a broken syntax checker in Flycheck visit the same file that triggered the bug in your normal Emacs session.&#xA;&#xA;While following these steps please take notes about the commands that you run, the keys that you type and the things that you do to reproduce the bug, and include these notes in your bug report.&#xA;&#xA;Why do developers ask for this? &#xA;&#xA;As package developers we ask you to reproduce a bug in this session because it’s an essential first step to pin down the bug.&#xA;&#xA;Emacs provides absolutely no isolation between all the packages that are loaded in your normal Emacs session.  This is blessing and curse at the same time: It allows you to customise almost everything in Emacs but a single faulty package can break down your entire Emacs session.  We can’t tell if the bug that you reported to us is really a bug in our own package or if there is another buggy or misbehaving package in your Emacs configuration that breaks our package.&#xA;&#xA;If you can reproduce a bug in emacs -Q you give us an important clue: The bug is in our own code and we only need to look at our own code to find it.  That is much simpler than looking at your entire Emacs configuration and all the other packages that you have installed.  What’s more you also enable us to reproduce the bug ourselves with just our package and a pure Emacs session, and if we can reproduce a bug we are halfway to fixing it.&#xA;&#xA;[good-reports]: https://geoff.greer.fm/2015/08/15/how-to-write-good-bug-reports/&#xA;[exec-path-from-shell]: https://github.com/purcell/exec-path-from-shell&#xA;[flycheck]: https://www.flycheck.org&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://swsnr.writeas.com/tag:emacs" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">emacs</span></a></p>

<blockquote><p>Please reproduce this issue in <code>emacs -Q</code>.</p></blockquote>

<p>This is a sentence you will often read when you report bugs in Emacs packages; it&#39;s often a quick reply from a developer and goes with no further explanation or even the slightest clue on what you’re supposed to do.  If you ever found yourself in that situation then this post is for you: I’ll explain what it means to “reproduce a bug in <code>emacs -Q</code>”, how to do that properly, and why developers ask you for this.</p>



<h2 id="how-do-you-reproduce-a-bug-in-emacs-q" id="how-do-you-reproduce-a-bug-in-emacs-q">How do you reproduce a bug in emacs -Q?</h2>

<p><code>emacs -Q</code> provides a “pure” Emacs session which loads no packages and absolutely no configuration files.</p>

<hr/>

<p>There is also <code>emacs -q</code> which will make Emacs ignore your init  (e.g. <code>~/.emacs</code> or <code>~/.emacs.d/init.el</code>) and packages that you installed with the built-in packages, but still load code from the global Emacs site which includes Emacs extensions that you installed with the system’s package manager (e.g. <code>apt-get</code>).  As such this option is insufficient to reproduce bugs because there may still be packages that infer.</p>

<hr/>

<p>To start one open a terminal window and type <code>emacs -Q</code>.  On OS X use the slightly more convoluted command <code>open --new -a Emacs.app --args -Q</code> to start a fresh GUI Emacs.</p>

<p>Now initialise Emacs’ package system with <code>M-x package-initialize</code>.  Normally this happens in your init file but since <code>emacs -Q</code> doesn’t load it you need to do that explicitly.  If you omit this step you can’t access your installed packages in <code>emacs -Q</code> so it’s a pretty important one.</p>

<p>On OS X you should also run <code>M-x exec-path-from-shell-initialize</code> now, provided that you installed <a href="https://github.com/purcell/exec-path-from-shell" rel="nofollow">exec-path-from-shell</a> in your Emacs.  This ensures that your <code>$PATH</code> in Emacs is correct, i.e. that you have access to the same executables as in your terminal.</p>

<p>Eventually enable the buggy package by following its setup instructions. You should now manually execute the commands that you copied to your init file when you installed the package in your Emacs.  For instance, if you’d like to reproduce a bug in <a href="https://www.flycheck.org" rel="nofollow">Flycheck</a> you should now type <code>M-x global-flycheck-mode</code> to enable Flycheck.</p>

<p>Now you’re ready to reproduce the bug, simply by following the same steps that triggered the bug in your normal Emacs session.  For instance, if you’d like to show a broken syntax checker in Flycheck visit the same file that triggered the bug in your normal Emacs session.</p>

<p>While following these steps please take notes about the commands that you run, the keys that you type and the things that you do to reproduce the bug, and include these notes in your bug report.</p>

<h2 id="why-do-developers-ask-for-this" id="why-do-developers-ask-for-this">Why do developers ask for this?</h2>

<p>As package developers we ask you to reproduce a bug in this session because it’s an essential first step to pin down the bug.</p>

<p>Emacs provides absolutely <em>no isolation</em> between all the packages that are loaded in your normal Emacs session.  This is blessing and curse at the same time: It allows you to customise almost everything in Emacs but a single faulty package can break down your entire Emacs session.  We can’t tell if the bug that you reported to us is really a bug in our own package or if there is another buggy or misbehaving package in your Emacs configuration that breaks our package.</p>

<p>If you can reproduce a bug in <code>emacs -Q</code> you give us an important clue: The bug is in our own code and we only need to look at our own code to find it.  That is much simpler than looking at your <em>entire</em> Emacs configuration and all the other packages that you have installed.  What’s more you also enable us to reproduce the bug <em>ourselves</em> with just our package and a pure Emacs session, and if we can reproduce a bug <a href="https://geoff.greer.fm/2015/08/15/how-to-write-good-bug-reports/" rel="nofollow">we are halfway to fixing it</a>.</p>
]]></content:encoded>
      <guid>https://swsnr.writeas.com/reproduce-bugs-in-emacs-q</guid>
      <pubDate>Sat, 28 Nov 2015 23:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Emacs script pitfalls</title>
      <link>https://swsnr.writeas.com/emacs-script-pitfalls?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[emacs&#xA;&#xA;Emacs isn&#39;t just an editor, it’s an entire Emacs Lisp interpreter and environment.  We can use Emacs Lisp not only to extend and customize our beloved editor, but also to write entire programs and applications.  Nic Ferrier’s elnode server is the most ambitious Emacs Lisp application of this sort, but we can start at a smaller scale and try to write our shell scripts and tools with Emacs Lisp.&#xA;&#xA;!--more--&#xA;&#xA;However, it turns out that writing programs in Emacs Lisp is more intricate than it looks at a first glance.  Emacs decades-long history as interactive application have left deep marks in Emacs and Emacs Lisp, which make independent noninteractive scripts difficult.&#xA;&#xA;[elnode]: https://github.com/nicferrier/elnode&#xA;&#xA;Making Emacs Lisp scripts executable&#xA;&#xA;In the early days, we’d muck about with --no-init-file, --batch and --load to enter noninteractive mode an.e.d load a file.  Nowadays Emacs has a convenient --script option to load and evaluate a specific file, but how to make a proper shebang out of it?  The naive approach won&#39;t do:&#xA;&#xA;!/usr/bin/emacs --script&#xA;(message &#34;Hello world&#34;)&#xA;&#xA;Emacs is not /bin/sh, and its location varies between different systems. There may even be different Emacs versions at different places.  For instance, on OS X /usr/bin/emacs is an outdated Emacs 22, and the “real” Emacs is typically installed via Homebrew at /usr/local/bin/emacs.&#xA;&#xA;Normally, we&#39;d accommodate these differences with /usr/bin/env:&#xA;&#xA;!/usr/bin/env emacs --script&#xA;(message &#34;Hello world&#34;)&#xA;&#xA;But this just raises another portability issue:  Linux doesn’t split arguments in the shebang, and sends emacs --script as a single argument to /usr/bin/env, which doesn’t really do the trick.&#xA;&#xA;To make our script executable in a portable and reliable way, we need to resort to some dirty trickery (see https://stackoverflow.com/a/6259330/355252):&#xA;&#xA;!/bin/sh&#xA;&#34;:&#34;; exec emacs --script &#34;$0&#34; &#34;$@&#34; # -- mode: emacs-lisp; lexical-binding: t; --&#xA;(message &#34;Hello world&#34;)&#xA;&#xA;This wraps the Emacs Lisp code into a POSIX shell script which calls out to emacs with appropriate arguments.  The semicolon in the second line hides the exec statement from Emacs, and the no-op colon statement turns this into a proper sequence statement for the shell.  The colon in turn is quoted to make it appear as string literal to Emacs Lisp.&#xA;&#xA;Eventually some file local variables tell Emacs to use Emacs Lisp Mode for the script, regardless of the shebang, and to enable lexical binding.&#xA;&#xA;This particularly evil trick works reliably with any POSIX shell.  Even better, we can now pass arbitrary arguments to the emacs executable, which allows us to get rid of a little nuisance of --script.&#xA;&#xA;Inhibiting site-start&#xA;&#xA;The --script option is just a shortcut for --batch -l, i.e. enter batch mode and load the given file.  Batch Mode mainly means that Emacs will not create a frame, but instead exit after processing all command line arguments (which includes evaluating our script).  Besides, --batch also disables the user initialization file.  However, it still processes the global site initialization file:&#xA;&#xA;  --batch implies -q (do not load an initialization file), but site-start.el is loaded nonetheless. It also causes Emacs to exit after processing all the command options. In addition, it disables auto-saving except in buffers for which auto-saving is explicitly requested.&#xA;&#xA;The global site initialization is often a kitchen sink which sets up globally installed packages and adds many seconds to Emacs’ startup time in the worst case.  Besides, it’s not really a good idea to load arbitrary packages before our script even gets a chance to run.&#xA;&#xA;We can opt out of the global site initialization by adding --quick to the emacs options of our script, which gives us a bare-bones Emacs without any initialization:&#xA;&#xA;!/bin/sh&#xA;&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # -- mode: emacs-lisp; lexical-binding: t; --&#xA;(message &#34;Hello world&#34;)&#xA;&#xA;If you need to, you can still load the global site initialization explicitly from site-run-file:&#xA;&#xA;(load site-run-file &#39;no-error &#39;no-message)&#xA;&#xA;[--script]: https://www.gnu.org/software/emacs/manual/htmlnode/emacs/Initial-Options.html&#xA;[--batch]: https://www.gnu.org/software/emacs/manual/htmlnode/emacs/Initial-Options.html&#xA;[srf]: https://www.gnu.org/software/emacs/manual/htmlnode/elisp/Init-File.html#index-site002drun002dfile&#xA;&#xA;Processing command line arguments &#xA;&#xA;Emacs exposes the command line arguments in command-line-args-left alias argv (not to be confused with command-line-args which holds all Emacs options, including those that Emacs already interpreted, and is of little use in scripts):&#xA;&#xA;!/bin/sh&#xA;&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # -- mode: emacs-lisp; lexical-binding: t; --&#xA;&#xA;(message &#34;Hello: %S&#34; argv)&#xA;&#xA;$ ./hello.el &#39;John Doe&#39;&#xA;Hello: (&#34;John Doe&#34;)&#xA;&#xA;Passing options doesn’t work that well, though:&#xA;&#xA;$ ./hello.el --greeting &#39;Good morning %s!&#39; &#39;John Doe&#39;&#xA;Hello: (&#34;--greeting&#34; &#34;Good morning %s!&#34; &#34;John Doe&#34;)&#xA;Unknown option `--greeting&#39;&#xA;&#xA;Emacs tries to interpret --greeting on its own, and rightfully complains that it has never heard of any such option.  How do we keep Emacs away from our options?&#xA;&#xA;The source code of startup.el, more precisely the function command-line-1, reveals the solution:  Emacs processes all command line arguments immediately, in order of their appearance.  After processing, each argument is removed from&#xA;argv, hence the name command-line-args-left.&#xA;&#xA;Since command-line-args-left aka argv is a global variable, we can just remove all remaining arguments from argv before our script exits:&#xA;&#xA;!/bin/sh&#xA;&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # -- mode: emacs-lisp; lexical-binding: t; --&#xA;&#xA;(message &#34;Hello: %S&#34; argv)&#xA;(setq argv nil)&#xA;&#xA;$ ./hello.el --greeting &#39;Good morning %s!&#39; &#39;John Doe&#39;&#xA;Hello: (&#34;--greeting&#34; &#34;Good morning %s!&#34; &#34;John Doe&#34;)&#xA;&#xA;We can also just force Emacs to exit early, which is good style anyway:&#xA;&#xA;!/bin/sh&#xA;&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # -- mode: emacs-lisp; lexical-binding: t; --&#xA;&#xA;(message &#34;Hello: %S&#34; argv)&#xA;(kill-emacs 0)&#xA;&#xA;However, as a reader of this blog pointed out that is still not enough.&#xA;Emacs ignores our custom arguments now, but it will still try to process its own.  This means that we can&#39;t have a --version argument in our script:&#xA;&#xA;$ ./hello.el --version&#xA;GNU Emacs 25.0.50.1&#xA;Copyright (C) 2014 Free Software Foundation, Inc.&#xA;GNU Emacs comes with ABSOLUTELY NO WARRANTY.&#xA;You may redistribute copies of Emacs&#xA;under the terms of the GNU General Public License.&#xA;For more information about these matters, see the file named COPYING.&#xA;&#xA;Emacs printed its own version and exited before our script even saw the --version argument.  We need to use the standard double-dash -- argument to separate Emacs options from arguments, so that our script can unaffectedly process what Emacs now considers mere arguments (see https://stackoverflow.com/a/6807133/355252):&#xA;&#xA;!/bin/sh&#xA;&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; -- &#34;$@&#34; # -- mode: emacs-lisp; lexical-binding: t; --&#xA;&#xA;(message &#34;Hello: %S&#34; argv)&#xA;(kill-emacs 0)&#xA;&#xA;Now we get the --version argument in our script, but also the separator, so we need to remember to drop the first argument:&#xA;&#xA;$ ./hello.el --version&#xA;Hello: (&#34;--&#34; &#34;--version&#34;)&#xA;&#xA;Typically, you’ll process all arguments in a loop, poping each argument as it is processed.  Initially, you need to pop the first argument to remove the argument separator:&#xA;&#xA;!/bin/sh&#xA;&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; -- &#34;$@&#34; # -- mode: emacs-lisp; lexical-binding: t; --&#xA;&#xA;(let ((greeting &#34;Hello %s!&#34;)&#xA;      options-done&#xA;      names)&#xA;  (pop argv)  ; Remove the -- separator&#xA;  (while argv&#xA;    (let ((option (pop argv)))&#xA;      (cond&#xA;       (options-done (push option names))&#xA;       ;; Don&#39;t process options after &#34;--&#34;&#xA;       ((string= option &#34;--&#34;) (setq options-done t))&#xA;       ((string= option &#34;--greeting&#34;)&#xA;        (setq greeting (pop argv)))&#xA;       ;; --greeting=Foo&#xA;       ((string-match &#34;\\`--greeting=\\(\\(?:.\\|\n\\)\\)\\&#39;&#34; option)&#xA;        (setq greeting (match-string 1 option)))&#xA;       ((string-prefix-p &#34;--&#34; option)&#xA;        (message &#34;Unknown option: %s&#34; option)&#xA;        (kill-emacs 1))&#xA;       (t (push option names)))&#xA;&#xA;      (unless (  (length greeting) 0)&#xA;        (message &#34;Missing argument for --greeting!&#34;)&#xA;        (kill-emacs 1))))&#xA;&#xA;  (unless names&#xA;    (message &#34;Missing names!&#34;)&#xA;    (kill-emacs 1))&#xA;&#xA;  (dolist (name (nreverse names))&#xA;    (message greeting name))&#xA;&#xA;  (kill-emacs 0))&#xA;&#xA;Emacs doesn&#39;t interfere with our options and arguments any more:&#xA;&#xA;$ ./hello.el --greeting=&#39;Hello %s&#39; &#39;John Doe&#39; &#39;Donald Duck&#39;&#xA;Hello John Doe&#xA;Hello Donald Duck&#xA;&#xA;[clal]: https://www.gnu.org/software/emacs/manual/htmlnode/elisp/Command002dLine-Arguments.html#index-command002dline002dargs002dleft&#xA;[cla]: https://www.gnu.org/software/emacs/manual/htmlnode/elisp/Command002dLine-Arguments.html#index-command002dline002dargs&#xA;&#xA;Standard output and input &#xA;&#xA;In the earlier examples, we used message to print text in our script. There’s a little issue, though.  We can&#39;t properly redirect the output:&#xA;&#xA;$ ./hello.el &#39;John Doe&#39; &#39;Donald Duck&#39;   /dev/null&#xA;Hello John Doe!&#xA;Hello Donald Duck!&#xA;&#xA;message writes to standard error, but a good script should use standard output.  For this output stream, there&#39;s another, lesser known family of functions: print, prin1, princ and friends.  These functions output “printed representations” of Lisp objects, with varying levels formatting and quoting.&#xA;&#xA;For simple printing, princ is the right candidate, since it prints without any formatting and quoting.  And naturally the unquoted “printed representation” of a string is… the string itself, so we can use this function to print a list of names to standard output:&#xA;&#xA;!/bin/sh&#xA;&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # --emacs-lisp--&#xA;&#xA;(while argv&#xA;  (princ (format &#34;Hello %s!&#34; (pop argv)))&#xA;  (terpri))&#xA;&#xA;(kill-emacs 0)&#xA;&#xA;Unlike message, princ doesn&#39;t take a format string, so we need to call format ourselves.  terpri is a little utility that just prints a&#xA;newline.  The result is as expected, and we can also redirect the output now:&#xA;&#xA;$ ./hello.el &#39;John Doe&#39; &#39;Donald Duck&#39;&#xA;Hello John Doe!&#xA;Hello Donald Duck!&#xA;$ ./hello.el &#39;John Doe&#39; &#39;Donald Duck&#39;   /dev/null&#xA;&#xA;We have covered standard output now, but what about standard input?  There are no obvious input functions in Emacs Lisp, but the minibuffer reads from standard input in batch mode (see https://stackoverflow.com/a/2906967/355252, I’d never&#xA;have figured this out by myself):&#xA;&#xA;!/bin/sh&#xA;&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # --emacs-lisp--&#xA;&#xA;(let (name)&#xA;  (while (and (setq name (ignore-errors (read-from-minibuffer &#34;&#34;)))&#xA;              (  (length name) 0))&#xA;    (princ (format &#34;Hello %s!&#34; name))&#xA;    (terpri)))&#xA;&#xA;(kill-emacs 0)&#xA;&#xA;We read lines from standard input with read-from-minibuffer, until an empty string is read, or an error occurs.  EOF, e.g. C-d signals an error, so we can exit the input with C-d like in other programs.&#xA;&#xA;$ ./hello.el&#xA;John Doe&#xA;Hello John Doe!&#xA;Donald Duck&#xA;Hello Donald Duck!&#xA;&#xA;This has limitations, though.  We can only read whole lines, and don&#39;t have direct access to the underlying TTY.  The former doesn&#39;t really matter, but the latter limits the graphical capabilities of Emacs scripts and rules out all curses-like stuff or any text UI.&#xA;&#xA;Watch out! This also affects password input in Emacs 24 and older: In these versions read-passwd reads from standard input in batch mode and thus exposes the password input on the terminal.  Only as of Emacs 25 read-passwd is safe to use in batch mode.&#xA;&#xA;[print]: https://www.gnu.org/software/emacs/manual/htmlnode/elisp/Output-Functions.html#index-print&#xA;[prin1]: https://www.gnu.org/software/emacs/manual/htmlnode/elisp/Output-Functions.html#index-prin1&#xA;[princ]: https://www.gnu.org/software/emacs/manual/htmlnode/elisp/Output-Functions.html#index-princ&#xA;[format]: https://www.gnu.org/software/emacs/manual/htmlnode/elisp/Formatting-Strings.html#index-format&#xA;[terpri]: https://www.gnu.org/software/emacs/manual/htmlnode/elisp/Output-Functions.html#index-terpri&#xA;&#xA;Debugging&#xA;&#xA;By default, Emacs’ error reporting is pretty terse, in interactive mode as well as in batch mode:  It just prints the error message, without any backtraces. Consider this script, which has a little type error inside:&#xA;&#xA;!/bin/sh&#xA;&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # --emacs-lisp--&#xA;&#xA;(message &#34;%S&#34; (+ (car argv) (cadr argv)))&#xA;(setq argv nil)&#xA;&#xA;The error message isn’t exactly helpful, though:&#xA;&#xA;$ ./hello.el 10 20&#xA;Wrong type argument: number-or-marker-p, &#34;10&#34;&#xA;&#xA;In interactive mode, we debug such errors by simply retrying the command after kbdM-x toggle-debug-on-error/kbd.  Emacs then enters the debugger and creates a backtrace if an error occurs.&#xA;&#xA;In batch mode, we can’t “retry”, though, so we need to enable backtraces right away, by setting debug-on-error:&#xA;&#xA;!/bin/sh&#xA;&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # --emacs-lisp--&#xA;&#xA;(setq debug-on-error t)&#xA;&#xA;(message &#34;%S&#34; (+ (car argv) (cadr argv)))&#xA;&#xA;(setq argv nil)&#xA;&#xA;Now we get stracktraces for any error:&#xA;&#xA;$ ./hello.el 10 20&#xA;Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p &#34;10&#34;)&#xA;  +(&#34;10&#34; &#34;20&#34;)&#xA;  (message &#34;%S&#34; (+ (car argv) (cadr argv)))&#xA;  eval-buffer(#buffer  load* nil &#34;/Users/swiesner/Developer/Sandbox/hello.el&#34; nil t)  ; Reading at buffer position 140&#xA;  load-with-code-conversion(&#34;/Users/swiesner/Developer/Sandbox/hello.el&#34; &#34;/Users/swiesner/Developer/Sandbox/hello.el&#34; nil t)&#xA;  load(&#34;/Users/swiesner/Developer/Sandbox/hello.el&#34; nil t t)&#xA;  command-line-1((&#34;-scriptload&#34; &#34;./hello.el&#34; &#34;10&#34; &#34;20&#34;))&#xA;  command-line()&#xA;  normal-top-level()&#xA;&#xA;[doe]: https://www.gnu.org/software/emacs/manual/htmlnode/elisp/Error-Debugging.html#index-debug002don002derror&#xA;&#xA;Keep your hands clean&#xA;&#xA;As much as we all love Emacs Lisp, it’s not a language that we should use for scripting or independent programs.  Emacs Lisp is not an independent language and runtime environment.  It’s tied to Emacs, and Emacs is an interactive text editor first and foremost.&#xA;&#xA;I wrote this article partly to help you in the rare cases that you need to write non-interactive Emacs Lisp programs, eg, a runner for your test suite, but even more to show how brittle Emacs Lisp is when used outside Emacs.&#xA;&#xA;Don’t get your hands dirty.  Instead, just use any of the plenty of other languages that are available, eg, Python, Ruby or whatever.  If you want a Lisp, use Common Lisp.  Or try Rust for a change.&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://swsnr.writeas.com/tag:emacs" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">emacs</span></a></p>

<p>Emacs isn&#39;t just an editor, it’s an entire Emacs Lisp interpreter and environment.  We can use Emacs Lisp not only to extend and customize our beloved editor, but also to write entire programs and applications.  Nic Ferrier’s <a href="https://github.com/nicferrier/elnode" rel="nofollow">elnode</a> server is the most ambitious Emacs Lisp application of this sort, but we can start at a smaller scale and try to write our shell scripts and tools with Emacs Lisp.</p>



<p>However, it turns out that writing programs in Emacs Lisp is more intricate than it looks at a first glance.  Emacs decades-long history as interactive application have left deep marks in Emacs and Emacs Lisp, which make independent noninteractive scripts difficult.</p>

<h2 id="making-emacs-lisp-scripts-executable" id="making-emacs-lisp-scripts-executable">Making Emacs Lisp scripts executable</h2>

<p>In the early days, we’d muck about with <code>--no-init-file</code>, <code>--batch</code> and <code>--load</code> to enter noninteractive mode an.e.d load a file.  Nowadays Emacs has a convenient <code>--script</code> option to load and evaluate a specific file, but how to make a proper shebang out of it?  The naive approach won&#39;t do:</p>

<pre><code class="language-lisp">#!/usr/bin/emacs --script
(message &#34;Hello world&#34;)
</code></pre>

<p>Emacs is not <code>/bin/sh</code>, and its location varies between different systems. There may even be different Emacs versions at different places.  For instance, on OS X <code>/usr/bin/emacs</code> is an outdated Emacs 22, and the “real” Emacs is typically installed via Homebrew at <code>/usr/local/bin/emacs</code>.</p>

<p>Normally, we&#39;d accommodate these differences with <code>/usr/bin/env</code>:</p>

<pre><code class="language-lisp">#!/usr/bin/env emacs --script
(message &#34;Hello world&#34;)
</code></pre>

<p>But this just raises another portability issue:  Linux doesn’t split arguments in the shebang, and sends <code>emacs --script</code> as a <em>single</em> argument to <code>/usr/bin/env</code>, which doesn’t really do the trick.</p>

<p>To make our script executable in a portable and reliable way, we need to resort to some dirty trickery (see <a href="https://stackoverflow.com/a/6259330/355252" rel="nofollow">https://stackoverflow.com/a/6259330/355252</a>):</p>

<pre><code class="language-bash">#!/bin/sh
&#34;:&#34;; exec emacs --script &#34;$0&#34; &#34;$@&#34; # -*- mode: emacs-lisp; lexical-binding: t; -*-
(message &#34;Hello world&#34;)
</code></pre>

<p>This wraps the Emacs Lisp code into a POSIX shell script which calls out to <code>emacs</code> with appropriate arguments.  The semicolon in the second line hides the <code>exec</code> statement from Emacs, and the no-op colon statement turns this into a proper sequence statement for the shell.  The colon in turn is quoted to make it appear as string literal to Emacs Lisp.</p>

<p>Eventually some file local variables tell Emacs to use Emacs Lisp Mode for the script, regardless of the shebang, and to enable lexical binding.</p>

<p>This particularly evil trick works reliably with any POSIX shell.  Even better, we can now pass arbitrary arguments to the <code>emacs</code> executable, which allows us to get rid of a little nuisance of <code>--script</code>.</p>

<h2 id="inhibiting-site-start" id="inhibiting-site-start">Inhibiting site-start</h2>

<p>The <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Initial-Options.html" rel="nofollow">—script</a> option is just a shortcut for <code>--batch -l</code>, i.e. enter batch mode and load the given file.  Batch Mode mainly means that Emacs will not create a frame, but instead exit after processing all command line arguments (which includes evaluating our script).  Besides, <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Initial-Options.html" rel="nofollow">—batch</a> also disables the user initialization file.  However, it still processes the global site initialization file:</p>

<blockquote><p><code>--batch</code> implies <code>-q</code> (do not load an initialization file), but <code>site-start.el</code> is <em>loaded nonetheless</em>. It also causes Emacs to exit after processing all the command options. In addition, it disables auto-saving except in buffers for which auto-saving is explicitly requested.</p></blockquote>

<p>The global site initialization is often a kitchen sink which sets up globally installed packages and adds many seconds to Emacs’ startup time in the worst case.  Besides, it’s not really a good idea to load arbitrary packages before our script even gets a chance to run.</p>

<p>We can opt out of the global site initialization by adding <code>--quick</code> to the <code>emacs</code> options of our script, which gives us a bare-bones Emacs without any initialization:</p>

<pre><code class="language-lisp">#!/bin/sh
&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # -*- mode: emacs-lisp; lexical-binding: t; -*-
(message &#34;Hello world&#34;)
</code></pre>

<p>If you need to, you can still load the global site initialization <em>explicitly</em> from <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Init-File.html#index-site_002drun_002dfile" rel="nofollow">site-run-file</a>:</p>

<pre><code class="language-lisp">(load site-run-file &#39;no-error &#39;no-message)
</code></pre>

<h2 id="processing-command-line-arguments" id="processing-command-line-arguments">Processing command line arguments</h2>

<p>Emacs exposes the command line arguments in <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Command_002dLine-Arguments.html#index-command_002dline_002dargs_002dleft" rel="nofollow">command-line-args-left</a> alias <code>argv</code> (not to be confused with <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Command_002dLine-Arguments.html#index-command_002dline_002dargs" rel="nofollow">command-line-args</a> which holds <em>all</em> Emacs options, including those that Emacs already interpreted, and is of little use in scripts):</p>

<pre><code class="language-lisp">#!/bin/sh
&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # -*- mode: emacs-lisp; lexical-binding: t; -*-

(message &#34;Hello: %S&#34; argv)
</code></pre>

<pre><code class="language-console">$ ./hello.el &#39;John Doe&#39;
Hello: (&#34;John Doe&#34;)
</code></pre>

<p>Passing options doesn’t work that well, though:</p>

<pre><code class="language-console">$ ./hello.el --greeting &#39;Good morning %s!&#39; &#39;John Doe&#39;
Hello: (&#34;--greeting&#34; &#34;Good morning %s!&#34; &#34;John Doe&#34;)
Unknown option `--greeting&#39;
</code></pre>

<p>Emacs tries to interpret <code>--greeting</code> on its own, and rightfully complains that it has never heard of any such option.  How do we keep Emacs away from our options?</p>

<p>The source code of <code>startup.el</code>, more precisely the function <code>command-line-1</code>, reveals the solution:  Emacs processes all command line arguments <em>immediately</em>, in order of their appearance.  After processing, each argument is <em>removed</em> from
<code>argv</code>, hence the name <code>command-line-args-left</code>.</p>

<p>Since <code>command-line-args-left</code> aka <code>argv</code> is a global variable, we can just remove all remaining arguments from <code>argv</code> before our script exits:</p>

<pre><code class="language-lisp">#!/bin/sh
&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # -*- mode: emacs-lisp; lexical-binding: t; -*-

(message &#34;Hello: %S&#34; argv)
(setq argv nil)
</code></pre>

<pre><code class="language-console">$ ./hello.el --greeting &#39;Good morning %s!&#39; &#39;John Doe&#39;
Hello: (&#34;--greeting&#34; &#34;Good morning %s!&#34; &#34;John Doe&#34;)
</code></pre>

<p>We can also just force Emacs to exit early, which is good style anyway:</p>

<pre><code class="language-lisp">#!/bin/sh
&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # -*- mode: emacs-lisp; lexical-binding: t; -*-

(message &#34;Hello: %S&#34; argv)
(kill-emacs 0)
</code></pre>

<p>However, as a reader of this blog pointed out that is still not enough.
Emacs ignores our custom arguments now, but it will still try to process its own.  This means that we can&#39;t have a <code>--version</code> argument in our script:</p>

<pre><code class="language-console">$ ./hello.el --version
GNU Emacs 25.0.50.1
Copyright (C) 2014 Free Software Foundation, Inc.
GNU Emacs comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of Emacs
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING.
</code></pre>

<p>Emacs printed its own version and exited before our script even saw the <code>--version</code> argument.  We need to use the standard double-dash <code>--</code> argument to separate Emacs options from arguments, so that our script can unaffectedly process what Emacs now considers mere arguments (see <a href="https://stackoverflow.com/a/6807133/355252" rel="nofollow">https://stackoverflow.com/a/6807133/355252</a>):</p>

<pre><code class="language-lisp">#!/bin/sh
&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; -- &#34;$@&#34; # -*- mode: emacs-lisp; lexical-binding: t; -*-

(message &#34;Hello: %S&#34; argv)
(kill-emacs 0)
</code></pre>

<p>Now we get the <code>--version</code> argument in our script, but also the separator, so we need to remember to drop the first argument:</p>

<pre><code class="language-console">$ ./hello.el --version
Hello: (&#34;--&#34; &#34;--version&#34;)
</code></pre>

<p>Typically, you’ll process all arguments in a loop, <code>pop</code>ing each argument as it is processed.  Initially, you need to pop the first argument to remove the argument separator:</p>

<pre><code class="language-lisp">#!/bin/sh
&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; -- &#34;$@&#34; # -*- mode: emacs-lisp; lexical-binding: t; -*-

(let ((greeting &#34;Hello %s!&#34;)
      options-done
      names)
  (pop argv)  ; Remove the -- separator
  (while argv
    (let ((option (pop argv)))
      (cond
       (options-done (push option names))
       ;; Don&#39;t process options after &#34;--&#34;
       ((string= option &#34;--&#34;) (setq options-done t))
       ((string= option &#34;--greeting&#34;)
        (setq greeting (pop argv)))
       ;; --greeting=Foo
       ((string-match &#34;\\`--greeting=\\(\\(?:.\\|\n\\)*\\)\\&#39;&#34; option)
        (setq greeting (match-string 1 option)))
       ((string-prefix-p &#34;--&#34; option)
        (message &#34;Unknown option: %s&#34; option)
        (kill-emacs 1))
       (t (push option names)))

      (unless (&gt; (length greeting) 0)
        (message &#34;Missing argument for --greeting!&#34;)
        (kill-emacs 1))))

  (unless names
    (message &#34;Missing names!&#34;)
    (kill-emacs 1))

  (dolist (name (nreverse names))
    (message greeting name))

  (kill-emacs 0))
</code></pre>

<p>Emacs doesn&#39;t interfere with our options and arguments any more:</p>

<pre><code class="language-console">$ ./hello.el --greeting=&#39;Hello %s&#39; &#39;John Doe&#39; &#39;Donald Duck&#39;
Hello John Doe
Hello Donald Duck
</code></pre>

<h2 id="standard-output-and-input" id="standard-output-and-input">Standard output and input</h2>

<p>In the earlier examples, we used <code>message</code> to print text in our script. There’s a little issue, though.  We can&#39;t properly redirect the output:</p>

<pre><code class="language-console">$ ./hello.el &#39;John Doe&#39; &#39;Donald Duck&#39; &gt; /dev/null
Hello John Doe!
Hello Donald Duck!
</code></pre>

<p><code>message</code> writes to standard <em>error</em>, but a good script should use standard output.  For this output stream, there&#39;s another, lesser known family of functions: <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Output-Functions.html#index-print" rel="nofollow">print</a>, <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Output-Functions.html#index-prin1" rel="nofollow">prin1</a>, <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Output-Functions.html#index-princ" rel="nofollow">princ</a> and friends.  These functions output “printed representations” of Lisp objects, with varying levels formatting and quoting.</p>

<p>For simple printing, <code>princ</code> is the right candidate, since it prints without any formatting and quoting.  And naturally the unquoted “printed representation” of a string is… the string itself, so we can use this function to print a list of names to standard output:</p>

<pre><code class="language-lisp">#!/bin/sh
&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # -*-emacs-lisp-*-

(while argv
  (princ (format &#34;Hello %s!&#34; (pop argv)))
  (terpri))

(kill-emacs 0)
</code></pre>

<p>Unlike <code>message</code>, <code>princ</code> doesn&#39;t take a format string, so we need to call <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Formatting-Strings.html#index-format" rel="nofollow">format</a> ourselves.  <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Output-Functions.html#index-terpri" rel="nofollow">terpri</a> is a little utility that just prints a
newline.  The result is as expected, and we can also redirect the output now:</p>

<pre><code class="language-console">$ ./hello.el &#39;John Doe&#39; &#39;Donald Duck&#39;
Hello John Doe!
Hello Donald Duck!
$ ./hello.el &#39;John Doe&#39; &#39;Donald Duck&#39; &gt;/dev/null
</code></pre>

<p>We have covered standard output now, but what about standard input?  There are no obvious input functions in Emacs Lisp, but the minibuffer reads from standard input in batch mode (see <a href="https://stackoverflow.com/a/2906967/355252" rel="nofollow">https://stackoverflow.com/a/2906967/355252</a>, I’d never
have figured this out by myself):</p>

<pre><code class="language-lisp">#!/bin/sh
&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # -*-emacs-lisp-*-

(let (name)
  (while (and (setq name (ignore-errors (read-from-minibuffer &#34;&#34;)))
              (&gt; (length name) 0))
    (princ (format &#34;Hello %s!&#34; name))
    (terpri)))

(kill-emacs 0)
</code></pre>

<p>We read lines from standard input with <code>read-from-minibuffer</code>, until an empty string is read, or an error occurs.  EOF, e.g. <code>C-d</code> signals an error, so we can exit the input with <code>C-d</code> like in other programs.</p>

<pre><code class="language-console">$ ./hello.el
John Doe
Hello John Doe!
Donald Duck
Hello Donald Duck!
</code></pre>

<p>This has limitations, though.  We can only read whole lines, and don&#39;t have direct access to the underlying TTY.  The former doesn&#39;t really matter, but the latter limits the graphical capabilities of Emacs scripts and rules out all curses-like stuff or any text UI.</p>

<p><strong>Watch out!</strong> This also affects password input in Emacs 24 and older: In these versions <code>read-passwd</code> reads from standard input in batch mode and thus <strong>exposes</strong> the password input on the terminal.  Only as of Emacs 25 <code>read-passwd</code> is safe to use in batch mode.</p>

<h2 id="debugging" id="debugging">Debugging</h2>

<p>By default, Emacs’ error reporting is pretty terse, in interactive mode as well as in batch mode:  It just prints the error message, without any backtraces. Consider this script, which has a little type error inside:</p>

<pre><code class="language-lisp">#!/bin/sh
&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # -*-emacs-lisp-*-

(message &#34;%S&#34; (+ (car argv) (cadr argv)))
(setq argv nil)
</code></pre>

<p>The error message isn’t exactly helpful, though:</p>

<pre><code class="language-console">$ ./hello.el 10 20
Wrong type argument: number-or-marker-p, &#34;10&#34;
</code></pre>

<p>In interactive mode, we debug such errors by simply retrying the command after M-x toggle-debug-on-error.  Emacs then enters the debugger and creates a backtrace if an error occurs.</p>

<p>In batch mode, we can’t “retry”, though, so we need to enable backtraces right away, by setting <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Error-Debugging.html#index-debug_002don_002derror" rel="nofollow">debug-on-error</a>:</p>

<pre><code class="language-lisp">#!/bin/sh
&#34;:&#34;; exec emacs --quick --script &#34;$0&#34; &#34;$@&#34; # -*-emacs-lisp-*-

(setq debug-on-error t)

(message &#34;%S&#34; (+ (car argv) (cadr argv)))

(setq argv nil)
</code></pre>

<p>Now we get stracktraces for any error:</p>

<pre><code class="language-console">$ ./hello.el 10 20
Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p &#34;10&#34;)
  +(&#34;10&#34; &#34;20&#34;)
  (message &#34;%S&#34; (+ (car argv) (cadr argv)))
  eval-buffer(#&lt;buffer  *load*&gt; nil &#34;/Users/swiesner/Developer/Sandbox/hello.el&#34; nil t)  ; Reading at buffer position 140
  load-with-code-conversion(&#34;/Users/swiesner/Developer/Sandbox/hello.el&#34; &#34;/Users/swiesner/Developer/Sandbox/hello.el&#34; nil t)
  load(&#34;/Users/swiesner/Developer/Sandbox/hello.el&#34; nil t t)
  command-line-1((&#34;-scriptload&#34; &#34;./hello.el&#34; &#34;10&#34; &#34;20&#34;))
  command-line()
  normal-top-level()
</code></pre>

<h2 id="keep-your-hands-clean" id="keep-your-hands-clean">Keep your hands clean</h2>

<p>As much as we all love Emacs Lisp, it’s not a language that we should use for scripting or independent programs.  Emacs Lisp is not an independent language and runtime environment.  It’s tied to Emacs, and Emacs is an interactive text editor first and foremost.</p>

<p>I wrote this article partly to help you in the rare cases that you need to write non-interactive Emacs Lisp programs, eg, a runner for your test suite, but even more to show how brittle Emacs Lisp is when used outside Emacs.</p>

<p>Don’t get your hands dirty.  Instead, just use any of the plenty of other languages that are available, eg, Python, Ruby or whatever.  If you want a Lisp, use Common Lisp.  Or try Rust for a change.</p>
]]></content:encoded>
      <guid>https://swsnr.writeas.com/emacs-script-pitfalls</guid>
      <pubDate>Mon, 11 Aug 2014 22:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Autoloads in Emacs Lisp</title>
      <link>https://swsnr.writeas.com/autoloads-in-emacs-lisp?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[emacs &#xA;&#xA;Emacs Lisp offers an autoloading mechanism to load libraries on demand.  Typically this is used to make interactive commands available to the user without entirely loading the corresponding library upfront.  This article explores how autoloads work and how Emacs Lisp packages use autoloads to improve load speed.&#xA;&#xA;[autoload]: https://www.gnu.org/software/emacs/manual/htmlnode/elisp/Autoload.html#Autoload&#xA;&#xA;!--more--&#xA;&#xA;Autoloads&#xA;&#xA;The autoload function creates autoloads, for instance for the function magit-status from Magit:&#xA;&#xA;(autoload &#39;magit-status &#34;magit&#34; &#34;Open a Magit status buffer […]&#34; t nil)&#xA;&#xA;Evaluating this expression tells Emacs to automatically load the library magit.el from load-path, when magit-status is called for the first time—either from Lisp, or interactively with M-x magit-status.  You can manually add autoloads to your init.el yourself to autoload 3rd party libraries.  In the old days before package.el, this was a common pattern.&#xA;&#xA;Note the emphasis on evaluation.  Merely writing this expression somewhere doesn&#39;t create any autoloads.  Emacs must evaluate it, which comes down to Emacs loading a file with this expression.&#xA;&#xA;It doesn&#39;t make any sense to put autoloads into the same file that has the actual definition of the autoloaded function.  Emacs would load the rest of the file as well and thus make the definition available right away, leading the purpose of autoloads ad absurdum.&#xA;&#xA;Autoloads should be in a separate file containing only autoloads and nothing else to make it load fast.  Emacs calls such files &#34;autoload files&#34;.&#xA;&#xA;Autoload cookies&#xA;&#xA;Maintaining autoload files manually to keep them in sync with the actual definitions in the library file is tiresome and error-prone so Emacs allows to automate this process with update-file-autoloads and update-directory-autoloads.&#xA;&#xA;update-file-autoloads inspects the source files for special comments called “autoload cookies”.  These cookies let you declare autoloads right at the corresponding definition.  An autoload cookie for magit-status looks like this:&#xA;&#xA;;;;###autoload&#xA;(defun magit-status ()&#xA;  &#34;Open a Magit status buffer […]&#34;&#xA;  (interactive)&#xA;  ;; …&#xA;)&#xA;&#xA;For each such cookie update-file-autoloads generates a corresponding autoload like the one shown above, and writes it to the autoload file. update-directory-autoloads performs this process for all files in a directory.&#xA;&#xA;These commands only generate autoload files.  You still need to load the generated files explicitly to make their autoloads available.&#xA;&#xA;If an autoload cookie occurs on an expression with no special support for autoloading, update-file-autoloads copies the expression verbatim.  This is used to register libraries in specific Emacs extension points, like auto-modes-alist.&#xA;&#xA;Package autoloads &#xA;&#xA;Emacs&#39; package manager package.el goes a step further and automatically generates autoloads files during package installation—internally it simply calls update-directory-autoloads.  This relieves package maintainers from the tedious work of manually updating autoload files and including them in their packages, and enables autoloads even for single-file packages.&#xA;&#xA;Likewise package-initialize automatically loads autoloads files of all installed packages to make all autoloads available.&#xA;&#xA;What to autoload? &#xA;&#xA;The general rule is to autoload interactive “entry points” of a package. Examples of interactive entry points include:&#xA;&#xA;definitions of major and minor modes,&#xA;interactive commands by which a user would start to use a specific package   (e.g. gnus, erc, magit-status, etc.),&#xA;and interactive commands which offer generic utilities, e.g. occur,   find, ace-jump-mode, etc.&#xA;&#xA;If your package just provides a library for use in Emacs Lisp code (e.g. like dash.el or s.el) you should not add any autoloads at all.  Libraries are typically requiredd by dependent libraries so autoloads would be redundant.&#xA;&#xA;If your package should automatically register itself in specific Emacs extension points you should add autoloads for these as well to make sure that they are evaluated during package initialization.  A typical example is adding a mode to auto-mode-alist:&#xA;&#xA;;;;###autoload&#xA;(add-to-list &#39;auto-mode-alist &#39;(&#34;\\.pp\\&#39;&#34; . puppet-mode))&#xA;&#xA;This puts puppet-mode into auto-mode-alist when Emacs starts, so that  Puppet Mode is automatically used for all files ending in .pp.&#xA;&#xA;Likewise, colour themes use autoload cookies to add themselves to the color theme search path:&#xA;&#xA;;;;###autoload&#xA;(when (and (boundp &#39;custom-theme-load-path) load-file-name)&#xA;  (add-to-list &#39;custom-theme-load-path&#xA;               (file-name-as-directory (file-name-directory load-file-name))))&#xA;&#xA;Emacs Lisp API for autoloads&#xA;&#xA;Emacs Lisp has some functions to work with autoloads.  In addition to autoload to create autoloads, there are autoloadp and autoload-do-load.  The first lets you check whether an object is an autoload object, and the latter loads the underlying library of an autoload.&#xA;&#xA;Both functions work on autoload objects, and not on symbols with attached autoloads.  Hence, (autoloadp &#39;foo) checks whether the symbol foo is autoloaded, which it isn&#39;t.  Symbols are not loaded at all, they are either directly created by the reader, or explicitly with intern.&#xA;&#xA;To check whether foo refers to an autoloaded function you need to check the function definition of foo:&#xA;&#xA;(autoloadp (function-definition &#39;foo))&#xA;&#xA;[al]: https://www.gnu.org/software/emacs/manual/htmlnode/elisp/Autoload.html#index-autoload-1&#xA;[alp]: https://www.gnu.org/software/emacs/manual/htmlnode/elisp/Autoload.html#index-autoloadp&#xA;[adl]: https://www.gnu.org/software/emacs/manual/htmlnode/elisp/Autoload.html#index-autoload002ddo002dload&#xA;[intern]: https://www.gnu.org/software/emacs/manual/html_node/elisp/Creating-Symbols.html#index-intern&#xA;&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://swsnr.writeas.com/tag:emacs" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">emacs</span></a></p>

<p>Emacs Lisp offers an <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Autoload.html#Autoload" rel="nofollow">autoloading mechanism</a> to load libraries on demand.  Typically this is used to make interactive commands available to the user without entirely loading the corresponding library upfront.  This article explores how autoloads work and how Emacs Lisp packages use autoloads to improve load speed.</p>



<h2 id="autoloads" id="autoloads">Autoloads</h2>

<p>The <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Autoload.html#index-autoload-1" rel="nofollow">autoload</a> function creates autoloads, for instance for the function <code>magit-status</code> from Magit:</p>

<pre><code class="language-lisp">(autoload &#39;magit-status &#34;magit&#34; &#34;Open a Magit status buffer […]&#34; t nil)
</code></pre>

<p><em>Evaluating</em> this expression tells Emacs to automatically load the library <code>magit.el</code> from <code>load-path</code>, when <code>magit-status</code> is called for the first time—either from Lisp, or interactively with <code>M-x magit-status</code>.  You can manually add autoloads to your <code>init.el</code> yourself to autoload 3rd party libraries.  In the old days before package.el, this was a common pattern.</p>

<p>Note the emphasis on <em>evaluation</em>.  Merely writing this expression somewhere doesn&#39;t create any autoloads.  Emacs must evaluate it, which comes down to Emacs loading a file with this expression.</p>

<p>It doesn&#39;t make any sense to put autoloads into the same file that has the actual definition of the autoloaded function.  Emacs would load the rest of the file as well and thus make the definition available right away, leading the purpose of autoloads ad absurdum.</p>

<p>Autoloads should be in a separate file containing only autoloads and nothing else to make it load fast.  Emacs calls such files “autoload files”.</p>

<h2 id="autoload-cookies" id="autoload-cookies">Autoload cookies</h2>

<p>Maintaining autoload files manually to keep them in sync with the actual definitions in the library file is tiresome and error-prone so Emacs allows to automate this process with <code>update-file-autoloads</code> and <code>update-directory-autoloads</code>.</p>

<p><code>update-file-autoloads</code> inspects the source files for special comments called “autoload cookies”.  These cookies let you declare autoloads right at the corresponding definition.  An autoload cookie for <code>magit-status</code> looks like this:</p>

<pre><code class="language-lisp">;;;###autoload
(defun magit-status ()
  &#34;Open a Magit status buffer […]&#34;
  (interactive)
  ;; …
)
</code></pre>

<p>For each such cookie <code>update-file-autoloads</code> generates a corresponding <code>autoload</code> like the one shown above, and writes it to the autoload file. <code>update-directory-autoloads</code> performs this process for all files in a directory.</p>

<p>These commands only <em>generate</em> autoload files.  You still need to load the generated files explicitly to make their autoloads available.</p>

<p>If an autoload cookie occurs on an expression with no special support for autoloading, <code>update-file-autoloads</code> copies the expression verbatim.  This is used to register libraries in specific Emacs extension points, like <code>auto-modes-alist</code>.</p>

<h2 id="package-autoloads" id="package-autoloads">Package autoloads</h2>

<p>Emacs&#39; package manager <code>package.el</code> goes a step further and automatically generates autoloads files during package installation—internally it simply calls <code>update-directory-autoloads</code>.  This relieves package maintainers from the tedious work of manually updating autoload files and including them in their packages, and enables autoloads even for single-file packages.</p>

<p>Likewise <code>package-initialize</code> automatically loads autoloads files of all installed packages to make all autoloads available.</p>

<h2 id="what-to-autoload" id="what-to-autoload">What to autoload?</h2>

<p>The general rule is to autoload <em>interactive “entry points”</em> of a package. Examples of interactive entry points include:</p>
<ul><li>definitions of major and minor modes,</li>
<li>interactive commands by which a user would start to use a specific package   (e.g. <code>gnus</code>, <code>erc</code>, <code>magit-status</code>, etc.),</li>
<li>and interactive commands which offer generic utilities, e.g. <code>occur</code>,   <code>find</code>, <code>ace-jump-mode</code>, etc.</li></ul>

<p>If your package just provides a library for use in Emacs Lisp code (e.g. like dash.el or s.el) you should <em>not</em> add any autoloads at all.  Libraries are typically <code>required</code>d by dependent libraries so autoloads would be redundant.</p>

<p>If your package should automatically register itself in specific Emacs extension points you should add autoloads for these as well to make sure that they are evaluated during package initialization.  A typical example is adding a mode to <code>auto-mode-alist</code>:</p>

<pre><code class="language-lisp">;;;###autoload
(add-to-list &#39;auto-mode-alist &#39;(&#34;\\.pp\\&#39;&#34; . puppet-mode))
</code></pre>

<p>This puts <code>puppet-mode</code> into <code>auto-mode-alist</code> when Emacs starts, so that  Puppet Mode is automatically used for all files ending in <code>.pp</code>.</p>

<p>Likewise, colour themes use autoload cookies to add themselves to the color theme search path:</p>

<pre><code class="language-lisp">;;;###autoload
(when (and (boundp &#39;custom-theme-load-path) load-file-name)
  (add-to-list &#39;custom-theme-load-path
               (file-name-as-directory (file-name-directory load-file-name))))
</code></pre>

<h2 id="emacs-lisp-api-for-autoloads" id="emacs-lisp-api-for-autoloads">Emacs Lisp API for autoloads</h2>

<p>Emacs Lisp has some functions to work with autoloads.  In addition to <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Autoload.html#index-autoload-1" rel="nofollow">autoload</a> to create autoloads, there are <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Autoload.html#index-autoloadp" rel="nofollow">autoloadp</a> and <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Autoload.html#index-autoload_002ddo_002dload" rel="nofollow">autoload-do-load</a>.  The first lets you check whether an object is an autoload object, and the latter loads the underlying library of an autoload.</p>

<p>Both functions work on <em>autoload objects</em>, and <em>not</em> on symbols with attached autoloads.  Hence, <code>(autoloadp &#39;foo)</code> checks whether the symbol <code>foo</code> is autoloaded, which it isn&#39;t.  Symbols are not loaded at all, they are either directly created by the reader, or explicitly with <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Creating-Symbols.html#index-intern" rel="nofollow">intern</a>.</p>

<p>To check whether <code>foo</code> refers to an autoloaded function you need to check the <em>function definition</em> of <code>foo</code>:</p>

<pre><code class="language-lisp">(autoloadp (function-definition &#39;foo))
</code></pre>
]]></content:encoded>
      <guid>https://swsnr.writeas.com/autoloads-in-emacs-lisp</guid>
      <pubDate>Tue, 01 Jul 2014 22:00:00 +0000</pubDate>
    </item>
  </channel>
</rss>