<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Elsa Gonsiorowski</title>
        <description>My Personal Website</description>
        <link>http://gonsie.com/</link>
        <atom:link href="http://gonsie.com/blorg/feeds/orgmode.xml" rel="self" type="application/rss+xml"/>
        <pubDate>Tue, 19 May 2026 17:45:38 +0000</pubDate>
        <lastBuildDate>Tue, 19 May 2026 17:45:38 +0000</lastBuildDate>
        <generator>Jekyll v3.10.0</generator>
        
        
            <item>
                <title>Emacs Carnival: Org Mode Completions</title>
                <author>gonsie@me.com (Elsa Gonsiorowski)</author>
                <description>&lt;p&gt;I’m so happy to be joining &lt;a href=&quot;https://sachachua.com/blog/2026/01/emacs-carnival-february-2026-completion/&quot;&gt;this month’s emacs carnival&lt;/a&gt;!
I love the idea behind these carnivals and I think it’s such a good way of building community virtually.&lt;/p&gt;

&lt;p&gt;This month’s topic is Emacs completions.
I’m going to share a sort of “hack”… a way that I’ve been able to achieve completions within core org mode.&lt;/p&gt;

&lt;h2 id=&quot;org-mode-tempo-templates&quot;&gt;Org Mode Tempo Templates&lt;/h2&gt;

&lt;p&gt;Org Mode has long supported a template expansion mechanism, some times called “easy templates” or “structured templates”.
The default behavior changed dramatically in &lt;a href=&quot;https://orgmode.org/worg/org-release-notes.html#orgf815049&quot;&gt;version 9.2&lt;/a&gt;, and is now built on top of the Emacs builtin &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tempo.el&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update&lt;/em&gt; To get the behavior described here, you must add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(require &apos;org-tempo)&lt;/code&gt; to your config.&lt;/p&gt;

&lt;p&gt;Essentially, you start a new line with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;X&lt;/code&gt; (where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X&lt;/code&gt; is a pre-defined key), then hit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TAB&lt;/code&gt; to have the template expanded.
For example, starting a new line with:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-org&quot; data-lang=&quot;org&quot;&gt;&amp;lt;s&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;and hitting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TAB&lt;/code&gt; will expand to:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-nil&quot; data-lang=&quot;nil&quot;&gt;#+begin_src

#+end_src&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Super handy and very easy to remember.&lt;/p&gt;

&lt;h3 id=&quot;default-templates&quot;&gt;Default templates&lt;/h3&gt;

&lt;p&gt;The default are not entirely documented, though most are listed on the &lt;a href=&quot;https://orgmode.org/manual/Structure-Templates.html&quot;&gt;Structured Templates manual page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Listed again here for convenience:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Key&lt;/th&gt;
      &lt;th&gt;Expansion&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;a&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+BEGIN_EXPORT ascii … #+END_EXPORT&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;c&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+BEGIN_CENTER … #+END_CENTER&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;C&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+BEGIN_COMMENT … #+END_COMMENT&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;e&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+BEGIN_EXAMPLE … #+END_EXAMPLE&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;E&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+BEGIN_EXPORT … #+END_EXPORT&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;h&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+BEGIN_EXPORT html … #+END_EXPORT&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;l&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+BEGIN_EXPORT latex … #+END_EXPORT&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;q&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+BEGIN_QUOTE … #+END_QUOTE&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;s&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+BEGIN_SRC … #+END_SRC&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;v&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+BEGIN_VERSE … #+END_VERSE&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;In addition to those blocks, there are also some quick tags:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Key&lt;/th&gt;
      &lt;th&gt;Expansion&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;L&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+latex:&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;H&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+html:&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;A&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+ascii:&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;i&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+index:&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;I&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+include:&lt;/code&gt; (will interactively find file to include)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;You can see that there is sort of a convention, uppercase letters usually insert a tag, whereas lowercase letters are mainly for blocks (though it’s definitely not perfect).&lt;/p&gt;

&lt;h3 id=&quot;additional-templates&quot;&gt;Additional Templates&lt;/h3&gt;

&lt;p&gt;Some additional templates can be defined by packages.
For example, the &lt;a href=&quot;https://gitlab.com/oer/org-re-reveal&quot;&gt;org-re-reveal&lt;/a&gt; package adds:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Key&lt;/th&gt;
      &lt;th&gt;Expansion&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;n&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+begin_notes ... #+end_notes&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;basic-customization&quot;&gt;Basic Customization&lt;/h2&gt;

&lt;p&gt;You can add your own tags and blocks.
In fact, there is actually no need for the “keys” to single characters.&lt;/p&gt;

&lt;h3 id=&quot;adding-tags&quot;&gt;Adding Tags&lt;/h3&gt;

&lt;p&gt;Adding another tag is very easy, seen here:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;org-tempo-keywords-alist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;N&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Which results in this completion:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Key&lt;/th&gt;
      &lt;th&gt;Expansion&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;N&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#+name:&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;create-a-new-hotkey&quot;&gt;Create a New Hotkey&lt;/h3&gt;

&lt;p&gt;I don’t like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;E&lt;/code&gt; hotkey for export block, instead I would like that to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;x&lt;/code&gt;.
That is easily added with:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;org-tempo-tags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;x&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tempo-template-org-export&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;create-a-completion&quot;&gt;Create a Completion&lt;/h3&gt;

&lt;p&gt;You can define your own completion with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tempo-define-template&lt;/code&gt; function (see the doc string for full details).
It is very flexible!
You can specify where the cursor (or “prompt”) ends up after the completion, or you can interactively prompt (via the minibuffer) for additional details.
There are more advance features, including auto indentation and dealing with regions.&lt;/p&gt;

&lt;h2 id=&quot;my-custom-completions&quot;&gt;My Custom Completions&lt;/h2&gt;

&lt;p&gt;There is no requirement that these templates be simply blocks or tags.
I’ve implemented about 5 custom templates, but here are a few that I think would be most useful for others.&lt;/p&gt;

&lt;h3 id=&quot;properties-drawer1&quot;&gt;Properties Drawer&lt;sup&gt;&lt;a id=&quot;fnr.1&quot; class=&quot;footref&quot; href=&quot;#fn.1&quot; role=&quot;doc-backlink&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;

&lt;p&gt;Org headings can have properties, specified by the &lt;a href=&quot;https://orgmode.org/manual/Property-Syntax.html&quot;&gt;properties drawer&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-org&quot; data-lang=&quot;org&quot;&gt;:PROPERTIES:

:END:&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I add this as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;p&lt;/code&gt; via this implementation code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tempo-define-template&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;org-properties-block&quot;&lt;/span&gt;
                       &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;:PROPERTIES:&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;
                         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;
                         &lt;span class=&quot;s&quot;&gt;&quot;:END:&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;org-tempo-tags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;p&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tempo-template-org-properties-block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;title-block&quot;&gt;Title Block&lt;/h3&gt;

&lt;p&gt;This is one that I use most frequently.
It’s a title block that I start all my org documents with.
It also executes a function call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;format-time-string&lt;/code&gt; to get today’s date in my preferred format.
By having this completion, all of my org documents get a title with a date and I always know when I started working on a document!&lt;/p&gt;

&lt;p&gt;My desired result:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-org&quot; data-lang=&quot;org&quot;&gt;#+title:
#+author: Elsa Gonsiorowski
#+date: February 28, 2026&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The implementation code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tempo-define-template&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;org-title-block&quot;&lt;/span&gt;
                       &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#+title: &quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;
                         &lt;span class=&quot;s&quot;&gt;&quot;#+author: Elsa Gonsiorowski&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;
                         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;#+date: &quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;format-time-string&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;%B %e, %Y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;org-tempo-tags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;t&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tempo-template-org-title-block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I also implement another completion that is a slightly different title block which I use for starting all my blog posts.
It includes the all the options that I want by default.&lt;/p&gt;

&lt;h2 id=&quot;finally&quot;&gt;Finally&lt;/h2&gt;

&lt;p&gt;In writing this article I stumbled across orgmode documentation page for &lt;a href=&quot;https://orgmode.org/manual/Completion.html&quot;&gt;Completions&lt;/a&gt;.
I had no idea these &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-tab&lt;/code&gt; completions existed!
(Clearly, since I implemented my own completion for the properties drawer).
I’ll definitely be trying these out.&lt;/p&gt;

&lt;h1 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h1&gt;

&lt;p&gt;&lt;sup&gt;&lt;a id=&quot;fn.1&quot; href=&quot;#fnr.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:properties:&lt;/code&gt; keyword can also be added with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-tab&lt;/code&gt; completion on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt;&lt;/p&gt;
</description>
                <pubDate>Sat, 28 Feb 2026 00:00:00 +0000</pubDate>
                <link>http://gonsie.com/blorg/org-completion-feb26-carnival.html</link>
                <guid isPermaLink="true">http://gonsie.com/blorg/org-completion-feb26-carnival.html</guid>
                
                <category>emacs</category>
                
                <category>orgmode</category>
                
                
            </item>
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
            <item>
                <title>Sending Email from Org Mode</title>
                <author>gonsie@me.com (Elsa Gonsiorowski)</author>
                <description>&lt;p&gt;Every so often, I need to generate a bunch of form emails.
Often, I’m sending the same email to multiple groups of people and I want use variables, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$first_name&lt;/code&gt;, in the text.
While I’m sure there a number of online services which could achieve this for me, I really don’t need to set up a fancy campaign or use tracking.
Plus, I’m wary of submitting others’ emails to a third party.&lt;/p&gt;

&lt;p&gt;Of course, I’ve used Emacs to do this, using org mode and AppleScript.&lt;/p&gt;

&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;

&lt;p&gt;To approach this task I start with a single org file.
Getting AppleScript executing from an org block is trickier than I would like.
Instead, I write the script whole cloth in my org file and tangle it out to a separate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.scpt&lt;/code&gt; file.
I store the data in my file as a table.
I then use a bash block, which takes the data through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:var&lt;/code&gt;, to loop over running the script.&lt;/p&gt;

&lt;h2 id=&quot;applescript-for-email&quot;&gt;AppleScript for Email&lt;/h2&gt;

&lt;p&gt;I’ve never formally learned AppleScript, but some searching on StackOverFlow and trial-and-error can get you pretty far.
Mac OS X has a built in editor found in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Applications/Utilities/Script Editor&lt;/code&gt;.
Once you’ve opened the editor, you can browse the dictionary with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File &amp;gt; Open Dictionary...&lt;/code&gt;.
This dictionary lists all the classes and commands for different applications.
The AppleScript language itself looks like natural language and is relatively easy to understand… especially once someone else has properly constructed the program.&lt;/p&gt;

&lt;p&gt;For my email-sender script, I store the AppleScript source is as a block.
This block is tangled (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-c C-v C-t&lt;/code&gt;) to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.scpt&lt;/code&gt; file.
The first half of this script sets some variables, including the body of the email message.
The second half creates the message and sets a “to” recipient (could also set a “cc” recipient).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-applescript&quot; data-lang=&quot;applescript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#+NAME: script&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;#+BEGIN_SRC apples :tangle email.scpt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;varName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;varEmail&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;varBody&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Hello &quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;varName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;,

Blah blah blah. Lor ipsum, etc.

Sincerely,
Elsa&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

   &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tell&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Mail&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;theMessage&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;outgoing&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Email&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;varBody&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;visible&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tell&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;theMessage&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
             &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;recipient&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;varName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;varEmail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
             &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;#send&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tell&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tell&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;#+END_SRC&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note that I’ve commented out the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;send&lt;/code&gt; command and set the message property &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;visible: true&lt;/code&gt;.
This means that the draft emails appear in the Mail GUI, but do not get automatically sent.
This allows me to do trial runs before spamming my recipients.&lt;/p&gt;

&lt;h2 id=&quot;filling-the-variables&quot;&gt;Filling the Variables&lt;/h2&gt;

&lt;p&gt;Once I have the script and email body written, I know what variables I’ll need to fill in.
The next step is to put all the data into a named org table.
I usually do this data formatting by hand since I’m bringing together data items from many different sources.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-nil&quot; data-lang=&quot;nil&quot;&gt;#+NAME: data
|    Name    |      Email      |
|------------|-----------------|
| Mx. Person | person@test.com |&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Since I tangle the email sending AppleScript program, I need to run it from the command line.
I call the script once for each row in the data table using a bash loop and variable arrays.
Then, I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-c C-c&lt;/code&gt; to run the bash loop and generate the emails.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#+BEGIN_SRC bash :var name=data[,0] email=data[,1]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;i &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;0 0&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
&lt;/span&gt;osascript email.scpt &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#+END_SRC&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note that I do not calculate the total number of data items / rows.
That would take way too much bash magic for this simple example.
Also, if you want to test the variables with an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo&lt;/code&gt; statement, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:results output&lt;/code&gt; as an argument to the org block.&lt;/p&gt;

&lt;h2 id=&quot;hitting-send&quot;&gt;Hitting Send&lt;/h2&gt;

&lt;p&gt;I usually choose to manually hit send on each individual email once I’m satisfied with the script.&lt;/p&gt;

&lt;p&gt;I keep all of these org commands in a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;notes.org&lt;/code&gt; file so that I can remember how to recreate the emails (usually a year later when it’s time to send them again).
For example, this &lt;a href=&quot;https://github.com/womeninhpc/mentoring/blob/master/notes.org&quot;&gt;notes.org&lt;/a&gt; file sends introduction emails for a mentoring program I organized with Women in HPC.&lt;/p&gt;
</description>
                <pubDate>Wed, 01 May 2019 00:00:00 +0000</pubDate>
                <link>http://gonsie.com/blorg/emailer.html</link>
                <guid isPermaLink="true">http://gonsie.com/blorg/emailer.html</guid>
                
                <category>emacs</category>
                
                <category>orgmode</category>
                
                <category>mac</category>
                
                <category>applescript</category>
                
                <category>email</category>
                
                
            </item>
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    </channel>
</rss>
