<?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> <channel> <title>notes - sodaware.sdf.org</title> <description></description> <copyright><![CDATA[]]></copyright> <lastBuildDate>Sat, 28 Feb 2026 09:27:19 -0500</lastBuildDate> <pubDate>Sat, 28 Feb 2026 09:27:19 -0500</pubDate> <link>http://sodaware.sdf.org/notes/</link> <atom:link href="http://sodaware.sdf.org/notes.xml" rel="self" type="application/rss+xml"/> <generator>Jekyll 3.8.5</generator> <item> <title>Escaping double curly braces in Jekyll</title> <pubDate>Fri, 27 Feb 2026 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/escaping-double-curly-braces-in-jekyll/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/escaping-double-curly-braces-in-jekyll/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I wrote a note about using the <code class="highlighter-rouge">absolute_url</code> filter in Jekyll and it kept evaluating the markdown code.</p> <p>To prevent this, you can place the liquid markup inside <code class="highlighter-rouge">raw</code> and <code class="highlighter-rouge">endraw</code> tags:</p> <p>{% raw %} {{ liquid_goes_here }} {% endraw %}.</p> ]]></description> </item> <item> <title>Getting absolute url's in Jekyll</title> <pubDate>Fri, 27 Feb 2026 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/absolute-urls-with-jekyll/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/absolute-urls-with-jekyll/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I wanted to add the canonical url to the site template, but using <code class="highlighter-rouge">page.url</code> only inserts the relative url.</p> <p>You can use the <code class="highlighter-rouge">absolute_url</code> filter to fix that: <code class="highlighter-rouge">{{ page.url | absolute_url }}</code></p> ]]></description> </item> <item> <title>Inserting a table of contents into Jekyll posts</title> <pubDate>Wed, 26 Apr 2023 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/jekyll-table-of-contents/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/jekyll-table-of-contents/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I recently wanted to add a table of contents to a post in Jekyll, but I didn’t really want to create it by hand. Thankfully there is a way to insert a dynamic table of contents into a post:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>* Table of Contents
{:toc}
</code></pre></div></div> <p>The line that starts with <code class="highlighter-rouge">*</code> is required but will not be displayed. The above markup will generate a table of contents that links to each header within the post.</p> <p>You can <a href="/blog/blitzmax-plugin-system-win32/">see an example here</a>.</p> ]]></description> </item> <item> <title>Saving a file under a different name in Emacs</title> <pubDate>Tue, 18 Oct 2022 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/emacs-save-as/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/emacs-save-as/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>The Emacs command <code class="highlighter-rouge">write-file</code> will prompt for a filename before saving the current buffer. Default keybinding is <kbd>C-x C-w</kbd>.</p> <p>This is usually called “Save As” in other editors.</p> ]]></description> </item> <item> <title>Getting Ubuntu's version from the command line</title> <pubDate>Sat, 16 Oct 2021 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/ubuntu-version-cli/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/ubuntu-version-cli/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I often forget which version of Ubuntu I’m running.</p> <p>Running <code class="highlighter-rouge">lsb_release -a</code> will show the version along with some other information. It looks like this:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 18.04.6 LTS
Release:	18.04
Codename:	bionic
</code></pre></div></div> ]]></description> </item> <item> <title>Reopening the last closed tab in Firefox</title> <pubDate>Sat, 16 Oct 2021 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/reopen-closed-tabs-firefox/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/reopen-closed-tabs-firefox/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I’m clumsy and sometimes I close the wrong browser tab.</p> <p><kbd>CTRL</kbd> + <kbd>SHIFT</kbd> + <kbd>T</kbd> will reopen the last tab that was closed. Subsequent uses will open the next closed tab in the stack.</p> ]]></description> </item> <item> <title>Upvoting all comments in a reddit thread with JavaScript</title> <pubDate>Fri, 13 Aug 2021 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/upvoting-all-comments/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/upvoting-all-comments/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>This little snippet will upvote all comments in a Reddit thread that you haven’t already upvoted. There’s a small timeout to prevent flooding.</p> <p>You probably shouldn’t do this.</p> <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="kd">function</span> <span class="nx">w</span><span class="p">(){</span><span class="kd">var</span> <span class="nx">u</span><span class="o">=</span><span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">.unvoted.up.arrow</span><span class="dl">"</span><span class="p">);</span><span class="k">if</span><span class="p">(</span><span class="nx">u</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">1</span><span class="p">){</span><span class="nx">setTimeout</span><span class="p">(</span><span class="nx">w</span><span class="p">,</span><span class="mi">500</span><span class="p">);</span><span class="nx">u</span><span class="p">.</span><span class="nx">trigger</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">)()}})()</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Changing the start day of weeks in the Emacs calendar</title> <pubDate>Sat, 10 Jul 2021 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/emacs-calendar-start/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/emacs-calendar-start/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I wanted my calendar to start weeks on a Monday instead of a Sunday. Thankfully it’s nice and easy:</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">calendar-week-start-day</span> <span class="mi">1</span><span class="p">)</span>
</code></pre></div></div> <p>Setting the value to <code class="highlighter-rouge">0</code> will start the week on Sunday.</p> ]]></description> </item> <item> <title>Configuring headline levels in org-mode HTML export</title> <pubDate>Tue, 25 May 2021 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/org-headline-export/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/org-headline-export/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>When org-mode exports content to HTML it converts headlines to <code class="highlighter-rouge">&lt;hN&gt;</code> tags. The default headline level is 3; any headline after that will be wrapped in a <code class="highlighter-rouge">&lt;li&gt;</code> tag instead.</p> <p>Altering <code class="highlighter-rouge">org-export-headline-levels</code> will change this behaviour.</p> <p>Adding the following to your init.el will wrap <code class="highlighter-rouge">level 4</code> in a <code class="highlighter-rouge">&lt;h5&gt;</code> tag:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(setq org-export-headline-levels 4)
</code></pre></div></div> <p>Alternatively this can be done on a per-file basis using <code class="highlighter-rouge">#+OPTIONS</code> somewhere in the org file. The same headline export settings as above would look like this:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#+OPTIONS: H:4

* level 1
** level 2
*** level 3
**** level 4
</code></pre></div></div> <p>The org-mode manual has more information on <a href="https://orgmode.org/manual/Export-Settings.html">org-mode export settings</a>.</p> ]]></description> </item> <item> <title>Excluding a list of words from a grep search</title> <pubDate>Sat, 27 Feb 2021 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/grep-exclude-word-list/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/grep-exclude-word-list/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><code class="highlighter-rouge">grep</code> can search for lines that <strong>don’t</strong> include word with the <code class="highlighter-rouge">-v</code> flag. We can use <code class="highlighter-rouge">-e</code> to search for multiple words, but this can be a pain when there’s a lot to search for.</p> <p>The <code class="highlighter-rouge">-f</code> flag allows us to specify a file that contains a list of words/phrases to search for (one on each line) which makes it much easier to read.</p> <p>For example:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">grep</span> <span class="nt">-v</span> <span class="nt">-e</span> <span class="s2">"phrase one"</span> <span class="nt">-e</span> <span class="s2">"phrase two"</span> <span class="nt">-e</span> <span class="s2">"phrase three"</span> &lt;filename&gt;
</code></pre></div></div> <p>Can be rewritten as follows:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">grep</span> <span class="nt">-v</span> <span class="nt">-f</span> words.txt &lt;filename&gt;
</code></pre></div></div> <p>where <code class="highlighter-rouge">words.txt</code> looks like:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>phrase one
phrase two
phrase three
</code></pre></div></div> <p>Removing the <code class="highlighter-rouge">-v</code> flag would search for only the words in the file.</p> ]]></description> </item> <item> <title>Getting the current git branch name in a Makefile</title> <pubDate>Fri, 26 Feb 2021 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/git-branch-in-makefile/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/git-branch-in-makefile/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I wanted to automate a build step that used the current git branch name. Here’s how to get it from within a <code class="highlighter-rouge">Makefile</code>:</p> <div class="language-makefile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">BRANCH</span> <span class="o">:=</span> <span class="nf">$(</span><span class="nb">shell</span> git rev-parse <span class="nt">--abbrev-ref</span> HEAD<span class="nf">)</span>
</code></pre></div></div> <p><code class="highlighter-rouge">BRANCH</code> will then contain the branch name and can be used like a normal <code class="highlighter-rouge">Makefile</code> variable.</p> ]]></description> </item> <item> <title>Hiding Emacs interface elements</title> <pubDate>Tue, 05 Jan 2021 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/emacs-tidy/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/emacs-tidy/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I like to see as many lines as possible, so I hide the bits of Emacs that I don’t use.</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Turn off menu bar, tool bar, and scroll bar.</span>
<span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">fboundp</span> <span class="ss">'menu-bar-mode</span><span class="p">)</span>   <span class="p">(</span><span class="nv">menu-bar-mode</span>   <span class="mi">-1</span><span class="p">))</span>
<span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">fboundp</span> <span class="ss">'tool-bar-mode</span><span class="p">)</span>   <span class="p">(</span><span class="nv">tool-bar-mode</span>   <span class="mi">-1</span><span class="p">))</span>
<span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">fboundp</span> <span class="ss">'scroll-bar-mode</span><span class="p">)</span> <span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">))</span>

<span class="c1">;; Turn off the splash screen.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span><span class="p">)</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Recompiling all Emacs packages</title> <pubDate>Sun, 27 Dec 2020 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/recompiling-all-emacs-packages/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/recompiling-all-emacs-packages/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>To re-compile all packages installed from Melpa/Elpa, use <code class="highlighter-rouge">byte-recompile-directory</code>. This can be called via <code class="highlighter-rouge">M-:</code>:</p> <p><code class="highlighter-rouge">M-: (byte-recompile-directory package-user-dir nil 'force)</code></p> <p>Emacs will need to be restarted for the compiled changes to load.</p> ]]></description> </item> <item> <title>Adding a homepage to Zetteldeft</title> <pubDate>Tue, 14 Jul 2020 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/zetteldeft-home/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/zetteldeft-home/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><strong>Note:</strong> This behaviour is now part of zetteldeft.</p> <p>This is a really simple tweak to add a homepage file to <a href="https://github.com/EFLS/zetteldeft">zetteldeft</a>. Although I usually use the main search page, adding a homepage makes zetteldeft act more like a wiki.</p> <p>Once this code is added to the Emacs init, running <code class="highlighter-rouge">C-c z h</code> will open the home file. The <code class="highlighter-rouge">home.org</code> file can be any file in your deft notes directory. It should be the local filename within the deft directory, not the full path.</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/zd-homepage</span> <span class="p">()</span>
  <span class="s">"Open Zetteldeft home file."</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">zetteldeft-find-file</span> <span class="s">"home.org"</span><span class="p">))</span>
<span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-c z h"</span><span class="p">)</span> <span class="nf">#'</span><span class="nv">sodaware/zd-homepage</span><span class="p">)</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Temporary org-agendas</title> <pubDate>Tue, 30 Jun 2020 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/temporary-org-agendas/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/temporary-org-agendas/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>This is a really simple way to run org-agenda commands on just a single file:</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/agenda-for-my-file</span> <span class="p">()</span>
  <span class="s">"Run org-agenda on a single file."</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">org-agenda-files</span> <span class="o">'</span><span class="p">(</span><span class="s">"/full/path/to/my.org"</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">org-agenda</span><span class="p">)))</span>
</code></pre></div></div> <p>The following version also creates an agenda for a single file, but prompts for the file name first:</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/agenda-for-single-file</span> <span class="p">(</span><span class="nv">file</span><span class="p">)</span>
  <span class="s">"Run org-agenda on FILE."</span>
  <span class="p">(</span><span class="nv">interactive</span> <span class="s">"FEnter a file name: "</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">org-agenda-files</span> <span class="p">(</span><span class="nb">list</span> <span class="nv">file</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">org-agenda</span><span class="p">)))</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Automatic Emacs theme switching in OSX dark mode</title> <pubDate>Sat, 27 Jun 2020 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/emacs-darkmode-theme-switch/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/emacs-darkmode-theme-switch/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>The following snippet of code will automatically switch between themes if OSX is using light or dark mode.</p> <p>Call using <code class="highlighter-rouge">M-x match-emacs-theme-to-system</code>. Replace <code class="highlighter-rouge">'dark-theme</code> and <code class="highlighter-rouge">'light-theme</code> with appropriate theme names.</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">match-emacs-theme-to-system</span> <span class="p">()</span>
  <span class="s">"Automatically set the theme to match if OSX is in dark mode."</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>

  <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nv">system-dark-mode-enabled-p</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'dark-theme</span>  <span class="no">t</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'light-theme</span> <span class="no">t</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">system-dark-mode-enabled-p</span> <span class="p">()</span>
  <span class="s">"Check if dark mode is currently enabled on OSX."</span>
  <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">string=</span> <span class="nv">system-type</span> <span class="s">"darwin"</span><span class="p">)</span>
      <span class="p">(</span><span class="nb">string=</span>
       <span class="p">(</span><span class="nv">shell-command-to-string</span> <span class="s">"printf %s \"$( osascript -e \'tell application \"System Events\" to tell appearance preferences to return dark mode\' )\""</span><span class="p">)</span>
       <span class="s">"true"</span><span class="p">)</span>
      <span class="no">nil</span><span class="p">))</span>

<span class="p">(</span><span class="nv">match-emacs-theme-to-system</span><span class="p">)</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Inserting buttons into Emacs buffers</title> <pubDate>Sat, 20 Jun 2020 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/emacs-buttons/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/emacs-buttons/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>This is something I discovered during development of <a href="/projects/beeminder.el/">beeminder.el</a> version 1.2. I wanted to have some text in the buffer saying “View all data” that would perform an action when clicked or when the user pressed <kbd>RET</kbd> on it.</p> <p>I tried a couple of approaches, such as setting text properties in the buffer and then searching at the current point when <kbd>RET</kbd> was pressed. But those solutions didn’t feel right.</p> <p>Finally, I discovered the <code class="highlighter-rouge">insert-button</code> function which does what I wanted.</p> <p>The previous code looked a little like this:</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">insert</span> <span class="s">"View all data"</span><span class="p">)</span>
<span class="p">(</span><span class="nv">put-text-property</span> <span class="p">(</span><span class="nv">line-beginning-position</span><span class="p">)</span>
                   <span class="p">(</span><span class="nv">line-end-position</span><span class="p">)</span>
                   <span class="ss">'beeminder-is-read-more</span>
                   <span class="no">t</span><span class="p">)</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">beeminder-handle-view-all-data-link</span> <span class="p">()</span>
  <span class="s">"Handle a click on the 'Read more data' text."</span>
  <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nv">get-text-property</span> <span class="p">(</span><span class="nv">point</span><span class="p">)</span> <span class="ss">'beeminder-is-read-more</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">beeminder-view-data-for-current-goal</span><span class="p">)))</span>

<span class="c1">;; Bind to &lt;RET&gt;</span>
<span class="p">(</span><span class="nv">define-key</span> <span class="nv">beeminder-mode-map</span>
            <span class="p">(</span><span class="nv">kbd</span> <span class="s">"&lt;RET&gt;"</span><span class="p">)</span>
            <span class="nf">#'</span><span class="nv">beeminder-handle-view-all-data-link</span><span class="p">)</span>
</code></pre></div></div> <p>It’s not the cleanest code ever, and it’s a lot of effort for a simple button. By using <code class="highlighter-rouge">insert-button</code>, it now looks like this:</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">insert-button</span> <span class="s">"View all data"</span>
               <span class="ss">'action</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">_arg</span><span class="p">)</span> <span class="p">(</span><span class="nv">beeminder-view-data-for-current-goal</span><span class="p">)))</span>
</code></pre></div></div> <p>Much better!</p> <p><strong>Read more</strong>: <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Buttons.html">Buttons - GNU Emacs Lisp Reference Manual</a>.</p> ]]></description> </item> <item> <title>Limiting the elfeed read buffer to 80 columns</title> <pubDate>Sat, 20 Jun 2020 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/elfeed-reading-width/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/elfeed-reading-width/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><a href="https://github.com/skeeto/elfeed">elfeed</a> is a really neat RSS reader for Emacs. By default, the reading buffer uses the full width of the window. This can make articles difficult to read on a large, widescreen monitor.</p> <p>Adding the following to the Emacs config limits the reading with to 80 columns:</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">shr-width</span> <span class="mi">80</span><span class="p">)</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Filtering an Emacs Lisp property list</title> <pubDate>Tue, 02 Jun 2020 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/filter-emacs-property-list/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/filter-emacs-property-list/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>In Emacs Lisp, a property list (<code class="highlighter-rouge">plist</code>) looks like this:</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">list</span> <span class="ss">:property1</span> <span class="s">"value1"</span> <span class="ss">:property2</span> <span class="s">"value2"</span><span class="p">)</span>
</code></pre></div></div> <p>I’m currently working on <a href="/projects/beeminder.el/">beeminder.el</a> and wanted to add some optional parameters to a function. Emacs Lisp doesn’t support <code class="highlighter-rouge">&amp;key</code> named parameters, so normally there isn’t a way to do something like this:</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">my-function</span> <span class="s">"required"</span> <span class="s">"also-required"</span> <span class="ss">:optional</span> <span class="s">"value"</span><span class="p">)</span>
</code></pre></div></div> <p>I settled on passing a <code class="highlighter-rouge">plist</code>, but wanted a way to whitelist keys. The following function will filter the <code class="highlighter-rouge">options</code> list to only include keys that are in <code class="highlighter-rouge">allowed</code>.</p> <p>It will probably re-order the list, but for a property list that usually isn’t an issue.</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">filter-plist</span> <span class="p">(</span><span class="nv">options</span> <span class="nv">allowed</span><span class="p">)</span>
  <span class="s">"Filter a symbol and values list OPTIONS to online include ALLOWED symbols.

For example, filtering (:key value :other-key value) with allowed
list of (:key) will return (:key value)."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">filtered-list</span><span class="p">))</span>
    <span class="p">(</span><span class="nb">dolist</span> <span class="p">(</span><span class="nv">key</span> <span class="nv">allowed</span><span class="p">)</span>
      <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nv">plist-member</span> <span class="nv">options</span> <span class="nv">key</span><span class="p">)</span>
        <span class="p">(</span><span class="k">setq</span> <span class="nv">filtered-list</span>
              <span class="p">(</span><span class="nv">plist-put</span> <span class="nv">filtered-list</span> <span class="nv">key</span> <span class="p">(</span><span class="nv">plist-get</span> <span class="nv">options</span> <span class="nv">key</span><span class="p">)))))</span>
    <span class="nv">filtered-list</span><span class="p">))</span>
</code></pre></div></div> <p>This allows us to do this:</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; List of parameters. Only want the :valid key/value pair.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">test-list</span> <span class="p">(</span><span class="nb">list</span> <span class="ss">:valid</span> <span class="s">"value"</span> <span class="ss">:invalid</span> <span class="s">"bad"</span><span class="p">))</span>

<span class="p">(</span><span class="nv">filter-plist</span> <span class="nv">test-list</span> <span class="p">(</span><span class="nb">list</span> <span class="ss">:valid</span><span class="p">))</span>
<span class="c1">;; =&gt; (:valid "value")</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Disabling global smartparens pairs in a mode</title> <pubDate>Sat, 30 May 2020 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/disable-smartparens-pairs/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/disable-smartparens-pairs/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I wanted to use <a href="https://github.com/Fuco1/smartparens">smartparens</a> with <a href="https://www.sodaware.net/blitzmax-mode/">blitzmax-mode</a>, but the global <code class="highlighter-rouge">'</code> completion was inserting two <code class="highlighter-rouge">'</code> characters whenever I commented a line. Not the end of the world, but it was annoying and I wanted a solution.</p> <p><strong>smartparens</strong> can disable a global pair by setting <code class="highlighter-rouge">:actions nil</code> when using <code class="highlighter-rouge">sp-local-pair</code>. For blitzmax-mode, my config looks like this:</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">smartparens</span>
  <span class="ss">:diminish</span> <span class="nv">smartparens-mode</span>
  <span class="ss">:commands</span> <span class="p">(</span><span class="nv">smartparens-mode</span> <span class="nv">sp-local-pair</span><span class="p">)</span>
  <span class="ss">:hook</span>
  <span class="p">((</span><span class="nv">blitzmax-mode</span> <span class="o">.</span> <span class="nv">smartparens-mode</span><span class="p">))</span>
  <span class="ss">:config</span>
  <span class="p">(</span><span class="nb">require</span> <span class="ss">'smartparens-config</span><span class="p">)</span>

  <span class="c1">;; Disable ' auto-pair in blitzmax-mode.</span>
  <span class="p">(</span><span class="nv">sp-local-pair</span> <span class="ss">'blitzmax-mode</span> <span class="s">"'"</span> <span class="no">nil</span> <span class="ss">:actions</span> <span class="no">nil</span><span class="p">))</span>
</code></pre></div></div> <p>Now smartparens inserts a single <code class="highlighter-rouge">'</code> character when I comment a line, but still inserts matching <code class="highlighter-rouge">(</code> and <code class="highlighter-rouge">[</code> characters. Perfect!</p> ]]></description> </item> <item> <title>Testing Emacs extensions with guard and ert-runner</title> <pubDate>Sat, 16 May 2020 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/emacs-guard-and-ert-runner/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/emacs-guard-and-ert-runner/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I use <a href="https://github.com/rejeep/ert-runner.el">ert-runner</a> for running unit tests in my Emacs packages. It’s a handy way to run all unit tests in a single go, and it works nicely with <a href="https://github.com/cask/cask">Cask</a> to make repeatable runs easier.</p> <p>One thing I missed was automatic testing when files are saved. I use <a href="https://github.com/guard/guard">Guard</a> when developing Rails projects and wanted to hook it into my Emacs setup.</p> <p>The following <code class="highlighter-rouge">Guardfile</code> uses <code class="highlighter-rouge">guard-shell</code> to run ert-runner whenever an <code class="highlighter-rouge">.el</code> file is modified. I added a workaround for ignoring flycheck files, which Emacs saves when a file is modified and can trigger a huge amount of builds.</p> <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">guard</span> <span class="ss">:shell</span> <span class="k">do</span>
  <span class="n">watch</span> <span class="p">(</span><span class="sr">/(.*)\.el$/</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span>
    <span class="c1"># Ugly fix but I couldn't spend time messing around with regex.</span>
    <span class="k">unless</span> <span class="n">file</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">to_s</span><span class="p">.</span><span class="nf">include?</span> <span class="s1">'flycheck'</span>
      <span class="k">if</span> <span class="nb">system</span><span class="p">(</span><span class="s1">'cask exec ert-runner'</span><span class="p">)</span>
        <span class="n">n</span> <span class="s1">'Tests succeeded'</span><span class="p">,</span> <span class="s1">'ERT'</span><span class="p">,</span> <span class="ss">:success</span>
      <span class="k">else</span>
        <span class="n">n</span> <span class="s1">'Tests failed'</span><span class="p">,</span> <span class="s1">'ERT'</span><span class="p">,</span> <span class="ss">:failed</span>
      <span class="k">end</span>

      <span class="s1">''</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div> <p>Using <code class="highlighter-rouge">:success</code> and <code class="highlighter-rouge">:failed</code> with the process result also means Guard’s notifier works correctly, so it’s possible to use the Emacs notifier to get realtime test pass &amp; fail colours whenever a file is saved. Pretty neat!</p> ]]></description> </item> <item> <title>Filtering org-projectile files</title> <pubDate>Sat, 07 Mar 2020 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/filtering-org-projectile-files/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/filtering-org-projectile-files/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><a href="https://github.com/IvanMalison/org-projectile/">org-projectile</a> is a small Emacs package that makes it easy to associate org-mode TODO items with projectile projects.</p> <p>Each projectile project can have its own <code class="highlighter-rouge">TODO.org</code>, but sometimes projects don’t have one (or don’t need one) and these empty files are still added to the agenda.</p> <p>The following function filters the <code class="highlighter-rouge">org-projectile</code> list of TODO files and removes any file that doesn’t actually exist.</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/org-projectile-todo-files</span> <span class="p">()</span> 
  <span class="s">"Fetch a list of org TODO files for projects that actually exist."</span>
  <span class="p">(</span><span class="nv">seq-filter</span> <span class="nf">#'</span><span class="nv">file-exists-p</span> <span class="p">(</span><span class="nv">org-projectile-todo-files</span><span class="p">)))</span>

<span class="c1">;; Add org-projectile files to org.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">org-agenda-files</span> <span class="p">(</span><span class="nb">append</span> <span class="nv">org-agenda-files</span> <span class="p">(</span><span class="nv">sodaware/org-projectile-todo-files</span><span class="p">)))</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Connecting the Harvest API to Beeminder</title> <pubDate>Tue, 11 Feb 2020 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/connecting-the-harvest-api-to-beeminder/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/connecting-the-harvest-api-to-beeminder/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>This is a little script I wrote to send my logged <a href="https://getharvest.com/">Harvest</a> hours to a <a href="https://beeminder.com">Beeminder</a> goal. It’s possible to do this via IFTTT or Zapier, but I had a couple of additional requirements:</p> <ol> <li>Should only submit data at the end of the day</li> <li>Only wanted a single data-point in my Beeminder graph</li> <li>Wanted each entry to be rounded up to the nearest 15 minutes</li> </ol> <p>Let’s take them in order.</p> <h3 id="1---only-submit-data-at-the-end-of-the-day">1 - Only submit data at the end of the day</h3> <p>I use cron to run the script every night at 10:55pm. I thought about running it at midnight, but the deadline stops me from working too late.</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>55 22 * * * cd &lt;script directory&gt; &amp;&amp; ./log_time &gt; /&lt;script directory&gt;/bee.log
</code></pre></div></div> <h3 id="2---only-want-a-single-data-point-in-my-graph">2 - Only want a single data point in my graph</h3> <p>Nothing too complex here, the script fetches all individual entries for the day and adds them together.</p> <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">client</span> <span class="o">=</span> <span class="no">Harvest</span><span class="p">.</span><span class="nf">client</span><span class="p">(</span>
  <span class="ss">subdomain: </span><span class="no">ENV</span><span class="p">[</span><span class="s1">'HARVEST_SUBDOMAIN'</span><span class="p">],</span>
  <span class="ss">username:  </span><span class="no">ENV</span><span class="p">[</span><span class="s1">'HARVEST_USERNAME'</span><span class="p">],</span>
  <span class="ss">password:  </span><span class="no">ENV</span><span class="p">[</span><span class="s1">'HARVEST_PASSWORD'</span><span class="p">]</span>
<span class="p">)</span>

<span class="n">todays_entries</span> <span class="o">=</span> <span class="n">client</span><span class="p">.</span><span class="nf">time</span><span class="p">.</span><span class="nf">all</span>
<span class="n">total_time</span>     <span class="o">=</span> <span class="mi">0</span>

<span class="n">todays_entries</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">entry</span><span class="o">|</span>
  <span class="n">total_time</span> <span class="o">+=</span> <span class="n">entry</span><span class="p">.</span><span class="nf">hours</span>
<span class="k">end</span>
</code></pre></div></div> <p>I’d like to replace the <code class="highlighter-rouge">each</code> loop with something more Ruby-ish, but for now it works.</p> <h3 id="3---round-all-entries-up-to-the-nearest-15-minutes">3 - Round all entries up to the nearest 15 minutes</h3> <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Round up a floating point time value to the nearest quarter hour.</span>
<span class="k">def</span> <span class="nf">round_to_quarter_hour</span><span class="p">(</span><span class="n">time</span><span class="p">)</span>
  <span class="p">(</span><span class="n">time</span> <span class="o">*</span> <span class="mi">4</span><span class="p">).</span><span class="nf">ceil</span> <span class="o">/</span> <span class="mf">4.0</span>
<span class="k">end</span>

<span class="c1"># Update the sum loop</span>
<span class="n">todays_entries</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">entry</span><span class="o">|</span>
  <span class="n">total_time</span> <span class="o">+=</span> <span class="n">round_to_quarter_hour</span><span class="p">(</span><span class="n">entry</span><span class="p">.</span><span class="nf">hours</span><span class="p">)</span>
<span class="k">end</span>
</code></pre></div></div> <h3 id="the-finished-script">The finished script</h3> <p>All configuration details are stored in a <code class="highlighter-rouge">.env</code> file in the script directory.</p> <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># frozen_string_literal: true</span>

<span class="nb">require</span> <span class="s1">'beeminder'</span>
<span class="nb">require</span> <span class="s1">'dotenv/load'</span>
<span class="nb">require</span> <span class="s1">'harvested'</span>

<span class="c1"># Round up a floating point time value to the nearest quarter hour.</span>
<span class="k">def</span> <span class="nf">round_to_quarter_hour</span><span class="p">(</span><span class="n">time</span><span class="p">)</span>
  <span class="p">(</span><span class="n">time</span> <span class="o">*</span> <span class="mi">4</span><span class="p">).</span><span class="nf">ceil</span> <span class="o">/</span> <span class="mf">4.0</span>
<span class="k">end</span>

<span class="nb">puts</span> <span class="s1">'Fetching data...'</span>

<span class="n">client</span> <span class="o">=</span> <span class="no">Harvest</span><span class="p">.</span><span class="nf">client</span><span class="p">(</span>
  <span class="ss">subdomain: </span><span class="no">ENV</span><span class="p">[</span><span class="s1">'HARVEST_SUBDOMAIN'</span><span class="p">],</span>
  <span class="ss">username:  </span><span class="no">ENV</span><span class="p">[</span><span class="s1">'HARVEST_USERNAME'</span><span class="p">],</span>
  <span class="ss">password:  </span><span class="no">ENV</span><span class="p">[</span><span class="s1">'HARVEST_PASSWORD'</span><span class="p">]</span>
<span class="p">)</span>

<span class="c1"># Get all entries for today.</span>
<span class="n">todays_entries</span> <span class="o">=</span> <span class="n">client</span><span class="p">.</span><span class="nf">time</span><span class="p">.</span><span class="nf">all</span>
<span class="n">total_time</span>     <span class="o">=</span> <span class="mi">0</span>

<span class="c1"># Round up each entry to nearest 0.25.</span>
<span class="n">todays_entries</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">entry</span><span class="o">|</span>
  <span class="n">total_time</span> <span class="o">+=</span> <span class="n">round_to_quarter_hour</span><span class="p">(</span><span class="n">entry</span><span class="p">.</span><span class="nf">hours</span><span class="p">)</span>
<span class="k">end</span>

<span class="c1"># Submit the value to beeminder.</span>
<span class="n">beeminder</span> <span class="o">=</span> <span class="no">Beeminder</span><span class="o">::</span><span class="no">User</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span>
  <span class="no">ENV</span><span class="p">[</span><span class="s1">'BEEMINDER_TOKEN'</span><span class="p">],</span>
  <span class="ss">auth_type: :personal</span>
<span class="p">)</span>

<span class="nb">puts</span> <span class="s1">'Sending data...'</span>

<span class="n">beeminder</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span>
  <span class="no">ENV</span><span class="p">[</span><span class="s1">'BEEMINDER_GOAL'</span><span class="p">],</span>
  <span class="n">total_time</span><span class="p">,</span>
  <span class="s2">"AUTO: </span><span class="si">#{</span><span class="n">total_time</span><span class="si">}</span><span class="s2"> hours billed for day"</span>
<span class="p">)</span>

<span class="nb">puts</span> <span class="s1">'Done'</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Enabling lsp-mode for solargraph projects</title> <pubDate>Sat, 28 Dec 2019 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/enabling-lsp-mode-for-solargraph-projects/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/enabling-lsp-mode-for-solargraph-projects/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I’ve started using <code class="highlighter-rouge">lsp-mode</code> in Emacs to add some smarter auto-completion and tooltips. I wanted to try and activate <code class="highlighter-rouge">lsp-mode</code> automatically when editing files in a Rails project, but only if solargraph is in the <code class="highlighter-rouge">Gemfile</code>.</p> <p>I’m not sure this is actually something I’ll keep using, but it was a fun exercise.</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'enh-ruby-mode-hook</span> <span class="nf">#'</span><span class="nv">sodaware/enable-lsp-for-solargraph-projects</span><span class="p">)</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/enable-lsp-for-solargraph-projects</span> <span class="p">()</span>
  <span class="s">"Enable lsp-mode if the current project has solargraph installed."</span>
  <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nv">sodaware/has-solargraph-p</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">lsp</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/has-solargraph-p</span> <span class="p">()</span>
  <span class="s">"Check if the current Rails project has solargraph installed."</span>
  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">root</span>    <span class="p">(</span><span class="nv">sodaware/get-closest-gemfile-root</span><span class="p">))</span>
         <span class="p">(</span><span class="nv">gemfile</span> <span class="p">(</span><span class="nv">concat</span> <span class="nv">root</span> <span class="s">"/Gemfile"</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">unless</span> <span class="no">nil</span>
      <span class="p">(</span><span class="nv">with-temp-buffer</span>
        <span class="p">(</span><span class="nv">insert-file-contents</span> <span class="nv">gemfile</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">search-forward</span> <span class="s">"solargraph"</span> <span class="no">nil</span> <span class="no">t</span><span class="p">)))))</span>

<span class="p">(</span><span class="nv">defun*</span> <span class="nv">sodaware/get-closest-gemfile-root</span> <span class="p">(</span><span class="k">&amp;optional</span> <span class="p">(</span><span class="nv">file</span> <span class="s">"Gemfile"</span><span class="p">))</span>
  <span class="s">"Determine the pathname of the first instance of FILE starting from the current directory towards root.

This may not do the correct thing in presence of links. If it does not find
FILE, then it shall return the name of FILE in the current directory, suitable
for creation."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">root</span> <span class="p">(</span><span class="nv">expand-file-name</span> <span class="s">"/"</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">loop</span>
     <span class="nv">for</span> <span class="nv">d</span> <span class="nb">=</span> <span class="nv">default-directory</span> <span class="nv">then</span> <span class="p">(</span><span class="nv">expand-file-name</span> <span class="s">".."</span> <span class="nv">d</span><span class="p">)</span>
     <span class="k">if</span> <span class="p">(</span><span class="nv">file-exists-p</span> <span class="p">(</span><span class="nv">expand-file-name</span> <span class="nv">file</span> <span class="nv">d</span><span class="p">))</span>
     <span class="nb">return</span> <span class="nv">d</span>
     <span class="k">if</span> <span class="p">(</span><span class="nb">equal</span> <span class="nv">d</span> <span class="nv">root</span><span class="p">)</span>
     <span class="nb">return</span> <span class="no">nil</span><span class="p">)))</span>
</code></pre></div></div> <p>It’s not particularly elegant, and I think there will be performance problems for with larger <code class="highlighter-rouge">Gemfile</code>s.</p> ]]></description> </item> <item> <title>BMK compiler flags</title> <pubDate>Sun, 01 Dec 2019 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/bmk-compiler-flags/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/bmk-compiler-flags/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>The BlitzMax compiler (<code class="highlighter-rouge">bmk</code>) supports a number of compilation options, but it just outputs “Command line error” instead of a help message.</p> <p>A compilation command is make up of three parts:</p> <ul> <li>The action to take</li> <li>Optional flags</li> <li>The file or module to compile</li> </ul> <p>Allowed actions are:</p> <ul> <li><code class="highlighter-rouge">makeapp</code> : Create an application (e.g. an <code class="highlighter-rouge">exe</code> file on Windows)</li> <li><code class="highlighter-rouge">makemods</code> : Compile a BlitzMax module</li> </ul> <p>The following flags are supported:</p> <ul> <li><code class="highlighter-rouge">-h</code> : Compile in threaded mode.</li> <li><code class="highlighter-rouge">-d</code> : Compile in debug mode.</li> <li><code class="highlighter-rouge">-r</code> : Compile in release mode.</li> <li><code class="highlighter-rouge">-a</code> : Rebuild all files during compilation.</li> <li><code class="highlighter-rouge">-t gui</code> : Compile in GUI mode. Applications compiled with this argument will not display a console window when run.</li> <li><code class="highlighter-rouge">-o &lt;file&gt;</code> : Write the compiled application to <code class="highlighter-rouge">&lt;file&gt;</code></li> </ul> <p>The final argument should be the file or module to compile.</p> <h2 id="examples">Examples:</h2> <h3 id="1-compile-a-module-in-release-mode">1. Compile a module in release mode</h3> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bmk makemods <span class="nt">-r</span> my_module
</code></pre></div></div> <h3 id="2-compile-a-threaded-non-console-application">2. Compile a threaded, non-console application</h3> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bmk makeapp <span class="nt">-h</span> <span class="nt">-t</span> gui <span class="nt">-o</span> output.exe src/my_file.bmx
</code></pre></div></div> ]]></description> </item> <item> <title>Showing Emacs dashboard on launch</title> <pubDate>Wed, 13 Nov 2019 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/showing-emacs-dashboard/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/showing-emacs-dashboard/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><a href="https://github.com/emacs-dashboard/emacs-dashboard">Emacs dashboard</a> creates a startup page for Emacs that gives quick access to projects, recent files and even org-mode agenda items.</p> <p>The following code configures Emacs to show the <code class="highlighter-rouge">*dashboard*</code> buffer after launch. It works with <code class="highlighter-rouge">emacsclient</code> as well.</p> <div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">initial-buffer-choice</span> <span class="nf">#'</span><span class="p">(</span><span class="k">lambda</span> <span class="p">()</span> <span class="p">(</span><span class="nv">get-buffer-create</span> <span class="s">"*dashboard*"</span><span class="p">)))</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Fetching JSON data with Emacs Lisp</title> <pubDate>Sat, 19 Oct 2019 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/elisp-get-json/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/elisp-get-json/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>The following snippet of Emacs Lisp will fetch a remote URI and return the contents as a parsed JSON object.</p> <div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">get-json</span> <span class="p">(</span><span class="nv">uri</span><span class="p">)</span>
  <span class="s">"Fetch the contents of URI and parse."</span>
  <span class="p">(</span><span class="nv">with-current-buffer</span> <span class="p">(</span><span class="nv">url-retrieve-synchronously</span> <span class="nv">uri</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">goto-char</span> <span class="p">(</span><span class="nv">point-min</span><span class="p">))</span>
    <span class="p">(</span><span class="nv">goto-char</span> <span class="nv">url-http-end-of-headers</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">prog1</span> <span class="p">(</span><span class="nv">json-read</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">kill-buffer</span><span class="p">))))</span>
</code></pre></div></div> <p>Something like:</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
   </span><span class="nl">"field"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"value"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div> <p>will return an object like this:</p> <div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">'</span><span class="p">((</span><span class="nv">field</span> <span class="o">.</span> <span class="s">"value"</span><span class="p">))</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Writing to STDERR with PHP</title> <pubDate>Wed, 18 Sep 2019 18:10:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/php-stderr/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/php-stderr/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>The following function will write <code class="highlighter-rouge">$text</code> to STDERR instead of STDOUT like <code class="highlighter-rouge">print</code> and <code class="highlighter-rouge">echo</code>.</p> <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">function</span> <span class="nf">print_error</span><span class="p">(</span><span class="nv">$text</span><span class="p">)</span> <span class="p">{</span>
    <span class="nb">fwrite</span><span class="p">(</span><span class="nx">STDERR</span><span class="p">,</span> <span class="nv">$text</span> <span class="o">.</span> <span class="nx">PHP_EOL</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div> <p>It’s handy for scripts that output things to STDOUT that may be redirected or saved to a file (e.g. a script that outputs CSV or JSON data).</p> ]]></description> </item> <item> <title>YASnippet to wrap a model access</title> <pubDate>Sat, 24 Aug 2019 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/wrap-helper-yasnippet/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/wrap-helper-yasnippet/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>A piece of PHP code I use fairly often is wrapping a model or helper field in a function so the object is only instantiated when accessed. It looks like this:</p> <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">protected</span> <span class="k">function</span> <span class="nf">my_helper</span><span class="p">()</span> <span class="p">{</span>
	<span class="k">if</span> <span class="p">(</span> <span class="k">empty</span><span class="p">(</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">my_helper</span> <span class="p">)</span> <span class="p">)</span> <span class="p">{</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">my_helper</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">MyHelper</span><span class="p">();</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">my_helper</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div> <p>The following bit of YASnippet code expands <code class="highlighter-rouge">wrap_helper</code> into the above code and automatically sets the field name once the function name has been entered.</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code># -*- mode: snippet -*-
# name: Wrap a helper or model
# key: wrap_helper
# group: templates
# --
protected function $1() {
	if ( empty( $this-&gt;$1 ) ) {
		$this-&gt;$1 = new ${2:ClassName}();
	}

	return $this-&gt;$1;
}
$0
</code></pre></div></div> ]]></description> </item> <item> <title>Listing BlitzMax module dependencies</title> <pubDate>Sun, 19 May 2019 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/list-blitzmax-dependencies/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/list-blitzmax-dependencies/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>The following snippet will list all modules that a source file (or files) depend on. Replace <code class="highlighter-rouge">&lt;SOURCE FILE&gt;</code> with a file name or directory to search:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">grep</span> <span class="nt">--include</span><span class="o">=</span><span class="s2">"*.bmx"</span> <span class="nt">-hri</span> <span class="s2">"^import [^</span><span class="se">\"</span><span class="s2">]"</span> &lt;SOURCE FILE&gt; |
    <span class="nb">sort</span> |
    <span class="nb">uniq</span> |
    <span class="nb">sed</span> <span class="s1">'s/[Ii]mport //g'</span>
</code></pre></div></div> <p>This will give output something like the following:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brl.linkedlist
brl.map
brl.reflection
brl.retro
sodaware.blitzmax_array
sodaware.blitzmax_ascii
sodaware.file_fnmatch
</code></pre></div></div> <p>The snippet is broken into a couple of parts:</p> <ul> <li><code class="highlighter-rouge">grep --include="*.bmx" -hri "^import [^\"]" &lt;SOURCE FILE&gt;</code> <ul> <li><code class="highlighter-rouge">--include="*.bmx*"</code> Instructs grep to search only <code class="highlighter-rouge">bmx</code> files.</li> <li><code class="highlighter-rouge">-h</code> Removes the file name from results</li> <li><code class="highlighter-rouge">-r</code> is a recursive search</li> <li><code class="highlighter-rouge">-i</code> ignores case</li> <li><code class="highlighter-rouge">"^import [^\"]"</code> will search for lines that start with “import” that are not followed by a <code class="highlighter-rouge">"</code> character (i.e. a file import).</li> </ul> </li> <li><code class="highlighter-rouge">sort</code> - Sorts lines A to Z</li> <li><code class="highlighter-rouge">uniq</code> - Removes duplicate lines from the results</li> <li><code class="highlighter-rouge">sed 's/[Ii]mport//g'</code> strips the starting <code class="highlighter-rouge">Import </code>.</li> </ul> ]]></description> </item> <item> <title>nginx IP authentication with password fallback</title> <pubDate>Sun, 12 May 2019 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/nginx-ip-password-fallback/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/nginx-ip-password-fallback/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I have a few pages online that I want to be protected, but ocassionally I might pass out a link to share. I didn’t really like having to remember a password, so I set up an IP whitelist. Anybody not on the list is denied.</p> <p>The problem is that I need to update the IP whitelist when someone new wants access, which isn’t always practical.</p> <p>This solution will check for a whitelisted IP first. If that fails, it will prompt for a username and password.</p> <div class="language-nginx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">satisfy</span> <span class="s">any</span><span class="p">;</span>

<span class="c1"># Authenticate via IP address.</span>
<span class="k">allow</span> <span class="mi">127</span><span class="s">.0.0.1</span><span class="p">;</span> <span class="c1"># Should be an actual IP</span>
<span class="k">deny</span> <span class="s">all</span><span class="p">;</span>

<span class="c1"># Try a password if IP didn't match.</span>
<span class="k">auth_basic</span>           <span class="s">"Private"</span><span class="p">;</span>
<span class="k">auth_basic_user_file</span> <span class="n">/path/to/.htpasswd</span><span class="p">;</span>
</code></pre></div></div> ]]></description> </item> <item> <title>FacileThings keyboard shortcuts</title> <pubDate>Sun, 21 Apr 2019 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/facile-things-keyboard-shortcuts/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/facile-things-keyboard-shortcuts/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><a href="https://facilethings.com/">FacileThings</a> is a todo organizer that is heavily optimized for the Getting Things Done (GTD) methodology.</p> <p>It took me a while to find keyboard shortcuts for navigating the different areas.</p> <h2 id="navigating-main-sections">Navigating main sections</h2> <table class="table--fancy table--striped table--shortcuts"> <thead> <tr> <th>Shortcut</th> <th>What it does</th> </tr> </thead> <tbody> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">1</code></td> <td>Jump to “Capture” section</td> </tr> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">2</code></td> <td>Jump to “Clarify” section</td> </tr> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">3</code></td> <td>Open “Organize” menu</td> </tr> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">4</code></td> <td>Open “Reflect” menu</td> </tr> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">5</code></td> <td>Jump to “Engage” section</td> </tr> </tbody> </table> <h2 id="organize-menu-shortcuts">“Organize” menu shortcuts</h2> <p>Call these after opening the “organize” menu with <code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">3</code>:</p> <table class="table--fancy table--striped table--shortcuts"> <thead> <tr> <th>Shortcut</th> <th>What it does</th> </tr> </thead> <tbody> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">L</code></td> <td>Open “Lists”</td> </tr> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">P</code></td> <td>Open “Projects”</td> </tr> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">R</code></td> <td>Open “Routines”</td> </tr> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">C</code></td> <td>Open “Checklists”</td> </tr> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">E</code></td> <td>Open “People”</td> </tr> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">L</code></td> <td>Open “Lists”</td> </tr> </tbody> </table> <h2 id="reflect-menu-shortcuts">“Reflect” menu shortcuts</h2> <p>Call these after opening the “reflect” menu with <code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">4</code>:</p> <table class="table--fancy table--striped table--shortcuts"> <thead> <tr> <th>Shortcut</th> <th>What it does</th> </tr> </thead> <tbody> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">R</code></td> <td>Open “Weekly review”</td> </tr> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">P</code></td> <td>Open “Perspective”</td> </tr> <tr> <td><code class="code--keycode highlighter-rouge">CTRL</code>+<code class="code--keycode highlighter-rouge">A</code></td> <td>Open “Analytics”</td> </tr> </tbody> </table> ]]></description> </item> <item> <title>Elisp for adding log entries</title> <pubDate>Mon, 15 Apr 2019 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/elisp-log-entries/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/elisp-log-entries/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>The <a href="/log/">logs section</a> of this site uses some simple markdown for entries. An example looks like this:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>---
title: 2019
layout: log
---

## 2019-04-15

* This is a log entry.
</code></pre></div></div> <p>I wanted to try writing a little bit of elisp code to streamline the process of adding new entries. It’s not exactly time-consuming to add a few new lines by hand, but reducing friction means I’m more likely to keep things updated.</p> <p>Each log file is stored in <code class="highlighter-rouge">_logs</code> inside the jekyll source directory:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>- src
  - _posts
  - _notes
  - _logs
    - 2019.md
</code></pre></div></div> <p>In the end I came up with the following code:</p> <div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defvar</span> <span class="nv">sodaware/sdf-logs-path</span> <span class="s">"/path/to/jekyll/src/_logs/"</span><span class="p">)</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/sdf-log</span> <span class="p">()</span>
  <span class="s">"Add a new entry to the current sodaware.sdf.org log."</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">current-year</span> <span class="p">(</span><span class="nv">format-time-string</span> <span class="s">"%Y"</span><span class="p">))</span>
         <span class="p">(</span><span class="nv">current-date</span> <span class="p">(</span><span class="nv">format-time-string</span> <span class="s">"%Y-%m-%d"</span><span class="p">))</span>
         <span class="p">(</span><span class="nv">log-file</span>     <span class="p">(</span><span class="nb">format</span> <span class="s">"%s%s.md"</span> <span class="nv">sodaware/sdf-logs-path</span> <span class="nv">current-year</span><span class="p">)))</span>
    <span class="c1">;; Find the log file.</span>
    <span class="p">(</span><span class="nv">find-file</span> <span class="nv">log-file</span><span class="p">)</span>

    <span class="c1">;; Add Jekyll markup if file is empty.</span>
    <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">=</span> <span class="mi">0</span> <span class="p">(</span><span class="nv">buffer-size</span><span class="p">))</span>
      <span class="p">(</span><span class="nv">insert</span> <span class="s">"---"</span> <span class="s">"\n"</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">insert</span> <span class="s">"title: "</span> <span class="nv">current-year</span> <span class="s">"\n"</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">insert</span> <span class="s">"layout: log\n"</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">insert</span> <span class="s">"---"</span> <span class="s">"\n\n"</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">insert</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"## %s\n\n"</span> <span class="nv">current-date</span><span class="p">)))</span>

    <span class="c1">;; Attempt to find the current heading. If not found, insert it.</span>
    <span class="p">(</span><span class="nv">sodaware/find-or-insert-heading</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"## %s"</span> <span class="nv">current-date</span><span class="p">)</span> <span class="s">"## "</span><span class="p">)</span>

    <span class="c1">;; Insert after.</span>
    <span class="p">(</span><span class="nv">forward-line</span> <span class="mi">2</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">insert</span> <span class="s">"* \n"</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">forward-line</span> <span class="mi">-1</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">move-end-of-line</span> <span class="mi">1</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/find-or-insert-heading</span> <span class="p">(</span><span class="nv">heading</span> <span class="nv">start-of-heading</span><span class="p">)</span>
  <span class="s">"Find or insert HEADING before START-OF-HEADING in the current buffer."</span>
  <span class="c1">;; Go to the start of the file.</span>
  <span class="p">(</span><span class="nv">goto-char</span> <span class="p">(</span><span class="nv">point-min</span><span class="p">))</span>

  <span class="c1">;; Search for the heading. If not found, find the start of the first heading</span>
  <span class="c1">;; and insert before that.</span>
  <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nv">search-forward</span> <span class="nv">heading</span> <span class="no">nil</span> <span class="no">t</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">goto-char</span> <span class="p">(</span><span class="nv">point-min</span><span class="p">))</span>
    <span class="p">(</span><span class="nv">search-forward</span> <span class="nv">start-of-heading</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">move-beginning-of-line</span> <span class="mi">1</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">insert</span> <span class="s">"\n\n"</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">forward-line</span> <span class="mi">-2</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">insert</span> <span class="nv">heading</span> <span class="s">"\n"</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">forward-line</span> <span class="mi">-1</span><span class="p">))</span>

  <span class="p">(</span><span class="nv">move-beginning-of-line</span> <span class="mi">1</span><span class="p">))</span>

</code></pre></div></div> <h2 id="notes">Notes</h2> <ul> <li> <dl> <dt><code class="highlighter-rouge">sodaware/sdf-logs-path</code></dt> <dd>The full path of the log directory.</dd> </dl> </li> <li> <dl> <dt><code class="highlighter-rouge">sodaware/find-or-insert-heading</code></dt> <dd>A utility function function that searches for a headline in the current buffer. If the headline is not found, it will be inserted above the first headline in the file. It’s not Markdown specific, so something like <code class="highlighter-rouge">(sodaware/find-or-insert-heading "** heading" "** ")</code> would work for org-mode headlines.</dd> </dl> </li> <li> <dl> <dt><code class="highlighter-rouge">sodaware/sdf-log</code></dt> <dd>The main function to call when adding a new entry. It opens the log file for the current year and inserts a timestamp heading before the first headline. If the file does not exist, it is created and filled with Jekyll markup and the first headline.</dd> </dl> </li> </ul> <h2 id="future-improvements">Future improvements</h2> <p>I’m not 100% happy with how things currently work. I’d like to split things up further so I can reuse the main note creation function for other projects. I often keep project development logs in markdown format and it would be handy to use the same skeleton code for adding entries to them.</p> ]]></description> </item> <item> <title>Opening a Quake-style terminal in XFCE</title> <pubDate>Sat, 13 Apr 2019 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/xfce-quake-terminal/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/xfce-quake-terminal/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>There are a plenty of packages for GNU/Linux that open Quake-style terminal windows. KDE has <a href="https://kde.org/applications/system/yakuake/">yakuake</a>, and GTK has <a href="https://github.com/lanoxx/tilda">tilda</a> and <a href="http://guake-project.org/">Guake</a> (and more).</p> <p>The built-in XFCE terminal can be opened in drop-down mode by calling <code class="highlighter-rouge">xfce4-terminal</code> with the <code class="highlighter-rouge">--drop-down</code> flag.</p> <p>The following steps will bind opening a terminal window to a keyboard shortcut without installing additional packages.</p> <h2 id="1-open-xfce-keyboard-settings">1. Open XFCE keyboard settings</h2> <p>This can be found under “Settings” &gt; “Keyboard” in the menu, or by running <code class="highlighter-rouge">xfce4-keyboard-settings</code> directly.</p> <h2 id="2-add-a-new-command">2. Add a new command</h2> <p><img src="/assets/images/xfce4-keyboard-settings.png" alt="XFCE keyboard settings window"/></p> <p>Switch to the “Application Shortcuts” tab and use the “Add” button to create a new shortcut.</p> <p>Enter <code class="highlighter-rouge">xfce4-terminal --drop-down</code> as the shortcut.</p> <p><img src="/assets/images/xfce4-shortcut.png" alt="XFCE new shortcut"/></p> <h2 id="3-enter-the-shortcut">3. Enter the shortcut</h2> <p>XFCE will prompt for a shortcut once the command has been added. I went with <code class="code--keycode highlighter-rouge">SUPER</code>+<code class="code--keycode highlighter-rouge">`</code>, but <code class="code--keycode highlighter-rouge">F12</code> is another popular shortcut.</p> <p>Once set up the shortcut key will show a terminal window at the top of the screen. Pressing it again will hide the window - the window keeps its previous contents so it can be hidden without losing anything.</p> ]]></description> </item> <item> <title>Setting Xubuntu calendar week to start on Mondays</title> <pubDate>Sat, 13 Apr 2019 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/setting-ubuntu-calendar-locale/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/setting-ubuntu-calendar-locale/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I use the <a href="https://xfce.org/">xfce</a> for my desktop environment. Recently I’ve been trying to fix all of the little things that bug me but aren’t really important. I wanted the xfce calendar to start weeks on Monday rather than Sunday.</p> <p>Adding the following to <code class="highlighter-rouge">/etc/default/locale</code> did the trick:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>LC_TIME="en_GB.UTF-8"
</code></pre></div></div> ]]></description> </item> <item> <title>Restarting frozen XFCE panels</title> <pubDate>Tue, 26 Mar 2019 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/restarting-xfce-panel/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/restarting-xfce-panel/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>Sometimes an XFCE panel will stop responding to mouse clicks. It’s frustrating to have to logout or restart just to get it working again.</p> <p>Running <code class="highlighter-rouge">xfce4-panel -r</code> from the terminal will restart all XFCE panels and fix any frozen ones.</p> ]]></description> </item> <item> <title>Zile - an Emacs-like nano alternative</title> <pubDate>Sun, 24 Mar 2019 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/emacs-like-nano-alternative/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/emacs-like-nano-alternative/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><img src="/assets/images/zile.png" alt="Zile screenshot" class="centered"/></p> <p>Although Emacs is my primary editor 99% of the time, I still use <code class="highlighter-rouge">nano</code> when I need to edit something quickly (and especially if I need root priveleges).</p> <p>I recently found out about <a href="https://www.gnu.org/software/zile/">zile</a>, an extremely lightweight editor that uses Emacs key-bindings and has a similar buffer mode.</p> <p>It’s not a replacement for Emacs, but it does support scripting and is a decent alternative to nano.</p> ]]></description> </item> <item> <title>Counting words with wc</title> <pubDate>Wed, 20 Mar 2019 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/counting-words/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/counting-words/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>Linux systems come with <code class="highlighter-rouge">wc</code>, a useful command for counting words that gives output something like this:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 39 141 853 sorting-directories-by-size.md
</code></pre></div></div> <p>This gives 3 values: The number of lines, the number of words and the number of bytes. <code class="highlighter-rouge">wc</code> also supports flags for getting just one of these values.</p> <p>For example:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">wc</span> <span class="nt">-w</span> my-file.md
123 my-file.md
</code></pre></div></div> <p>However, that still includes the filename. To get <strong>just</strong> the word count (or byte count/line count) without parsing the file takes an extra step:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat </span>my-file.md | <span class="nb">wc</span> <span class="nt">-w</span>
</code></pre></div></div> <p>Which will echo the number of words without any extra data.</p> <p>I’ve used this to keep track of a text file’s wordcount over time with the following snippet:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">date</span> <span class="s1">'+%Y-%m-%d %H:%M:%S'</span><span class="si">)</span><span class="s2">,file.org,</span><span class="si">$(</span><span class="nb">cat </span>file.org | <span class="nb">wc</span> <span class="nt">-w</span><span class="si">)</span><span class="s2">"</span> <span class="o">&gt;&gt;</span> wordcount.csv
</code></pre></div></div> <p>This appends a line to “wordcount.csv” containing the current time and date, the file name and the number of words.</p> ]]></description> </item> <item> <title>Sorting top-level directory names by size</title> <pubDate>Sun, 17 Mar 2019 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/sorting-directories-by-size/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/sorting-directories-by-size/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>This is a quick one-liner for sorting a list of directories by size, largest first:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">du</span> <span class="nt">--max-depth</span><span class="o">=</span>1 <span class="nb">.</span> | <span class="nb">sort</span> <span class="nt">-nr</span>
</code></pre></div></div> <p>Which will return a list something like this:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>8204	./.cache
1829	./.git
1416	./_site
785	./source
384	./.sass-cache
8	./plugins
4	./raw
0	./images
</code></pre></div></div> <p>There are two parts to the command:</p> <h4 id="du-max-depth1-">du –max-depth=1 .</h4> <p><code class="highlighter-rouge">du</code> displays a list of directory sizes. The <code class="highlighter-rouge">--max-depth=1</code> parameter limits the list to top-level directories. Their size will still include files in their sub-directories, but these sub-directories will not be included in the results list.</p> <h4 id="sort--nr">sort -nr</h4> <p>Sorts the results. The <code class="highlighter-rouge">n</code> parameter sorts by numerical data (in this case size rather than the name) and <code class="highlighter-rouge">r</code> reverses the list so newer smallest items show at the bottom.</p> ]]></description> </item> <item> <title>Aligning PHP arrays with Emacs (Part 2)</title> <pubDate>Tue, 12 Mar 2019 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/aligning-php-arrays-part-2/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/aligning-php-arrays-part-2/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>In the past I’ve used <a href="/notes/aligning-php-arrays-with-emacs/">emacs-php-align</a> to align PHP arrays. However, there’s a more flexible alternative built into Emacs - <code class="highlighter-rouge">align-regexp</code>.</p> <p>Here’s the original example I used.</p> <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$my_array</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
    <span class="s1">'key'</span> <span class="o">=&gt;</span> <span class="s1">'Value'</span><span class="p">,</span>
    <span class="s1">'key_two'</span> <span class="o">=&gt;</span> <span class="s1">'Another value'</span><span class="p">,</span>
    <span class="s1">'really_long_key'</span> <span class="o">=&gt;</span> <span class="s1">'Value'</span><span class="p">,</span>
    <span class="s1">'k'</span> <span class="o">=&gt;</span> <span class="s1">'Value'</span><span class="p">,</span>
<span class="p">);</span>
</code></pre></div></div> <p>To align this with <code class="highlighter-rouge">align-regexp</code>, highlight the contents of the array and then:</p> <ol> <li>Run the <code class="highlighter-rouge">align-regexp</code> command (i.e. <code class="highlighter-rouge">M-x align-regexp</code>)</li> <li>Enter <code class="highlighter-rouge">=&gt;</code> at the “Align regexp” prompt</li> </ol> <p>Which converts it into this:</p> <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$my_array</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
    <span class="s1">'key'</span>             <span class="o">=&gt;</span> <span class="s1">'Value'</span><span class="p">,</span>
    <span class="s1">'key_two'</span>         <span class="o">=&gt;</span> <span class="s1">'Another value'</span><span class="p">,</span>
    <span class="s1">'really_long_key'</span> <span class="o">=&gt;</span> <span class="s1">'Value'</span><span class="p">,</span>
    <span class="s1">'k'</span>               <span class="o">=&gt;</span> <span class="s1">'Value'</span><span class="p">,</span>
<span class="p">);</span>
</code></pre></div></div> <p>As the name suggests, <code class="highlighter-rouge">align-regexp</code> takes a regular expression for alignment. This means it can also be used to align pretty much anything.</p> <p>e.g.</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"key"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"Value"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"key_two"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"Another value"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"really_long_key"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="mi">200</span><span class="p">,</span><span class="w">
    </span><span class="nl">"k"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"Value"</span><span class="p">,</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div> <p>With <code class="highlighter-rouge">align-regexp</code> using <code class="highlighter-rouge">:</code> becomes:</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"key"</span><span class="w">             </span><span class="p">:</span><span class="w"> </span><span class="s2">"Value"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"key_two"</span><span class="w">         </span><span class="p">:</span><span class="w"> </span><span class="s2">"Another value"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"really_long_key"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="mi">200</span><span class="p">,</span><span class="w">
    </span><span class="nl">"k"</span><span class="w">               </span><span class="p">:</span><span class="w"> </span><span class="s2">"Value"</span><span class="p">,</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div> ]]></description> </item> <item> <title>Enabling doom-modeline icons when using daemon mode</title> <pubDate>Tue, 22 Jan 2019 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/emacs-daemon-doom-modeline-icons/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/emacs-daemon-doom-modeline-icons/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><a href="https://seagle0128.github.io/doom-modeline/">doom-modeline</a> disables modeline icons when running Emacs in daemon mode. This caused me much head-scratching, but I came across two solutions:</p> <p>The quickest is to set <code class="highlighter-rouge">doom-modeline-icon</code> to <code class="highlighter-rouge">t</code> during initialization. This works fine, but if you connect emacs from the terminal using <code class="highlighter-rouge">emacsclient -nw</code> things can look a little weird.</p> <p>Adding the following to my “init.el” file does the same thing, but only enables icons the first time a window frame is opened:</p> <div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">enable-doom-modeline-icons</span> <span class="p">(</span><span class="nv">_frame</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">doom-modeline-icon</span> <span class="no">t</span><span class="p">))</span>
  
<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-make-frame-functions</span> 
          <span class="nf">#'</span><span class="nv">enable-doom-modeline-icons</span><span class="p">)</span>
</code></pre></div></div> <p>I’m still looking for a way to switching icons on and off when switching between a terminal and windowed session. This does things well enough for now.</p> ]]></description> </item> <item> <title>Converting binary strings to ASCII text in PHP</title> <pubDate>Wed, 12 Dec 2018 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/converting-binary-strings-in-php/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/converting-binary-strings-in-php/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>PHP has a couple of functions for converting between formats (such as <code class="highlighter-rouge">hex2bin</code>).</p> <p>The following function converts a binary string (i.e. a string made up of “0” and “1” characters) into a regular PHP string:</p> <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">function</span> <span class="nf">bin_to_ascii</span><span class="p">(</span><span class="nv">$data</span><span class="p">)</span> <span class="p">{</span>
    <span class="nv">$output</span> <span class="o">=</span> <span class="s1">''</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span> <span class="nv">$i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nv">$i</span> <span class="o">&lt;</span> <span class="nb">strlen</span><span class="p">(</span> <span class="nv">$data</span> <span class="p">);</span> <span class="nv">$i</span> <span class="o">+=</span> <span class="mi">8</span> <span class="p">)</span> <span class="p">{</span>
        <span class="nv">$chunk</span> <span class="o">=</span> <span class="nb">substr</span><span class="p">(</span> <span class="nv">$data</span><span class="p">,</span> <span class="nv">$i</span><span class="p">,</span> <span class="mi">8</span> <span class="p">);</span>
        <span class="nv">$output</span> <span class="o">.=</span> <span class="nb">pack</span><span class="p">(</span><span class="s1">'H*'</span><span class="p">,</span> <span class="nb">base_convert</span><span class="p">(</span><span class="nv">$chunk</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">16</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nv">$output</span><span class="p">;</span>
<span class="p">}</span>

<span class="c1">// Example:</span>
<span class="nv">$data</span>  <span class="o">=</span> <span class="s1">'01001000011001010110110001101100011011110010110000100000'</span><span class="p">;</span>
<span class="nv">$data</span> <span class="o">.=</span> <span class="s1">'010101110110111101110010011011000110010000100001'</span><span class="p">;</span>

<span class="c1">// Prints "Hello, World!"</span>
<span class="k">echo</span> <span class="nx">bin_to_ascii</span><span class="p">(</span><span class="nv">$data</span><span class="p">);</span>

</code></pre></div></div> <p>The function slices the input string into chunks of 8 characters, because each ASCII character is 8 bits long.</p> <p><a href="https://secure.php.net/manual/en/function.pack.php">pack</a> is a nifty PHP function for converting binary data into other forms.</p> <p>In this example, the chunk of data is converted into actual binary data using <code class="highlighter-rouge">base_convert</code>. <code class="highlighter-rouge">base_convert</code> is used to convert a base 2 (i.e. binary) number into base 16 (hexadecimal). <code class="highlighter-rouge">pack</code> then converts the hex value into a readable string. Each character is converted before being returned in one string.</p> <p><strong>Important</strong>:</p> <p>The input string should be valid binary - it should only contain 1s and 0s, and the length should be a multiple of 8. Weird things will happen otherwise.</p> ]]></description> </item> <item> <title>BlitzMax variables are case-insensitive</title> <pubDate>Sat, 15 Sep 2018 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/blitzmax-variables/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/blitzmax-variables/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>Even though I’ve used BlitzMax for years, I only just realized that it doesn’t care about case when it comes to variables. I knew that local and global variables didn’t matter, but constant names are also case-insensitive.</p> <p>For example, the following will output “ONE”:</p> <div class="language-blitzmax highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Const</span> <span class="nv">my_constant</span><span class="p">:</span><span class="kt">Int</span> <span class="o">=</span> <span class="mi">1</span>

<span class="k">If</span> <span class="n">MY_CONSTANT</span> <span class="o">=</span> <span class="mi">1</span> <span class="k">Then</span> <span class="k">Print</span> <span class="s">"ONE"</span>
</code></pre></div></div> <p>The same result occurs even in <code class="highlighter-rouge">SuperStrict</code> mode.</p> ]]></description> </item> <item> <title>Converting values to booleans in PHP</title> <pubDate>Fri, 07 Sep 2018 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/convert-php-booleans/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/convert-php-booleans/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>PHP doesn’t have a specific function for converting data to booleans, but it does have <code class="highlighter-rouge">filter_var</code> which can be used to do the same thing.</p> <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">filter_var</span><span class="p">(</span><span class="nv">$value</span><span class="p">,</span> <span class="nx">FILTER_VALIDATE_BOOLEAN</span><span class="p">);</span>
</code></pre></div></div> <p>Passing a value to <code class="highlighter-rouge">filter_var</code> with the <code class="highlighter-rouge">FILTER_VALIDATE_BOOLEAN</code> flag will return true for the following values:</p> <ul> <li><code class="highlighter-rouge">true</code></li> <li><code class="highlighter-rouge">'true'</code></li> <li><code class="highlighter-rouge">1</code></li> <li><code class="highlighter-rouge">'1'</code></li> <li><code class="highlighter-rouge">'on'</code></li> <li><code class="highlighter-rouge">'yes'</code></li> </ul> <p>Anything else will return <code class="highlighter-rouge">false</code>.</p> ]]></description> </item> <item> <title>Importing a remote MySQL database into another</title> <pubDate>Tue, 21 Aug 2018 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/sync-remote-mysql-database/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/sync-remote-mysql-database/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>This is a very simple bash script that downloads a copy of a remote MySQL database to a temporary file, and then imports that into a local database.</p> <p>It can’t be used to import the local contents into the remote one (deliberately to prevent me from making mistakes). I use it to keep my local development copy of a site up-to-date with the production version.</p> <p><strong>Important:</strong> Running this script will OVERWRITE the contents of the local database.</p> <h2 id="configuration">Configuration</h2> <p>To use the script, replace the variables in the “Configuration” section with your own values.</p> <table class="table--striped table--fancy table--function-map"> <thead> <tr> <th>Variable</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td>SSH_USER</td> <td>The username to login to the remote site with.</td> </tr> <tr> <td>SSH_HOST</td> <td>The remote machine to connect to.</td> </tr> <tr> <td>REMOTE_DB_HOST</td> <td>The database host on the remote machine. Usually <code class="highlighter-rouge">localhost</code>.</td> </tr> <tr> <td>REMOTE_DB_NAME</td> <td>The remote database name.</td> </tr> <tr> <td>REMOTE_DB_USER</td> <td>The user to connect to the database as.</td> </tr> <tr> <td>REMOTE_DB_PW</td> <td>The remote database user’s password.</td> </tr> <tr> <td>LOCAL_DB_HOST</td> <td>The local database post. Usually <code class="highlighter-rouge">localhost</code>.`</td> </tr> <tr> <td>LOCAL_DB_NAME</td> <td>The local database name.</td> </tr> <tr> <td>LOCAL_DB_USER</td> <td>The local database user.</td> </tr> <tr> <td>LOCAL_DB_PW</td> <td>Password for the local database user.</td> </tr> </tbody> </table> <h2 id="code">Code</h2> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>

<span class="c"># ------------------------------</span>
<span class="c"># -- Configuration.</span>

<span class="nv">SSH_USER</span><span class="o">=</span><span class="s2">"&lt;value goes here&gt;"</span>
<span class="nv">SSH_HOST</span><span class="o">=</span><span class="s2">"&lt;value goes here&gt;"</span>

<span class="nv">REMOTE_DB_HOST</span><span class="o">=</span><span class="s2">"localhost"</span>
<span class="nv">REMOTE_DB_NAME</span><span class="o">=</span><span class="s2">"&lt;value goes here&gt;"</span>
<span class="nv">REMOTE_DB_USER</span><span class="o">=</span><span class="s2">"&lt;value goes here&gt;"</span>
<span class="nv">REMOTE_DB_PW</span><span class="o">=</span><span class="s2">"&lt;value goes here&gt;"</span>

<span class="nv">LOCAL_DB_HOST</span><span class="o">=</span><span class="s2">"localhost"</span>
<span class="nv">LOCAL_DB_NAME</span><span class="o">=</span><span class="s2">"&lt;value goes here&gt;"</span>
<span class="nv">LOCAL_DB_USER</span><span class="o">=</span><span class="s2">"&lt;value goes here&gt;"</span>
<span class="nv">LOCAL_DB_PW</span><span class="o">=</span><span class="s2">"&lt;value goes here&gt;"</span>

<span class="c"># ------------------------------</span>
<span class="c"># -- Syncing.</span>

<span class="c"># Remove any existing dumps.</span>
<span class="nb">rm</span> /tmp/<span class="nv">$REMOTE_DB_NAME</span>.sql

<span class="c"># Fetch the remote database.</span>
<span class="nb">echo</span> <span class="s1">'Fetching remote database'</span>
ssh <span class="nv">$SSH_USER</span>@<span class="nv">$SSH_HOST</span> <span class="s2">"mysqldump -u</span><span class="nv">$REMOTE_DB_USER</span><span class="s2"> --password='</span><span class="nv">$REMOTE_DB_PW</span><span class="s2">' -h </span><span class="nv">$REMOTE_DB_HOST</span><span class="s2"> </span><span class="nv">$REMOTE_DB_NAME</span><span class="s2">"</span> <span class="o">&gt;</span> /tmp/<span class="nv">$REMOTE_DB_NAME</span>.sql

<span class="c"># Load it into the local database.</span>
<span class="nb">echo</span> <span class="s1">'Importing database dump'</span>
mysql <span class="nt">-u</span><span class="nv">$LOCAL_DB_USER</span> <span class="nt">--password</span><span class="o">=</span><span class="nv">$LOCAL_DB_PW</span> <span class="nt">-h</span> <span class="nv">$LOCAL_DB_HOST</span> <span class="nv">$LOCAL_DB_NAME</span> &lt; /tmp/<span class="nv">$REMOTE_DB_NAME</span>.sql
</code></pre></div></div> ]]></description> </item> <item> <title>Formatting JSON with Ruby</title> <pubDate>Tue, 14 Aug 2018 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/formatting-json-with-ruby/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/formatting-json-with-ruby/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>Sometimes the JSON that’s received from a web service is hard to read. Ruby’s JSON module comes with a function to help:</p> <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">require</span> <span class="s1">'json'</span>

<span class="n">json</span> <span class="o">=</span> <span class="no">JSON</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="n">raw_text</span><span class="p">)</span>
<span class="nb">puts</span> <span class="no">JSON</span><span class="p">.</span><span class="nf">pretty_generate</span><span class="p">(</span><span class="n">json</span><span class="p">)</span>
</code></pre></div></div> <p>The <code class="highlighter-rouge">pretty_generate</code> function will add line breaks where needed and fix any alignment issues.</p> <p>Adding in syntax highlighting using <a href="https://github.com/jneen/rouge">rouge</a> requires only a few more steps:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>require 'json''
require 'rouge'

def prettify_json(raw_text)
  json = JSON.parse(raw_text)
  JSON.pretty_generate(json)
end

def highlight_json(text)
  formatter = Rouge::Formatters::HTML.new(css_class: 'highlight')
  lexer = Rouge::Lexer.find('json')
  formatter.format(lexer.lex(text))
end
</code></pre></div></div> <p>Calling <code class="highlighter-rouge">highlight_json</code> will return HTML markup to display json with syntax highlighting.</p> ]]></description> </item> <item> <title>Using the Emacs notifier with Guard</title> <pubDate>Thu, 02 Aug 2018 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/guard-emacs-notifier/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/guard-emacs-notifier/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><a href="https://guardgem.org/">Guard</a> is one of my favourite Ruby tools, especially when working on Rails projects.</p> <p>One of the most helpful features of Guard is the display of notifications to indicate a test’s success (or failure). There are a few different types available, but I find the popup ones to be a little annoying after a while.</p> <p>However, Guard comes with an Emacs notifier that changes the colour of the modeline depending on the result of the latest test. This makes getting feedback from tests extremely quick, and also means I don’t have to leave the editor.</p> <p>Adding the following to <code class="highlighter-rouge">.guard.rb</code> in your home directory will enable the Emacs notifier on the local machine.</p> <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">notification</span> <span class="ss">:emacs</span>
</code></pre></div></div> <p>The default colours didn’t work so well for my current theme (<a href="https://emacsthemes.com/themes/aurora-theme.html">aurora</a>), but thankfully Guard supports configuring colours:</p> <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">notification</span> <span class="ss">:emacs</span><span class="p">,</span>
  <span class="ss">fontcolor: </span><span class="s1">'#263238'</span><span class="p">,</span>
  <span class="ss">default:   </span><span class="s1">'#546d7a'</span><span class="p">,</span>
  <span class="ss">success:   </span><span class="s1">'#396c00'</span><span class="p">,</span>
  <span class="ss">failed:    </span><span class="s1">'#640900'</span><span class="p">,</span>
  <span class="ss">pending:   </span><span class="s1">'#776600'</span>
</code></pre></div></div> <p>Alternatively these can go in a <code class="highlighter-rouge">Guardfile</code>, but I prefer to leave notification settings up to individuals.</p> ]]></description> </item> <item> <title>Finding the longest value of a MySQL column</title> <pubDate>Sat, 23 Jun 2018 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/finding-longest-mysql-column-value/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/finding-longest-mysql-column-value/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>This came up during the rebuild of a very old legacy application. The previous app used <code class="highlighter-rouge">varchar(255)</code> for most columns, but this seemed a bit wasteful.</p> <p>To get a better idea of how large things needed to be in the new design, I wanted to know the the longest value stored for each column.</p> <p>Thankfully MySQL has the <code class="highlighter-rouge">length</code> function that can be used for this. The following query qill return a single result containing the longest value, as well as its length:</p> <div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">&lt;</span><span class="k">column</span><span class="o">&gt;</span><span class="p">,</span> <span class="k">LENGTH</span><span class="p">(</span><span class="o">&lt;</span><span class="k">column</span><span class="o">&gt;</span><span class="p">)</span> <span class="k">as</span> <span class="n">col_length</span> 
<span class="k">FROM</span> <span class="o">&lt;</span><span class="k">table</span><span class="o">&gt;</span> 
<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">col_length</span> <span class="k">DESC</span>
<span class="k">LIMIT</span> <span class="mi">1</span>
</code></pre></div></div> <p>Just replace <code class="highlighter-rouge">&lt;column&gt;</code> and <code class="highlighter-rouge">&lt;table&gt;</code> with the column and table name to query.</p> ]]></description> </item> <item> <title>Per-platform Emacs configuration</title> <pubDate>Thu, 03 May 2018 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/per-platform-emacs-config/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/per-platform-emacs-config/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>Synchronising Emacs configuration files between machines usually works well, but sometimes there need to be different settings for different operating system.</p> <p>Thankfully, Emacs lisp provides the variable <code class="highlighter-rouge">system-type</code>.</p> <p>For example, it can be used to set a different font depending on the os:</p> <div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Windows only font</span>
<span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">string=</span> <span class="s">"windows-nt"</span> <span class="nv">system-type</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">set-face-font</span> <span class="ss">'default</span> <span class="s">"Consolas"</span><span class="p">))</span>

<span class="c1">;; Mac OS only font</span>
<span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">string=</span> <span class="s">"darwin"</span> <span class="nv">system-type</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">set-face-font</span> <span class="ss">'default</span> <span class="s">"Monaco"</span><span class="p">))</span>
  
<span class="c1">;; Linux only font</span>
<span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">string=</span> <span class="s">"gnu/linux"</span> <span class="nv">system-type</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">set-face-font</span> <span class="ss">'default</span> <span class="s">"Ubuntu"</span><span class="p">))</span>
</code></pre></div></div> <p><strong>More info</strong>: <a href="https://www.gnu.org/software/emacs/manual/html%5Fnode/elisp/System-Environment.html">Gnu Emacs: Operating System Environment</a></p> ]]></description> </item> <item> <title>Overriding Ruby class constants</title> <pubDate>Sun, 08 Apr 2018 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/overriding-ruby-class-constants/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/overriding-ruby-class-constants/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I’ll preface this note with the disclaimer that you probably shouldn’t do this.</p> <p>I use org-mode to track time worked on projects, and I’ve been using <a href="https://github.com/bdewey/org-ruby">org-ruby</a> to extract the data to make graphs and things.</p> <p>One issue I’ve bumped into is that org-ruby hard-codes the list of keywords that can start a headline and only supports <code class="highlighter-rouge">TODO</code> and <code class="highlighter-rouge">DONE</code>. This meant some headlines got ignored and didn’t show up in reports.</p> <p>To get around this I needed to override the constants org-ruby uses. In the end I went with the following approach:</p> <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">##</span>
<span class="c1"># Monkey patch</span>
<span class="k">module</span> <span class="nn">Orgmode</span>
  <span class="k">class</span> <span class="nc">Headline</span>
    <span class="n">remove_const</span><span class="p">(</span><span class="ss">:Keywords</span><span class="p">)</span> <span class="k">if</span> <span class="k">defined?</span><span class="p">(</span><span class="no">Keywords</span><span class="p">)</span>
    <span class="n">remove_const</span><span class="p">(</span><span class="ss">:KeywordsRegexp</span><span class="p">)</span> <span class="k">if</span> <span class="k">defined?</span><span class="p">(</span><span class="no">KeywordsRegexp</span><span class="p">)</span>

    <span class="no">Keywords</span>       <span class="o">=</span> <span class="sx">%w[TODO IN-PROGRESS TESTING DONE CANCELLED]</span><span class="p">.</span><span class="nf">freeze</span>
    <span class="no">KeywordsRegexp</span> <span class="o">=</span> <span class="no">Regexp</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"^(</span><span class="si">#{</span><span class="no">Keywords</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s1">'|'</span><span class="p">)</span><span class="si">}</span><span class="s2">)</span><span class="se">\$</span><span class="s2">"</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Removing text properties from an Emacs buffer</title> <pubDate>Thu, 29 Mar 2018 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/removing-emacs-buffer-text-properties/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/removing-emacs-buffer-text-properties/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I wanted to write tests for <a href="/projects/blitzmax-mode/">blitzmax-mode</a> indentation to make sure everything worked correctly. The approach was something like this:</p> <ol> <li>Load a properly-formatted file into a buffer</li> <li>Enable the major mode for the buffer</li> <li>Indent the entire file</li> <li>Compare the indented buffer with the original file and fail the test if they don’t match</li> </ol> <p>The problem with the above approach is that <code class="highlighter-rouge">buffer-string</code> also returns formatting information for the buffer. This causes all comparisons to fail as the indented buffer contains highlight information.</p> <p>Luckily the solution is quite simple:</p> <div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">cleaned-buffer-string</span> <span class="p">()</span>
  <span class="s">"Get \"buffer-string\" without any fontification data."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">buffer</span> <span class="p">(</span><span class="nv">buffer-string</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">set-text-properties</span> <span class="mi">0</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">buffer</span><span class="p">)</span> <span class="no">nil</span> <span class="nv">buffer</span><span class="p">)</span>
    <span class="nv">buffer</span><span class="p">))</span>
</code></pre></div></div> <p>This returns the entire contents of the buffer as a clean string.</p> ]]></description> </item> <item> <title>Converting to (and from) snake case in Emacs</title> <pubDate>Thu, 18 Jan 2018 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/converting-to-snake-case-in-emacs/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/converting-to-snake-case-in-emacs/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><a href="https://github.com/akicho8/string-inflection">string-inflection</a> is a neat Emacs package that adds functionality to quickly switch text between <code class="highlighter-rouge">CamelCase</code>, <code class="highlighter-rouge">snake_case</code> and <code class="highlighter-rouge">kebab-case</code>.</p> <p>It adds functions that can be called using <code class="highlighter-rouge">M-x</code> or bound to a shortcut. All of them can select the word at the current point, so no region needs to be marked before using them.</p> <h2 id="conversion-functions">Conversion Functions</h2> <h3 id="string-inflection-upcase"><code class="highlighter-rouge">string-inflection-upcase</code></h3> <p>Converts text to <code class="highlighter-rouge">UPPER_SNAKE_CASE</code>.</p> <ul> <li><code class="highlighter-rouge">ExampleName</code> becomes <code class="highlighter-rouge">EXAMPLE_NAME</code></li> <li><code class="highlighter-rouge">another-name</code> becomes <code class="highlighter-rouge">ANOTHER_NAME</code></li> </ul> <h3 id="string-inflection-camelcase"><code class="highlighter-rouge">string-inflection-camelcase</code></h3> <p>Converts text to <code class="highlighter-rouge">CamelCase</code>.</p> <ul> <li><code class="highlighter-rouge">EXAMPLE_NAME</code> becomes <code class="highlighter-rouge">ExampleName</code></li> <li><code class="highlighter-rouge">another-name</code> becomes <code class="highlighter-rouge">AnotherName</code></li> </ul> <h3 id="string-inflection-underscore"><code class="highlighter-rouge">string-inflection-underscore</code></h3> <p>Converts text to <code class="highlighter-rouge">underscore_case</code>. Pretty much the same as <code class="highlighter-rouge">string-inflection-upcase</code> but with lowercase letters.</p> <ul> <li><code class="highlighter-rouge">ExampleName</code> becomes <code class="highlighter-rouge">example_name</code></li> <li><code class="highlighter-rouge">another-name</code> becomes <code class="highlighter-rouge">another_name</code></li> </ul> <h3 id="string-inflection-kebab-case"><code class="highlighter-rouge">string-inflection-kebab-case</code></h3> <p>Converts text to <code class="highlighter-rouge">kebab-case</code>. Also known as <code class="highlighter-rouge">lisp-case</code> or <code class="highlighter-rouge">dash-case</code>.</p> <ul> <li><code class="highlighter-rouge">ExampleName</code> becomes <code class="highlighter-rouge">example-name</code></li> <li><code class="highlighter-rouge">ANOTHER_NAME</code> becomes <code class="highlighter-rouge">another-name</code></li> </ul> <h3 id="string-inflection-lower-camelcase"><code class="highlighter-rouge">string-inflection-lower-camelcase</code></h3> <p>Converts to <code class="highlighter-rouge">lowerCamelCase</code>.</p> <ul> <li><code class="highlighter-rouge">EXAMPLE_NAME</code> becomes <code class="highlighter-rouge">exampleName</code></li> <li><code class="highlighter-rouge">another-name</code> becomes <code class="highlighter-rouge">anotherName</code></li> </ul> <h2 id="cycling-cases">Cycling Cases</h2> <p>There are a few additional functions that cycle between cases.</p> <h3 id="string-inflection-ruby-style-cycle"><code class="highlighter-rouge">string-inflection-ruby-style-cycle</code></h3> <p>Cycles between:</p> <ul> <li>Lower snake case</li> <li>Upper snake case</li> <li>Upper camel case</li> </ul> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>emacs_lisp =&gt; EMACS_LISP =&gt; EmacsLisp =&gt; emacs_lisp
</code></pre></div></div> <h3 id="string-inflection-python-style-cycle"><code class="highlighter-rouge">string-inflection-python-style-cycle</code></h3> <p>Cycles between:</p> <ul> <li>Lower snake case</li> <li>Upper snake case</li> <li>Upper camel case</li> </ul> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>emacs_lisp =&gt; EMACS_LISP =&gt; EmacsLisp =&gt; emacs_lisp
</code></pre></div></div> <h3 id="string-inflection-java-style-cycle"><code class="highlighter-rouge">string-inflection-java-style-cycle</code></h3> <p>Cycles between:</p> <ul> <li>Lower camel case</li> <li>Upper snake case</li> <li>Upper camel case</li> </ul> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>emacsLisp =&gt; EMACS_LISP =&gt; EmacsLisp =&gt; emacsLisp
</code></pre></div></div> <h3 id="string-inflection-all-cycle"><code class="highlighter-rouge">string-inflection-all-cycle</code></h3> <p>Cycles between all available cases:</p> <ul> <li>Lower snake case</li> <li>Upper snake case</li> <li>Upper camel case</li> <li>Lower camel case</li> <li>Kebab case</li> </ul> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>emacs_lisp =&gt; EMACS_LISP =&gt; EmacsLisp =&gt; emacsLisp =&gt; emacs-lisp =&gt; emacs_lisp
</code></pre></div></div> <hr/> <p class="project-information"> <a href="https://github.com/akicho8/string-inflection" class="button"> View string-inflection on GitHub </a> </p> ]]></description> </item> <item> <title>Aligning PHP arrays with Emacs</title> <pubDate>Tue, 16 Jan 2018 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/aligning-php-arrays-with-emacs/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/aligning-php-arrays-with-emacs/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<aside class="aside aside--info" role="complementary"> <h3 id="note">Note</h3> <p><code>emacs-php-align</code> has been merged into the main <a href="https://github.com/emacs-php/php-mode"><code>php-mode</code></a> extension.</p> </aside> <p>PHP doesn’t require arrays to be aligned in a specific way, but certain coding standards will raise a warning if they’re aren’t aligned correctly. Doing this by hand can be a pain.</p> <p><a href="https://github.com/tetsujin/emacs-php-align">emacs-php-align</a> is a small extension that can automatically align arrays. It’s not available on Melpa, but it’s fairly quick to setup.</p> <p>Once it’s installed, calling <code class="highlighter-rouge">M-x align-current</code> will align an array and turn this:</p> <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$my_array</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
    <span class="s1">'key'</span> <span class="o">=&gt;</span> <span class="s1">'Value'</span><span class="p">,</span>
    <span class="s1">'key_two'</span> <span class="o">=&gt;</span> <span class="s1">'Another value'</span><span class="p">,</span>
    <span class="s1">'really_long_key'</span> <span class="o">=&gt;</span> <span class="s1">'Value'</span><span class="p">,</span>
    <span class="s1">'k'</span> <span class="o">=&gt;</span> <span class="s1">'Value'</span><span class="p">,</span>
<span class="p">);</span>
</code></pre></div></div> <p>into this:</p> <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$my_array</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
    <span class="s1">'key'</span>             <span class="o">=&gt;</span> <span class="s1">'Value'</span><span class="p">,</span>
    <span class="s1">'key_two'</span>         <span class="o">=&gt;</span> <span class="s1">'Another value'</span><span class="p">,</span>
    <span class="s1">'really_long_key'</span> <span class="o">=&gt;</span> <span class="s1">'Value'</span><span class="p">,</span>
    <span class="s1">'k'</span>               <span class="o">=&gt;</span> <span class="s1">'Value'</span><span class="p">,</span>
<span class="p">);</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Using multiple SSH keys with GitHub</title> <pubDate>Wed, 20 Dec 2017 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/multiple-github-keys/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/multiple-github-keys/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>I have a couple of different accounts for GitHub<sup id="fnref:1"><a href="#fn:1" class="footnote">1</a></sup> - one for my personal projects, and one for work. GitHub doesn’t allow the same SSH key to be used on different accounts which can make working with repositories difficult.</p> <p>For example, cloning a private repository from one account may not work, even if both keys are currently being used by the SSH agent.</p> <p>To workaround this limitation, the SSH agent can be configured to use a specific key when accessing a domain. In this case the same domain requires different keys, so an alias is used instead.</p> <p>This alias needs to be used when checking out repositories, but once the initial step is complete everything else happens automatically.</p> <p>Modifying <code class="highlighter-rouge">~/.ssh/config</code> with the following:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Work GitHub Account
Host github.com-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/work_public_key
</code></pre></div></div> <p>Will now tell the SSH agent to use <code class="highlighter-rouge">~/.ssh/work_public_key</code> when trying to access anything on <code class="highlighter-rouge">github.com-work</code>.</p> <h2 id="cloning-a-repository">Cloning a repository</h2> <p>To use the alias when cloning a reposiory, replace <code class="highlighter-rouge">github.com</code> with the configured alias.</p> <p>For example, cloning the <code class="highlighter-rouge">ruby</code> repository with the work alias from earlier looks like this:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone git@github.com-work:ruby/ruby.git
</code></pre></div></div> <p>Standard git commands like <code class="highlighter-rouge">git push</code> will work just the same as any other repository.</p> <h2 id="existing-repositories">Existing repositories</h2> <p>To update an existing repository to use a new alias, modify the <code class="highlighter-rouge">.git/config</code> file in the project’s working directory. It should look something like this:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[remote "origin"]
	url = git@github.com-work:ruby/ruby.git

</code></pre></div></div> <div class="footnotes"> <ol> <li id="fn:1"> <p>This solution also works with BitBucket. <a href="#fnref:1" class="reversefootnote">&#8617;</a></p> </li> </ol> </div> ]]></description> </item> <item> <title>Middle-click scrolling on Linux Firefox</title> <pubDate>Tue, 17 Oct 2017 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/auto-scrolling-in-firefox/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/auto-scrolling-in-firefox/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>After upgrading to Ubuntu 16.04 I noticed my usual middle-click behaviour on Firefox had changed - instead of enabling auto-scroll it was attempting to navigate to strange urls.</p> <p>Normally Ubuntu will try to paste the contents of the clipboard when you click your middle mouse button. If you’re currently in Firefox and you do this it will try to open what you pasted as a URL.</p> <p>To revert to middle-click scrolling:</p> <ol> <li> <p>Go the the advanced preferences page. To get there, type <code class="highlighter-rouge">about:config</code> in the Address Bar and hit enter.</p> </li> <li>In the preferences search bar type <code class="highlighter-rouge">middlemouse</code> <ol> <li>Change <code class="highlighter-rouge">middlemouse.contentLoadURL</code> to <code class="highlighter-rouge">false</code>.</li> <li>Change <code class="highlighter-rouge">middlemouse.paste</code> to <code class="highlighter-rouge">false</code>.</li> </ol> </li> <li>Type <code class="highlighter-rouge">autoScroll</code> into the preferences search bar. <ol> <li>Change <code class="highlighter-rouge">general.autoScroll</code> to <code class="highlighter-rouge">true</code>.</li> </ol> </li> <li>Close the browser and restart.</li> </ol> <p>Middle-click scrolling will now be enabled again.</p> ]]></description> </item> <item> <title>Showing a list of git branches with their last commit date</title> <pubDate>Wed, 24 May 2017 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/showing-git-branches-with-dates/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/showing-git-branches-with-dates/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>Over time a git repository can end up with a lot of feature branches. Most of these are not much use once they’ve been merged into the main branch.</p> <p>The following command shows a list of all local branch names, along with the date of their last commit:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git <span class="k">for</span><span class="nt">-each-ref</span> <span class="nt">--sort</span><span class="o">=</span>committerdate refs/heads/ <span class="nt">--format</span><span class="o">=</span><span class="s1">'%(committerdate:short) %(refname:short)'</span>
</code></pre></div></div> <p>Produces output like:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>2015-10-12 feature-branch-name
2016-01-15 another-feature-branch
2016-03-16 one-last-feature-branch
2017-05-24 master
</code></pre></div></div> ]]></description> </item> <item> <title>Formatting JSON from the command line with Python</title> <pubDate>Wed, 19 Apr 2017 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/formatting-json-with-python/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/formatting-json-with-python/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>This is a really quick way to format JSON nicely. Calling <code class="highlighter-rouge">python -m json.tool</code> with a filename argument will fix any indentation issues in the file and output the result.</p> <p>For example, a file called <em>my_file.json</em> with the following contents:</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"some_field"</span><span class="w"> </span><span class="p">:</span><span class="w">
</span><span class="s2">"value"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div> <p>When called like this:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python <span class="nt">-m</span> json.tool my_file.json
</code></pre></div></div> <p>Will output:</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"some_field"</span><span class="p">:</span><span class="w"> </span><span class="s2">"value"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div> ]]></description> </item> <item> <title>Adding a trailing slash to all urls in Rails</title> <pubDate>Thu, 13 Apr 2017 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/rails-trailing-slashes/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/rails-trailing-slashes/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>Add the following to the <code class="highlighter-rouge">Application</code> class in <code class="highlighter-rouge">config/application.rb</code>:</p> <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">default_url_options</span><span class="p">[</span><span class="ss">:trailing_slash</span><span class="p">]</span> <span class="o">=</span> <span class="kp">true</span>
</code></pre></div></div> <p>For example, the application <code class="highlighter-rouge">MyApplicationName</code> will look something like this:</p> <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">module</span> <span class="nn">MyApplicationName</span>
  <span class="k">class</span> <span class="nc">Application</span> <span class="o">&lt;</span> <span class="no">Rails</span><span class="o">::</span><span class="no">Application</span>
    <span class="n">default_url_options</span><span class="p">[</span><span class="ss">:trailing_slash</span><span class="p">]</span> <span class="o">=</span> <span class="kp">true</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div> <p>The Rails server will need restarting for the new settings to take effect.</p> <p>This solution works for Rails 5 and will add a trailing slash to all urls automatically.</p> ]]></description> </item> <item> <title>Emacs Lisp - Loading a custom configuration file</title> <pubDate>Thu, 09 Mar 2017 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/emacs-lisp-custom-config/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/emacs-lisp-custom-config/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><code class="highlighter-rouge">.dir-locals.el</code> is a great way to store directory-specific configuration values. However you don’t always want to clog it up when writing a custom extension.</p> <p>This function searches a directory (and its parents) for a named file. The file is loaded if found. An error is raised if the file is not found.</p> <p>For the <code class="highlighter-rouge">sodaware/file-search-upward</code> function see “<a href="/notes/emacs-lisp-find-file-upwards/">Emacs Lisp - Searching parent folders for a file</a>”.</p> <div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/load-custom-config</span> <span class="p">(</span><span class="nv">filename</span> <span class="nb">directory</span><span class="p">)</span>
  <span class="s">"Loads a configuration FILENAME from DIRECTORY.

If not found in the current directory, will search upwards until one is found."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">config-file-path</span> <span class="p">(</span><span class="nv">sodaware/file-search-upward</span> <span class="nb">directory</span> <span class="nv">filename</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nb">and</span> <span class="nv">config-file-path</span>
                 <span class="p">(</span><span class="nv">file-exists-p</span> <span class="nv">config-file-path</span><span class="p">))</span>
      <span class="p">(</span><span class="nb">error</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"Could not find configuration file '%s'"</span> <span class="nv">filename</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">message</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"Loading configuration file: %s"</span> <span class="nv">config-file-path</span><span class="p">))</span>
    <span class="p">(</span><span class="nv">load-file</span> <span class="nv">config-file-path</span><span class="p">)))</span>
</code></pre></div></div> <h2 id="example-usage">Example usage</h2> <h3 id="1-loading-a-configuration">1. Loading a configuration</h3> <p>Assuming <code class="highlighter-rouge">.config.el</code> exists in <code class="highlighter-rouge">/some/dir/</code>:</p> <div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">sodaware/load-custom-config</span> <span class="s">".config.el"</span> <span class="s">"/some/dir/"</span><span class="p">)</span>
<span class="nv">=&gt;</span> <span class="no">t</span>
</code></pre></div></div> <p>Assuming <code class="highlighter-rouge">.invalid.el</code> does not exist in <code class="highlighter-rouge">/some/dir/</code>:</p> <div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">sodaware/load-custom-config</span> <span class="s">".invalid.el"</span> <span class="s">"/some/dir/"</span><span class="p">)</span>
<span class="c1">;; =&gt; Could not find configuration file '.bad.el'</span>
</code></pre></div></div> <h3 id="2-loading-a-configuration-based-on-the-current-file">2. Loading a configuration based on the current file</h3> <p>Emacs provides the variable <code class="highlighter-rouge">buffer-file-name</code> which contains the full path of the currently edited buffer.</p> <p>This example searches for a configuration file using the current buffer’s path:</p> <div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">sodaware/load-custom-config</span> <span class="s">".config.el"</span> <span class="p">(</span><span class="nv">file-name-directory</span> <span class="nv">buffer-file-name</span><span class="p">))</span>
</code></pre></div></div> <h2 id="without-error-raising">Without error raising</h2> <p>This is a modified version of the original function. It still searches parent directories for the configuration file, but will return <code class="highlighter-rouge">NIL</code> if the file is not found instead of raising an error.</p> <div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/load-custom-config</span> <span class="p">(</span><span class="nv">filename</span> <span class="nb">directory</span><span class="p">)</span>
  <span class="s">"Loads a configuration FILENAME from DIRECTORY.

If not found in the current directory, will search upwards until one is found."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">config-file-path</span> <span class="p">(</span><span class="nv">sodaware/file-search-upward</span> <span class="nb">directory</span> <span class="nv">filename</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">and</span> <span class="nv">config-file-path</span>
               <span class="p">(</span><span class="nv">file-exists-p</span> <span class="nv">config-file-path</span><span class="p">))</span>
      <span class="p">(</span><span class="nv">load-file</span> <span class="nv">config-file-path</span><span class="p">))))</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Emacs Lisp - Searching parent folders for a file</title> <pubDate>Wed, 08 Mar 2017 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/emacs-lisp-find-file-upwards/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/emacs-lisp-find-file-upwards/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>This code searches a directory for a filename. If the file is not found, the parent directory is searched. It continues searching upwards until the file is found or there are no more directories to search.</p> <p>If the file is found its full path is returned, otherwise <code class="highlighter-rouge">NIL</code> is returned.</p> <div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/file-search-upward</span> <span class="p">(</span><span class="nb">directory</span> <span class="nv">file</span><span class="p">)</span>
  <span class="s">"Search DIRECTORY for FILE and return its full path if found, or NIL if not.

If FILE is not found in DIRECTORY, the parent of DIRECTORY will be searched."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">parent-dir</span> <span class="p">(</span><span class="nv">file-truename</span> <span class="p">(</span><span class="nv">concat</span> <span class="p">(</span><span class="nv">file-name-directory</span> <span class="nb">directory</span><span class="p">)</span> <span class="s">"../"</span><span class="p">)))</span>
        <span class="p">(</span><span class="nv">current-path</span> <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">not</span> <span class="p">(</span><span class="nb">string=</span> <span class="p">(</span><span class="nv">substring</span> <span class="nb">directory</span> <span class="p">(</span><span class="nb">-</span> <span class="p">(</span><span class="nb">length</span> <span class="nb">directory</span><span class="p">)</span> <span class="mi">1</span><span class="p">))</span> <span class="s">"/"</span><span class="p">))</span>
                         <span class="p">(</span><span class="nv">concat</span> <span class="nb">directory</span> <span class="s">"/"</span> <span class="nv">file</span><span class="p">)</span>
                         <span class="p">(</span><span class="nv">concat</span> <span class="nb">directory</span> <span class="nv">file</span><span class="p">))))</span>
    <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nv">file-exists-p</span> <span class="nv">current-path</span><span class="p">)</span>
        <span class="nv">current-path</span>
        <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nb">not</span> <span class="p">(</span><span class="nb">string=</span> <span class="p">(</span><span class="nv">file-truename</span> <span class="nb">directory</span><span class="p">)</span> <span class="nv">parent-dir</span><span class="p">))</span>
                   <span class="p">(</span><span class="nb">&lt;</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">parent-dir</span><span class="p">)</span> <span class="p">(</span><span class="nb">length</span> <span class="p">(</span><span class="nv">file-truename</span> <span class="nb">directory</span><span class="p">))))</span>
          <span class="p">(</span><span class="nv">sodaware/file-search-upward</span> <span class="nv">parent-dir</span> <span class="nv">file</span><span class="p">)))))</span>
</code></pre></div></div> <h2 id="example-usage">Example usage</h2> <p>Given the following directory structure:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>|-- dir1
    |-- my_file.txt
    |-- dir2
        |-- dir3
</code></pre></div></div> <p>Searching <code class="highlighter-rouge">dir3</code> will also search <code class="highlighter-rouge">dir2</code> and <code class="highlighter-rouge">dir1</code>:</p> <div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Finding a file that exists in a parent directory.</span>
<span class="p">(</span><span class="nv">sodaware/file-search-upward</span> <span class="s">"/dir1/dir2/dir3/"</span> <span class="s">"my_file.txt"</span><span class="p">)</span>
<span class="nv">=&gt;</span> <span class="s">"/dir1/my_file.txt"</span>

<span class="c1">;; Failing to find a file.</span>
<span class="p">(</span><span class="nv">sodaware/file-search-upward</span> <span class="s">"/dir1/dir2/dir3/"</span> <span class="s">"not_found.txt"</span><span class="p">)</span>
<span class="nv">=&gt;</span> <span class="nv">NIL</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Marking all items as read in elfeed</title> <pubDate>Wed, 15 Feb 2017 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/elfeed-all-as-read/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/elfeed-all-as-read/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><a href="https://github.com/skeeto/elfeed">Elfeed</a> is an excellent RSS reader for Emacs. Recently <a href="https://github.com/skeeto/elfeed/issues/197">this issue on GitHub</a> asked how to add a yes/no prompt before marking all items as read.</p> <p>Here’s a simple function that marks all RSS items as read before fetching new posts:</p> <div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/elfeed-all-read-refresh</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">y-or-n-p</span> <span class="s">"Really mark all items as read?"</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">elfeed-mark-all-as-read</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">elfeed-search-fetch</span> <span class="no">nil</span><span class="p">)))</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Extracting org-mode data with Ruby</title> <pubDate>Wed, 11 Jan 2017 00:00:00 -0500</pubDate> <link>http://sodaware.sdf.org/notes/extracting-org-data-with-ruby/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/extracting-org-data-with-ruby/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><a href="https://github.com/bdewey/org-ruby"><strong>org-ruby</strong></a> is a Ruby gem that can be used to parse <code class="highlighter-rouge">org-mode</code> files. It’s not as robust as using Emacs itself, but sometimes a quick script is all that’s needed to extract a couple of bits of data</p> <p>The following code will read an <code class="highlighter-rouge">org-mode</code> file and list all major headlines:</p> <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">require</span> <span class="s1">'org-ruby'</span>
<span class="n">document</span> <span class="o">=</span> <span class="no">Orgmode</span><span class="o">::</span><span class="no">Parser</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">File</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="s1">'TODO.org'</span><span class="p">))</span>

<span class="n">document</span><span class="p">.</span><span class="nf">headlines</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">headline</span><span class="o">|</span>
  <span class="nb">puts</span> <span class="n">headline</span><span class="p">.</span><span class="nf">headline_text</span>
<span class="k">end</span>
</code></pre></div></div> <p>Here’s a more advanced example. This will read all headlines that are marked as “DONE” along with any list items they contain.</p> <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">require</span> <span class="s1">'org-ruby'</span>
<span class="n">document</span> <span class="o">=</span> <span class="no">Orgmode</span><span class="o">::</span><span class="no">Parser</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">File</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="s1">'TODO.org'</span><span class="p">))</span>

<span class="n">doc</span><span class="p">.</span><span class="nf">headlines</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">headline</span><span class="o">|</span>
  <span class="k">next</span> <span class="k">unless</span> <span class="n">headline</span><span class="p">.</span><span class="nf">keyword</span> <span class="o">==</span> <span class="s1">'DONE'</span>

  <span class="nb">puts</span> <span class="n">headline</span><span class="p">.</span><span class="nf">headline_text</span>

  <span class="n">headline</span><span class="p">.</span><span class="nf">body_lines</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">line</span><span class="o">|</span>
    <span class="k">next</span> <span class="k">if</span> <span class="n">line</span><span class="p">.</span><span class="nf">nil?</span>
    <span class="k">next</span> <span class="k">unless</span> <span class="n">line</span><span class="p">.</span><span class="nf">paragraph_type</span> <span class="o">==</span> <span class="ss">:list_item</span>

    <span class="n">task_line</span> <span class="o">=</span> <span class="n">line</span><span class="p">.</span><span class="nf">output_text</span><span class="p">.</span><span class="nf">strip</span>
    <span class="nb">puts</span> <span class="s1">' -&gt; '</span> <span class="o">+</span> <span class="n">task_line</span><span class="p">[</span><span class="mi">4</span><span class="o">..-</span><span class="mi">1</span><span class="p">]</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div> <p>Using this file:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#+TITLE: TODO.org
DONE Top Level Task 1
  - [X] Checkbox one
  - [X] Checkbox two
TODO Top Level Task 2
  - [ ] Checkbox three
</code></pre></div></div> <p>will output:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Top Level Task 1
 -&gt; Checkbox one
 -&gt; Checkbox two
</code></pre></div></div> <hr/> <p>The <a href="https://www.sodaware.net/1gam-2017/01-mini-shinobi/">Mini Shinobi development page</a> is a good example of what this can be used to create. The “daily activity” and “milestones” sections are both built entirely using org data.</p> ]]></description> </item> <item> <title>Automatic .emacs recompilation</title> <pubDate>Mon, 31 Oct 2016 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/automatic-dot-emacs-recompilation/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/automatic-dot-emacs-recompilation/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>Byte-compiled Elisp files run faster. This snippet will automatically recompile <code class="highlighter-rouge">~/.emacs</code> when it’s saved in the editor.</p> <div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/autocompile-emacs-configuration</span> <span class="p">()</span>
  <span class="s">"Automatically compile changes to ~/.emacs"</span>
  <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">eq</span> <span class="nv">major-mode</span> <span class="ss">'emacs-lisp-mode</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">sodaware/compile-elisp-file</span> <span class="s">"~/emacs"</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/compile-elisp-file</span> <span class="p">(</span><span class="nv">file-name</span><span class="p">)</span>
  <span class="s">"Byte-compile FILE-NAME if it exists."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">elisp-file</span> <span class="p">(</span><span class="nv">expand-file-name</span> <span class="nv">file-name</span><span class="p">)))</span>
    <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">string=</span> <span class="p">(</span><span class="nv">buffer-file-name</span><span class="p">)</span> <span class="p">(</span><span class="nv">file-chase-links</span> <span class="nv">elisp-file</span><span class="p">))</span>
        <span class="p">(</span><span class="nv">byte-compile-file</span> <span class="nv">elisp-file</span><span class="p">))))</span>

<span class="c1">;; Run the auto-compile function when an Elisp file is saved</span>
<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-save-hook</span> <span class="nf">#'</span><span class="nv">sodaware/autocompile-emacs-configuration</span><span class="p">)</span>
</code></pre></div></div> <p>I have a couple of different files in my <code class="highlighter-rouge">~/.emacs.d/</code> directory, but it’s easy to modify the <code class="highlighter-rouge">sodaware/autocompile-emacs-configuration</code> function to support multiple files:</p> <div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">sodaware/autocompile-emacs-configuration</span> <span class="p">()</span>
  <span class="s">"Automatically compile changes to ~/.emacs"</span>
  <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">eq</span> <span class="nv">major-mode</span> <span class="ss">'emacs-lisp-mode</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">mapc</span> <span class="nf">#'</span><span class="nv">sodaware/compile-elisp-file</span>
          <span class="p">(</span><span class="nb">list</span> <span class="s">"~/.emacs"</span>
                <span class="s">"~/.emacs.d/init.el"</span>
                <span class="s">"~/.emacs.d/my-email.el"</span>
                <span class="c1">;; ... and more</span>
                <span class="s">"~/.emacs.d/my-news.el"</span><span class="p">))))</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Two great ParEdit guides</title> <pubDate>Thu, 20 Oct 2016 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/paredit/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/paredit/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><a href="https://www.emacswiki.org/emacs/ParEdit">Paredit</a> is an Emacs extension for working with parenthesis and S-expressions.</p> <p>From the ParEdit page:</p> <blockquote> <p>ParEdit (paredit.el) is a minor mode for performing structured editing of S-expression data. The typical example of this would be Lisp or Scheme source code.</p> <p>ParEdit helps <strong>keep parentheses balanced</strong> and adds many keys for moving S-expressions and moving around in S-expressions.</p> </blockquote> <p>Seeing it in action makes it much clearer how useful it is. Here’s two great visual guides to ParEdit and what it can do:</p> <ol> <li><a href="http://emacsrocks.com/e14.html">Emacs Rocks! Paredit</a></li> <li><a href="http://danmidwood.com/content/2014/11/21/animated-paredit.html">The Animated Guide to Paredit</a></li> </ol> <p>Like most things Emacs, it takes a while to get used to. But once over the initial learning curve it’s indespensible.</p> ]]></description> </item> <item> <title>Installing Roswell on CentOS</title> <pubDate>Tue, 27 Sep 2016 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/roswell-on-centos/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/roswell-on-centos/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p><a href="https://github.com/roswell/roswell">Roswell</a> is a command line tool used to install and manage Common Lisp implementations. It’s similar to Ruby’s <a href="https://rvm.io/">rvm</a> and Python’s <a href="https://github.com/yyuu/pyenv">pyenv</a>.</p> <p>There are some binaries available, but none for CentOS. The following will get Roswell up and running on a fresh CentOS 7.2 installation:</p> <h2 id="setting-up-centos">Setting up CentOS</h2> <p>Run the following as <code class="highlighter-rouge">root</code> to install dependencies required for building Roswell:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yum <span class="nb">install </span>git automake gcc gcc-c++ make openssl-devel curl-devel bzip2
</code></pre></div></div> <h2 id="fetching-and-installing-roswell">Fetching and installing Roswell</h2> <p>These can be run as any user:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone <span class="nt">-b</span> release https://github.com/roswell/roswell.git
<span class="nb">cd </span>roswell
sh bootstrap
./configure
make
</code></pre></div></div> <p>And as <code class="highlighter-rouge">root</code></p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make <span class="nb">install</span>
</code></pre></div></div> <p>And finally (as the original user)…</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ros setup
</code></pre></div></div> <p>Roswell will now be installed and available globally.</p> <h2 id="installing-and-running-a-lisp">Installing and running a Lisp</h2> <p>To install a Lisp binary, such as SBCL, run:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ros install sbcl-bin
</code></pre></div></div> <p>SBCL can then be started using <code class="highlighter-rouge">ros run</code>.</p> ]]></description> </item> <item> <title>Using multiple configuration files with Jekyll</title> <pubDate>Sun, 25 Sep 2016 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/jekyll-multiple-configs/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/jekyll-multiple-configs/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>When building this site I wanted to use <code class="highlighter-rouge">jekyll-minifier</code> to keep the page size small. However, it increases the build time significantly which is a pain during development.</p> <p>Thankfully Jekyll can accept multiple configuration files at a time.</p> <p>The following command will start a Jekyll server with the standard <code class="highlighter-rouge">_config.yml</code> configuration as well as <code class="highlighter-rouge">_config.development.yml</code>.</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bundle <span class="nb">exec </span>jekyll serve <span class="nt">--drafts</span> <span class="nt">--watch</span> <span class="nt">--config</span><span class="o">=</span>_config.yml,_config.development.yml
</code></pre></div></div> <p>Anything in the <em>development</em> configuration will override the base values in <code class="highlighter-rouge">_config.yml</code>.</p> <h2 id="examples">Examples</h2> <p>The production &amp; development configurations for this site look like this:</p> <p><strong>_config.production.yml</strong></p> <div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">gems</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="s">jekyll-minifier</span>
</code></pre></div></div> <p><strong>_config.development.yml</strong></p> <div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">livereload</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">gems</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="s">jekyll-livereload</span>
</code></pre></div></div> <p>Cutting <code class="highlighter-rouge">jekyll-minifier</code> from development cuts page generation times from 10 seconds to about 0.8. Coupled with <code class="highlighter-rouge">jekyll-livereload</code> it makes previewing site changes much easier.</p> <h2 id="updated-makefile">Updated Makefile</h2> <p>This changes the build and serve parts of the Makefile<sup id="fnref:1"><a href="#fn:1" class="footnote">1</a></sup> to look like this:</p> <div class="language-make highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">build</span><span class="o">:</span>
	bundle <span class="nb">exec </span>jekyll build <span class="nt">--config</span><span class="o">=</span>_config.yml,_config.production.yml

<span class="nl">serve</span><span class="o">:</span>
	bundle <span class="nb">exec </span>jekyll serve <span class="nt">--drafts</span> <span class="nt">--watch</span> <span class="nt">--config</span><span class="o">=</span>_config.yml,_config.development.yml
</code></pre></div></div> <div class="footnotes"> <ol> <li id="fn:1"> <p>See <a href="/notes/jekyll-makefile/">A simple Jekyll deployment Makefile</a> <a href="#fnref:1" class="reversefootnote">&#8617;</a></p> </li> </ol> </div> ]]></description> </item> <item> <title>Common Lisp: Convert a list into an alist</title> <pubDate>Mon, 19 Sep 2016 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/convert-list-to-alist/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/convert-list-to-alist/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>This function converts a list of values into an association list (alist).</p> <div class="language-common-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">list-&gt;alist</span> <span class="p">(</span><span class="nv">items</span><span class="p">)</span>
  <span class="s">"Convert a list into an alist."</span>
  <span class="p">(</span><span class="nb">loop</span> <span class="nv">for</span> <span class="nv">item</span> <span class="nv">from</span> <span class="mi">0</span> <span class="nv">to</span> <span class="p">(</span><span class="nb">1-</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">items</span><span class="p">))</span> <span class="nv">by</span> <span class="mi">2</span>
     <span class="nv">for</span> <span class="nv">key</span> <span class="nb">=</span> <span class="p">(</span><span class="nb">nth</span> <span class="nv">item</span> <span class="nv">items</span><span class="p">)</span>
     <span class="nv">for</span> <span class="nv">data</span> <span class="nb">=</span> <span class="p">(</span><span class="nb">nth</span> <span class="p">(</span><span class="nb">1+</span> <span class="nv">item</span><span class="p">)</span> <span class="nv">items</span><span class="p">)</span>
     <span class="nb">nconc</span> <span class="p">(</span><span class="nb">acons</span> <span class="nv">key</span> <span class="nv">data</span> <span class="no">nil</span><span class="p">)))</span>
</code></pre></div></div> <h2 id="basic-example">Basic example</h2> <p>Running <code class="highlighter-rouge">list-&gt;alist</code> on this input:</p> <div class="language-common-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">list</span> <span class="ss">:key1</span> <span class="s">"value1"</span> <span class="ss">:key2</span> <span class="s">"value2"</span> <span class="ss">:key3</span> <span class="s">"value3"</span><span class="p">)</span>
</code></pre></div></div> <p>produces the following output:</p> <div class="language-common-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">((</span><span class="ss">:key1</span> <span class="o">.</span> <span class="s">"value1"</span><span class="p">)</span>
 <span class="p">(</span><span class="ss">:key2</span> <span class="o">.</span> <span class="s">"value2"</span><span class="p">)</span>
 <span class="p">(</span><span class="ss">:key3</span> <span class="o">.</span> <span class="s">"value3"</span><span class="p">))</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Extracting a PHP function with Emacs Lisp</title> <pubDate>Thu, 15 Sep 2016 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/emacs-extract-php-function/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/emacs-extract-php-function/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>This snippet moves the currently selected region to a new function and replaces it with a call to that function. It’s not meant for heavy refactoring but it’s ok for quick bits of code cleanup.</p> <p><img src="/assets/images/php-extract-function.gif" alt="Terrible Example" class="centered bordered"/></p> <p>A little bit of work needs to be done after extracting code, but it’s slightly quicker than doing the whole thing manually.</p> <div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">php-extract-function</span> <span class="p">(</span><span class="nv">start</span> <span class="nv">end</span> <span class="nv">name</span><span class="p">)</span>
  <span class="s">"Moves the currently marked text to a new function"</span>

  <span class="c1">;; Prompt for new method name</span>
  <span class="p">(</span><span class="nv">interactive</span> <span class="s">"r\nsNew Function Name: "</span><span class="p">)</span>

  <span class="c1">;; Kill selected region</span>
  <span class="p">(</span><span class="nv">kill-region</span> <span class="nv">start</span> <span class="nv">end</span><span class="p">)</span>

  <span class="c1">;; Insert call to new function</span>
  <span class="p">(</span><span class="nv">insert</span> <span class="s">"\n"</span> <span class="nv">name</span> <span class="s">"();\n"</span><span class="p">)</span>

  <span class="c1">;; Set a marker so we can jump back to this line</span>
  <span class="p">(</span><span class="nv">point-to-register</span> <span class="mi">1</span><span class="p">)</span>

  <span class="c1">;; Move to end of current function</span>
  <span class="p">(</span><span class="nv">php-end-of-defun</span><span class="p">)</span>

  <span class="c1">;; Insert new function</span>
  <span class="p">(</span><span class="nv">insert</span> <span class="s">"\n\nfunction "</span> <span class="nv">name</span> <span class="s">"() {\n"</span>
	  <span class="p">(</span><span class="nb">car</span> <span class="nv">kill-ring-yank-pointer</span><span class="p">)</span>
	  <span class="s">"\n}\n"</span><span class="p">)</span>

  <span class="c1">;; Jump back to where function was snipped from</span>
  <span class="p">(</span><span class="nv">jump-to-register</span> <span class="mi">1</span><span class="p">))</span>
</code></pre></div></div> ]]></description> </item> <item> <title>Common Lisp: Read a file into a string</title> <pubDate>Fri, 02 Sep 2016 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/cl-read-file-into-string/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/cl-read-file-into-string/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>There’s a couple of ways to do this. <code class="highlighter-rouge">with-open-file</code> takes care of opening and closing the stream:</p> <div class="language-common-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">file-get-contents</span> <span class="p">(</span><span class="nv">filename</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">with-open-file</span> <span class="p">(</span><span class="nc">stream</span> <span class="nv">filename</span><span class="p">)</span>
    <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">contents</span> <span class="p">(</span><span class="nb">make-string</span> <span class="p">(</span><span class="nb">file-length</span> <span class="nc">stream</span><span class="p">))))</span>
      <span class="p">(</span><span class="nb">read-sequence</span> <span class="nv">contents</span> <span class="nc">stream</span><span class="p">)</span>
      <span class="nv">contents</span><span class="p">)))</span>
</code></pre></div></div> <p>To return the file as a list of lines instead, the <code class="highlighter-rouge">loop</code> macro can be used:</p> <div class="language-common-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">file-get-lines</span> <span class="p">(</span><span class="nv">filename</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">with-open-file</span> <span class="p">(</span><span class="nc">stream</span> <span class="nv">filename</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">loop</span> <span class="nv">for</span> <span class="nv">line</span> <span class="nb">=</span> <span class="p">(</span><span class="nb">read-line</span> <span class="nc">stream</span> <span class="no">nil</span><span class="p">)</span>
          <span class="nv">while</span> <span class="nv">line</span>
          <span class="nv">collect</span> <span class="nv">line</span><span class="p">)))</span>
</code></pre></div></div> ]]></description> </item> <item> <title>A simple Jekyll deployment Makefile</title> <pubDate>Tue, 30 Aug 2016 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/jekyll-makefile/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/jekyll-makefile/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>The following <em>Makefile</em> can be used to build, serve and deploy a Jekyll site.</p> <div class="language-make highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">REMOTE</span> <span class="o">?=</span> <span class="s2">"&lt;connection info here&gt;"</span>
<span class="nl">build</span><span class="o">:</span>
	bundle <span class="nb">exec </span>jekyll build

<span class="nl">push</span><span class="o">:</span>
	rsync <span class="nt">-avrz</span> <span class="nt">--delete-excluded</span> _site/<span class="k">*</span> <span class="nv">$(REMOTE)</span>

<span class="nl">deploy</span><span class="o">:</span> <span class="nf">build push</span>

<span class="nl">serve</span><span class="o">:</span>
	bundle <span class="nb">exec </span>jekyll serve <span class="nt">--drafts</span> <span class="nt">--watch</span>
</code></pre></div></div> <p><code class="highlighter-rouge">REMOTE</code> should be something like this <code class="highlighter-rouge">username@server:path</code>, where:</p> <ul> <li><code class="highlighter-rouge">username</code> is your username on the remote server</li> <li><code class="highlighter-rouge">server</code> is the remote server to deploy to</li> <li><code class="highlighter-rouge">path</code> is the remote directory files should be copied to</li> </ul> <p>If <em>rsync</em> is unavailable on the remote machine, <em>scp</em> can also be used by changing <code class="highlighter-rouge">push</code> to the following:</p> <div class="language-make highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">push</span><span class="o">:</span>
	scp <span class="nt">-r</span> _site/<span class="k">*</span> <span class="nv">$(REMOTE)</span>
</code></pre></div></div> <p>Running <code class="highlighter-rouge">make deploy</code> will build the site and upload it in one command.</p> ]]></description> </item> <item> <title>Adding CSS classes to images in Jekyll</title> <pubDate>Sun, 28 Aug 2016 00:00:00 -0400</pubDate> <link>http://sodaware.sdf.org/notes/jekyll-css-classes/</link> <guid isPermaLink="true">http://sodaware.sdf.org/notes/jekyll-css-classes/</guid> <author>phil@sodaware.net (Phil Newton)</author> <description><![CDATA[<p>Sometimes an image in a Jekyll post needs a little extra styling.</p> <p>The following markup will add a CSS class to the generated image.</p> <div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">![</span><span class="nv">Alt Text</span><span class="p">](</span><span class="sx">http://example.org/image.jpg</span><span class="p">)</span>{:class="image-class"}
</code></pre></div></div> <p>Will produce this:</p> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">"http://example.org/image.jpg"</span> <span class="na">alt=</span><span class="s">"Alt Text"</span> <span class="na">class=</span><span class="s">"image-class"</span> <span class="nt">/&gt;</span>
</code></pre></div></div> <p>There should no space around the <code class="highlighter-rouge">=</code> sign.</p> <hr/> <p>This technique can also be used to add multiple HTML attributes. Adding them all in a single pair of <code class="highlighter-rouge">{}</code> does not work; each attribute needs to be in its own set.</p> <div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">![</span><span class="nv">Alt Text</span><span class="p">](</span><span class="sx">/whatever</span><span class="p">)</span>{:class="something-else"}{:style="border: 2px solid red;"}
</code></pre></div></div> <p>It also works on links:</p> <div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="nv">Link Example</span><span class="p">](</span><span class="sx">http://example.org/</span><span class="p">)</span>{:class="big-link"}
</code></pre></div></div> ]]></description> </item> </channel> </rss>