Dot Grid Paper Templates

August 11, 2017

Dot Grid Paper Template in GoodNotes on iPad
Dot Grid Paper Template in GoodNotes on iPad

I use GoodNotes (iOS, macOS) for taking hand-written notes on my iPad. It has a variety of paper templates built-in—ruled, grid, Cornell, and so on—but I wanted to give dot grid paper a try. Rather than go out and buy a ream of it, I created several PDFs for 1/4" (quarter inch) dot grid paper that I can load into GoodNotes as templates (U.S. Letter size).

The result is on GitHub. The repository also contains the Python script and LaTeX package (.sty file) I used to generate them. The script generates individual LaTeX files (which in turn use the LaTeX package) for each of several specifications:

See the dot-grid-paper repository on GitHub for more details.


Using Custom CSS in Markdown Mode

August 11, 2017

The default stylesheet for HTML in most browsers is rather unattractive, so you may want to use a custom stylesheet by either linking to an external stylesheet or including a <style> block in the exported HTML itself.

Custom CSS in Markdown Mode Output
Custom CSS in Markdown Mode Output

Linking to an External Stylesheet

The easiest way to customize the style of previewed and exported HTML output is to link to an existing CSS stylesheet. Markdown Mode has a customizable variable markdown-css-paths, which is a list of stylesheets to link to. For each path or URL in markdown-css-paths, a line like the following will be included in the HTML output:

<link rel="stylesheet" type="text/css" media="all" href="URL" />

The most obvious way to use this is to link to an existing stylesheet. Noting that the variable is a list, one can specify a single CSS path on the local filesystem like so:

(setq markdown-css-paths '("/path/to/custom.css"))

On the other hand, to use an existing URL use the following form:

(setq markdown-css-paths '("http://mydomain.com/style.css"))

As another example, the Marked 2 previewer contains several built-in stylesheets that users can choose between. Conveniently, these stylesheets are stored on the filesystem as CSS files inside the application package and you can link to them locally. To use the “Lopash” style when previewing from markdown-mode, you can set the markdown-css-paths list as follows:

(setq markdown-css-paths
    '("/Applications/Marked 2.app/Contents/Resources/Lopash.css"))

If you don’t have a stylesheet already, there are many popular Markdown stylesheets available online. For example, here are three such repositories on GitHub:

Embedding a Custom Stylesheet

As an alternative (or in addition to) linking to an external stylesheet, you can also include inline style information in output files by using the markdown-xhtml-header-content variable. This variable specifies a string to add to the <head> block of the resulting HTML output.

For example, to remove the underline from links, but underline links when hovering, you can add the following <style> block to markdown-xhtml-header-content:

(setq markdown-xhtml-header-content
      "<style type='text/css'>
a { text-decoration: none; }
a:hover { text-decoration: underline; }
</style>")

Markdown Mode and Imenu

August 10, 2017

Markdown Mode for Emacs includes support for imenu, an interface for quickly navigating to different sections within a buffer. To try imenu with Markdown Mode, simply run M-x imenu-add-menubar-index. An “Index” menu will appear in the menubar. Clicking a heading moves the point to that heading. Alternatively, when invoking M-x imenu using the keyboard Emacs will present you with a list of headings in the minibuffer.

imenu Index in Markdown Mode
imenu Index in Markdown Mode

Markdown Mode adds a “.” to the top of each sub-menu. Clicking this dot takes you to the parent section. Otherwise, there is no way to jump directly to headings that are not “leaf nodes.”

To automatically load imenu when markdown-mode is loaded, you can add the following to your .emacs or init.el file:

(add-hook 'markdown-mode-hook 'imenu-add-menubar-index)
(setq imenu-auto-rescan t)

The first line asks Emacs to run the imenu-add-menubar-index function each time markdown-mode is loaded. The second line asks imenu to keep the index up to date when files are modified, as sections may be added or removed.

Another useful imenu-based tool is imenu-list, a third-party package which shows the current buffer’s imenu entries in a popup buffer. You can install it from MELPA. I use use-package for loading packages in my init file, so I configure it like this:

(use-package imenu-list
  :ensure t
  :bind (("C-'" . imenu-list-smart-toggle))
  :config
  (setq imenu-list-focus-after-activation t
        imenu-list-auto-resize nil))

Then, when pressing C-‘, a window appears on the right side showing the heading hierarchy in the *Ilist* buffer. Pressing C-’ again hides the window.

imenu-list with Markdown Mode
imenu-list with Markdown Mode

Of course, there are several keybindings in the *Ilist* buffer for navigating between sections:

Unlike the imenu Index menu, the *Ilist* buffer is updated automatically when Emacs is idle.


Blink Shell for iOS

August 10, 2017

Markdown Mode in Emacs on iPad via Blink Shell
Markdown Mode in Emacs on iPad via Blink Shell

Blink Shell is a unique and powerful shell app for iOS for connecting to remote hosts. Although it is perhaps not quite as polished as Prompt, my other favorite iOS SSH client, it has several features that Prompt does not.

When you first start Blink, there are no buttons or menus, as one expects from an iOS app. Instead, you are greeted with a cryptic blink> prompt in a black terminal with tiny white text.

This might be a bit disconcerting, but after a brief moment of panic, you will probably start to experiment with some commands. If you type an invalid command, Blink will inform you that you can type “help” to see a list of commands:

Blink: v7.0.1. Jul 11 2017

Available commands:
  mosh: mosh client.
  ssh: ssh client.
  ssh-copy-id: Copy an identity to the server.
  config: Configure Blink. Add keys, hosts, themes, etc...
  help: Prints this.
  exit: Close this shell.

Available gestures and keyboard shortcuts:
  two fingers tap or cmd+t: New shell.
  two fingers swipe down or cmd+w: Close shell.
  one finger swipe left/right or cmd+shift+[/]: Switch between shells.
  cmd+alt+N: Switch to shell number N.
  cmd+o: Switch to other screen (Airplay mode).
  cmd+shift+o: Move current shell to other screen (Airplay mode).
  cmd+,: Open config.
  pinch: Change font size.

If you have a Smart or Bluetooth keyboard attached—and you probably should to get the most out of Blink—then instead of typing a command you might try holding to see a list of keyboard shortcuts.

Blink Shell Keyboard Shortcuts
Blink Shell Keyboard Shortcuts

You can see that pressing ⌘, is an alternative to typing config to enter the app settings. Note that this is the same keyboard shortcut for opening the preferences window in most macOS applications. You can also do normal shell things like Control+L to clear, Control+D to log out, and so on.

Configuring and Connecting to Remote Hosts

Blink works with both SSH and Mosh, but before connecting to a remote host you should first import your SSH login keys and set the default username for SSH connections.

Configuring a New Host
Configuring a New Host

You can issue the ssh command with the usual flags, such as ssh -l <username> <hostname>, but you’ll want to configure frequently-accessed hosts for convenience. Each host is given an alias, say <host> instead of <hostname>, so that once configured you can simply type ssh <host> or mosh <host> to connect with the pre-configured hostname, username, port, etc.

SSH Connection Using a Host Alias
SSH Connection Using a Host Alias

SSH

For basic SSH access to a host, you’ll need provide the following:

Mosh: Mobile Shell

Most readers probably use SSH already but may not have heard of Mosh, which is much newer. Mosh is designed to provide robust remote connections with roaming when your IP changes (e.g., switching from WiFi to cellular) and intermittent connectivity. Mosh piggy-backs on top of SSH, so if you already have remote SSH access you only need to install a user-level mosh-server binary to enable Mosh access.

If you have installed Mosh on the remote host, then you may also need to provide the following:

If you use Homebrew on macOS, installing Mosh is as simple as this:

brew install mobile-shell

Customizing Modifier Keys: Caps Lock as Control

One of Blink’s most powerful features is the ability to customize the keyboard modifier keys. In fact, the reason I found Blink to begin with is it’s ability to use Caps Lock as a Control key (although there is an important caveat, discussed below).

Customizable Keyboard Modifier Keys
Customizable Keyboard Modifier Keys

If you set Caps Lock to be a Control key, there is a very important caveat: Caps Lock may be in an unexpected state when you leave and re-enter blink. This is due to the limitations of iOS development. There is a GitHub issue devoted to this problem if you’d like to read more about the technical details.

To summarize the issue, you can think in terms of two distinct Caps Lock states: one global in scope and one local. There is the iOS system-wide Caps Lock state and then the local state within the Blink app. If you are using Caps Lock as the control key, each time you press Caps Lock the system state is toggled but the Blink Caps Lock state remains off. The issue is that when you leave the Blink app, other apps honor the system state, which could be either on or off depending on whether you’ve pressed Caps Lock an even or odd number of times during your Blink session.

If you have an Apple wireless keyboard with a Caps Lock light, the light follows the system state every time you use Caps Lock in Blink, so this can at least help you track the state. Overall, I’ve found that the annoyance of this issue is small in comparison to the convenience of using Caps Lock as Control in Emacs and for other shell commands.

Another caveat is the small delay between when Caps Lock is pressed and when it is registered. When I quickly type control sequences as fast as I typically do—expecting no delay—the Control key part is not recognized. For example, to send ^C you’ll need to press Caps Lock and hold it for a fraction of a second longer than you typically might before pressing C. I don’t mean to overstate this issue, but I find that I do have to be more deliberate about entering control sequences.

Customization

There is a Blink Shell Theme Gallery with a huge selection of themes which you can access in Settings > Appearance > Add a new theme.

Appearance Settings
Appearance Settings

In the screenshot, I’m enjoying the Fira Code font—the same font I use in Emacs, yes, a monospaced font with programming ligatures—with the Arthur theme for Blink.

Customizable Keyboard Shortcuts
Customizable Keyboard Shortcuts

The keyboard shortcuts are also customizable. This includes the keys for switching to the previous and next shells, creating a new shell, closing a shell, and configuring Blink.

Getting Blink Shell

You can purchase the Blink Shell app on the App Store. Blink is also open source, so you can take a look at the source code on GitHub.2



JSON Feed

August 6, 2017

Ten years ago, I added an Atom feed to this website. Before that, there was an RSS feed—version 1—and for a while I had an RSS 2 feed. But in more recent years I disabled RSS and have used the Atom feed exclusively.

The reality for Atom is that, not only is it difficult to write valid XML by hand, but people also have trouble writing programs to generate valid XML. Once a feed is available, it needs to be parsed. Even parsing valid Atom feeds is no simple task, but the implementation challenges mean that there are also a bunch of broken Atom feeds in the wild that feed reader writers have to deal with.

Enter JSON Feed, written by two individuals with a lot of collective feed-processing experience, with the stated goal of being “simpler to read and write” and “less prone to bugs.” It has been adopted widely already, both by publishers and feed readers.

This is all a long way of announcing that there is now a JSON Feed for this site and you can validate it here.


File Local Variables in Emacs and Markdown Mode

August 2, 2017

Emacs allows one to specify values for variables inside files themselves. For example, you can specify which mode Emacs should use to edit a particular file by setting a special mode variable. You can specify such file local variables at either the beginning or end of a file.

Perhaps you have seen lines like the following at the beginning of scripts. This particular line tells Emacs that you’d like to open this file using cperl-mode:

#!/usr/bin/perl       -*- mode: cperl -*-

The mode variable is special; it’s not an actual variable name in Emacs. Another special variable is coding, which specifies the character coding system for this file (e.g., utf-8 or latin-1). A third special variable is eval, which specifies a Lisp expression to evaluate. Multiple eval declarations can be given in the same file.

Among the special variables, mode is the most special of all and so the mode: declaration can even be omitted:

#!/usr/bin/perl       -*-cperl-*-

File variable definitions should appear in a comment, and the comment syntax used by Markdown Mode is the same as for HTML comments: <!-- comment -->. So, to specify a local variable at the beginning of a file you could add the following to the first line (which would result in Emacs loading the file in gfm-mode instead of, say, markdown-mode):

<!-- -*- mode: gfm -*- -->

To specify multiple variables, separate them by semicolons:

<!-- -*- mode: markdown; coding: utf-8 -*- -->

Alternatively, you can insert a local variable block at the end of a file. Such a block opens with a Local Variables: declaration and closes with End:, like so:

<!-- Local Variables: -->
<!-- markdown-enable-math: t -->
<!-- End: -->

It’s not necessary that each line is a self-contained comment, so the following also works and it is a personal preference which form you use:

<!--
Local Variables:
markdown-enable-math: t
End:
-->

One useful scenario for using file local variables with Markdown files include toggling special modes, like setting markdown-enable-math in the previous example. If you mostly have math mode disabled (so that $ is not a special character), but sometimes want to enable it, using a file-local variable as above is a great way to handle this case.

Other example uses are setting the fill-column in a particular file, or declaring that spaces should be used for indentation instead of tabs:

<!--
Local Variables:
fill-column: 70
indent-tabs-mode: nil
End:
-->

Scripting and Compiling Swift on the Command Line

April 4, 2017

Apple’s Swift programming language is most widely used for iOS and macOS development in Xcode, however, it can also be used in a manner more like a traditional Unix shell script or even compiled into an executable using the command line. Below, I give some examples of these alternative uses.

For scripting, like other shell scripts, the first line of your script’s .swift file should be a “shebang”, which points to the swift executable. Following that, you can write Swift code as usual:

#!/usr/bin/swift

func fibonacci(_ n: Int) -> Int {
    if n <= 2 {
        return 1
    } else {
        return fibonacci(n - 1) + fibonacci(n - 2)
    }
}

print(fibonacci(10))

You can make the script executable and run it as you would any other shell script:

% chmod +x fibonacci.swift
% ./fibonacci.swift
55

Printing the 10th integer in the Fibonacci sequence is hard coded above, but what if you want to print other values? We can modify the script to take a single command line argument, the index of the Fibonacci number you want to print. Replace the last line above with the following:

let arg = CommandLine.arguments[1]  // Store first argument.
if let n = Int(arg) {               // If it converts to Int,
    print(fibonacci(n))             // print fibonacci(n).
} else {                            // Otherwise,
    print("Usage: fibonacci <n>")   // print usage and exit.
}

Then invoke the script as follows:

% ./fibonacci.swift 36
14930352
% ./fibonacci.swift junk
Usage: fibonacci <n>

As with modern scripting languages such as Python and Ruby, you can also run Swift interactively (with Xcode 6.1 and later). The interactive command-line interface is called the Swift Read Eval Print Loop (REPL):

% swift
Welcome to Apple Swift version 3.1 (swiftlang-802.0.48 clang-802.0.48). Type :help for assistance.
  1> 1 + 2
$R0: Int = 3
  2> print("hello, world")
hello, world

Finally, you can also compile Swift code and run it as a binary:

% swiftc -o fibonacci fibonacci.swift
% ./fibonacci 7
13

As with C and other languages, you can compile multiple Swift files:

% swiftc first.swift second.swift third.swift -o program

Note: These instructions are valid on macOS Sierra with Xcode 8.3 and Swift 3.1, but as the Swift language evolves they may change.


Using Markdown Mode: Switching and Toggling Markup

February 18, 2016

Markdown Mode is a major mode for editing Markdown-formatted text files in Emacs. On the surface, it provides syntax highlighting (“font lock” in Emacs parlance) to provide visual cues when editing files and it defines commands and keyboard shortcuts for inserting certain markup. For example, surrounding a phrase in double asterisks (**) in Markdown makes the phrase appear in bold when converted to HTML or another format. The corresponding key sequence in Markdown Mode for inserting bold text, as you probably know if you’ve read this far, is C-c C-s s.

The documentation for Markdown Mode is now quite lengthy, so certain features go unnoticed even by long-time users. Two of these features involve ways to switch types of markup (e.g., from bold to italics). As an example, suppose I typed **really scary** and wish I had written it instead using italics as *really scary*. There are at least two ways in Markdown Mode to quickly fix the mistake.

  1. Using the kill ring: Move the point anywhere in the bold span and press C-c C-k to execute markdown-kill-thing-at-point. This removes the entire bold span and adds the contents (“really scary” without the asterisks) to the kill ring. Then press C-c C-s e to insert an empty italic span and yank the text with C-y.

  2. Using markup toggling: Markdown Mode allows you to “toggle” certain markup, including, bold, italics, and inline code. The second method is to move the point to the bold text and repeat the insertion key sequence (C-c C-s s) to remove (toggle) the asterisks. Then select the text “really scary” (i.e., place it in the active region) and press C-c C-s e to add the italic markup.

In this case, because there are multiple words, you have to activate and set the region (the default is for insertion commands to apply to the single word at the point if there is no active region, or insert empty markup otherwise). This means the first approach is a little faster in this case, but there are cases where both approaches are useful. Both methods also apply to other forms of markup such as bold, italics, and even links.

Extra Credit: Suppose I have *really scary* in the buffer now but I wish it was _really scary_ instead. Both will render in HTML as italics, but you might have a preference for the latter in plain text. You can use the Markdown Mode cycling commands to switch between underscores and asterisks in bold and italic phrases by pressing C-c C-= or C-c C– (markdown-demote and markdown-promote).


Preventing Emacs From Filling Up Your Clipboard History

February 9, 2016

I use a clipboard manager called Copied that syncs previously copied text across all my devices. Short of having an OS X version of Drafts, this is a very efficient way to get text from a Mac to an iOS device. However, when I’m working in Emacs, my clipboard history quickly becomes cluttered because every bit of text I “kill” in Emacs gets “copied” to the system pasteboard and then synchronized to all of my devices.

Indeed, every time I select a sentence or paragraph and kill it with C-w (kill-region), that text gets added to the clipboard history. Worse still, every time I press M-DEL (backward-kill-word) to kill the previous word, that word also gets added to my history. I use these commands a lot, so even with a history of 100 previous items, the important items in my history are quickly buried under a heap of words and phrases that I have killed in Emacs during the normal process of writing and editing text.

This is mitigated to some extent by the fact that Copied allows one to quickly filter the history by just typing a search string in the main window. However, I discovered today that Emacs has a minor mode called delete-selection-mode and when this mode is active, the region is replaced when a character is inserted or deleted (e.g., with backspace). The practical implication of this is that one can remove the active region by pressing DEL rather than C-w:

By default, text insertion occurs normally even if the mark is active–for example, typing a inserts the character ‘a’, then deactivates the mark. If you enable Delete Selection mode, a minor mode, then inserting text while the mark is active causes the text in the region to be deleted first. To toggle Delete Selection mode on or off, type M-x delete-selection-mode.

Source: GNU Emacs Manual, section 11.3.

Also see DeleteSelectionMode on the EmacsWiki and in the Emacs FAQ. To summarize, if one uses DEL instead of C-w to remove text in the active region, it won’t end up in the kill ring or clipboard history. Somehow this slipped by me, but delete-selection-mode is enabled by default in Emacs 24 and 25.

Replacing M-DEL with an alternative that deletes without adding to the kill ring is less obvious. Without adding a custom function, a long version would be C-SPC M-b DEL. This sequence activates the mark1, moves the point backward by one word, and deletes the active region. If you find yourself using this often, it might be better to define a backward-delete-word function to your init.el (source):

(defun backward-delete-word (arg)
  "Delete characters backward until encountering the beginning of a word.
With argument ARG, do this that many times."
  (interactive "p")
  (delete-region (point) (progn (backward-word arg) (point))))

I moved the default backward-kill-word binding to C-M-DEL and set M-DEL to this new function:

(global-set-key (kbd "C-M-<backspace>") 'backward-kill-word)
(global-set-key (kbd "M-<backspace>") 'backward-delete-word)

  1. Use C-SPC C-SPC to activate the mark if you keep transient-mark-mode disabled.


On the Security Implications of Suggested Snippets in TextExpander

August 21, 2015

Synopsis

Suggested snippets in TextExpander 5.0 and 5.1 are stored in plain text and synchronize to the cloud and other devices in kind. This may be unexpected given the current wording of the “Privacy Details” section of the help file (below). This may seem harmless, but if not configured carefully to exclude certain apps (e.g., Terminal, iTerm 2, Emacs) then TextExpander may unintentionally save passwords you type as suggested snippets, which then are stored in plain text and will propagate to the cloud and other devices. I contacted Smile support about this, since I thought it must be a bug or an oversight given what I read in the documentation. They kindly clarified the behavior and indicated that they will consider updating the documentation or adding an FAQ entry to address these points. Read more below for additional background, suggested configuration changes, and details on how to remove any such sensitive information that may have been stored in Dropbox as a result.

Background and Details

TextExpander from Smile is a Mac (and iOS) application that allows one to define short abbreviations for longer words and phrases. A TextExpander “snippet” consists of an abbreviation, content (the full-text associated with the abbreviation), and rules about how and when the abbreviation can be used. TextExpander then watches what you type and when an abbreviation is noticed it automatically replaces the abbreviation with the content, provided that the rules are satisfied.

This is only a basic description the program. More advanced snippets can include date and time arithmetic, scripts, fill-in forms with drop-down menus and optional sections, etc. Because of this, TextExpander is one of a core set of utilities that I install on every Mac I work on (and every iOS device).

Snippet Suggestion

TextExpander 5.x Preferences: Snippet Suggestion
TextExpander 5.x Preferences: Snippet Suggestion

In TextExpander 5.0, released in May 2015, Smile added a new feature called “Suggestions” whereby TextExpander will automatically suggest new snippets based on things you frequently type. This raises obvious privacy and security concerns, which are addressed as follows in the TextExpander 5.1 documentation:

Privacy Details

TextExpander observes your keystrokes, as well as the contents of the pasteboard when you Paste using ⌘V.

TextExpander will track how many times you repeat the same group of characters and create a new suggestion after a certain amount of repetition. However, it does not save the tracking of what you type so the tracking is lost with each TextExpander restart. Therefore, frequent restarting of TextExpander won’t result in many suggestions. None of what you type is saved by TextExpander except for the snippets listed in the Suggested snippets group.

“Tracking” does not mean TextExpander keeps a list of the actual characters you type. Instead, it keeps an encoded record (called a “hash”) of that group of characters, similar to the way a password is securely stored so that no one reading it knows what it is. You might type “yourpetsname” but what TextExpander sees and records is “1739405847385.”

Source: TextExpander 5.1 Help.

After reading this, I was fully reassured about any potential security risks. If TextExpander only keeps an encoded record of what I type and that record doesn’t persist across restarts, then I assumed it only kept the information in memory and that nothing would be stored in the cloud.

Insecure Text Input and Snippet Suggestion

There are measures in place to prevent TextExpander from storing potentially sensitive text, like passwords. However, on my system it still managed to occasionally suggest a passwords as new snippets. I admit to being slightly terrified every time a notification popped up to suggest that I add one of my important, paranoia-grade passwords as a snippet, but at least they weren’t being stored in plain text anywhere, or so I thought.

To understand why TextExpander was able to see my passwords in the first place, it helps to know a little more about how text input in a modern OS X application works. Developers can flag certain text fields for secure text input (e.g., password fields that don’t display what you type). The operating system won’t allow TextExpander to see what you type in those fields and therefore it could not feasibly suggest snippets based on that input. Applications such as 1Password and Safari (for properly written web forms) have no problem properly flagging secure text fields.

In other cases, it’s nearly impossible for OS X to know when secure text is being requested. Consider a terminal emulator like Terminal or iTerm 2, or a programmable text editor like Emacs. These applications can run arbitrary, cross-platform code that is not specifically written for OS X and hence does not flag secure text entry in the way that OS X recognizes. Consider logging in to a remote server via SSH on the command line. When you type your password in the terminal, unless your terminal emulator is in the list of excluded apps, TextExpander will take note that you typed a certain string, one that happens to be your password. If you do that often enough and you have snippet suggestion turned on, then your password becomes a suggested snippet. Therefore, one has to be careful to exclude all applications where passwords and other sensitive information might be entered but not marked as secure text. Primary examples are Terminal, iTerm 2, Emacs, and so on.

TextExpander Preferences: Applications to Exclude from Snippet Suggestion
TextExpander Preferences: Applications to Exclude from Snippet Suggestion

Suggested Snippet Storage and Synchronization

It turns out that suggestions are stored in plain text in an XML file in the TextExpander settings bundle (a directory called Settings.textexpandersettings). The file is named group_<uuid>.xml, where <uuid> is a long string of numbers and letters, and is associated with the “Suggested Snippets” group. Furthermore, if you have sync enabled (via Dropbox, iCloud, etc.) then these suggestions also sync in plain text. Because I have Dropbox sync enabled, the group_<uuid>.xml file is stored on Dropbox. As an example, in the Settings.textexpandersettings directory in my Dropbox account, I found the following entry in an XML file:

<dict>
    <key>abbreviation</key>
    <string></string>
    <key>abbreviationMode</key>
    <integer>0</integer>
    <key>creationDate</key>
    <date>2015-06-17T17:18:54Z</date>
    <key>extraInfo</key>
    <dict>
        <key>pendingSuggestionDate</key>
        <date>2015-06-17T17:18:54Z</date>
    </dict>
    <key>label</key>
    <string></string>
    <key>modificationDate</key>
    <date>2015-06-17T17:18:54Z</date>
    <key>plainText</key>
    <string>REDACTED</string>
    <key>snippetType</key>
    <integer>0</integer>
    <key>uuidString</key>
    <string>9EFC26DA-8536-4D3E-A002-983E792EDBAD</string>
</dict>

Notice this section in particular:

<key>plainText</key>
<string>REDACTED</string>

Indeed, rather than REDACTED the value of the plainText key was actually one my most important passwords–all 47-characters in full, plain text glory.

In retrospect, I should have been much more vigilant in many ways. I should have excluded any apps that might result in insecure text being added as a snippet. The terminal entry weakness wasn’t obvious to me at first though. It also wasn’t obvious to me that the suggested snippets were being synchronized across machines because there tend to be a large number of suggestions to filter through and, since I type similar things on multiple machines, some similarities across machines are to be expected.

While I still think the documentation on suggested snippets and privacy is incomplete and potentially misleading, here is a more thorough description of the behavior I received from Smile support:

The help text you cited refers to the tracking of keystrokes up to the point at which a suggestion is made. Once a suggestion is made, yes, it is stored in the settings in plain text. TextExpander remembers the suggestions it’s found for later, so as to not keep suggesting them again. The Help text may need clarification, but in essence it is exactly true. The log of all keystrokes (tracking) is discarded and only suggestions are kept.

Clean Up and Prevention

If this happened to you as well and you want to clean things up, try the following:

  1. Disable snippet suggestion in the TextExpander for any apps that might not flag all secure text entry by adding them to the list of excluded apps, as discussed above.

  2. Note the name of the XML file in your settings bundle corresponding to the “Suggested Snippets” group. You’ll need to find this file on the Dropbox website later. This step can be tricky since Finder hides the contents of the setting bundle by default.

    One option is to control-click the bundle in finder and click “Show package contents”. Then preview the group_<uuid>.xml files until you find the one containing <key>name</key> followed by <string>Suggested Snippets</string>.

    Another option, if you’re comfortable on the command line, is to cd to the Settings.textexpandersettings directory and grep for "Suggested Snippets" to find the right file. For example:

    cd ~/Dropbox/TextExpander/Settings.textexpandersettings
    grep "Suggested Snippets" group*.xml
    
  3. Turn off snippet suggestions in the TextExpander preferences and delete the Suggested Snippets group.

  4. The previous step should delete the corresponding XML file, but you’ll also want to remove the Dropbox version history for the file. On the Dropbox website, navigate to the settings bundle and click the trashcan icon to show deleted files. Command-click (or right click) the deleted XML file and click “Permanently delete”.

  5. Optionally, re-enable snippet suggestion.

Permanently Delete Files in Dropbox
Permanently Delete Files in Dropbox

Archive

Dot Grid Paper Templates • August 11, 2017
PDF dot paper templates for use in apps such as GoodNotes.
Using Custom CSS in Markdown Mode • August 11, 2017
How to link to an external CSS stylesheet or include an inline style block in HTML output from Markdown Mode.
Markdown Mode and Imenu • August 10, 2017
Using imenu and imenu-list with markdown-mode in Emacs.
Blink Shell for iOS • August 10, 2017
A brief review and guide to Blink Shell, an SSH and Mosh client for iOS.
JSON Feed • August 6, 2017
This site now produces a JSON feed.
File Local Variables in Emacs and Markdown Mode • August 2, 2017
How to use file local variables in Emacs generally, and specifically in Markdown Mode.
Scripting and Compiling Swift on the Command Line • April 4, 2017
Examples of using Swift for shell scripts and compiling Swift code on the command line.
Using Markdown Mode: Switching and Toggling Markup • February 18, 2016
A note on advanced Markdown Mode usage for Emacs.
Preventing Emacs From Filling Up Your Clipboard History • February 9, 2016
Ways to delete rather than kill text in Emacs to keep your clipboard history clear.
On the Security Implications of Suggested Snippets in TextExpander • August 21, 2015
If not configured properly, TextExpander 5.x suggested snippets may be stored as plain text, may sync to the cloud, and may include passwords.
Pasteboard Cleaning on OS X • August 19, 2015
Brief summary of some methods for removing styles from copied text in OS X.
Sending Events to Fantastical 2 from Emacs • August 16, 2015
An Emacs Lisp function for sending the region to Fantastical 2 to parse as a new event.
Sending Tasks to OmniFocus from Emacs • August 13, 2015
An Emacs Lisp function for creating an OmniFocus task using the region.
MATH77 and mathc90 Libraries • July 21, 2015
Two large mathematical libraries, MATH77 and mathc90, go open source.
(Emacs) Keyboard Shortcuts for Editing Text Fields in OS X • July 17, 2015
A comparison of Emacs and OS X keyboard shortcuts for editing text.
Syntax highlighting for code blocks in Emacs Markdown Mode • July 13, 2015
A follow-up to Charl Botha's post on using mmm-mode for syntax highlighting of fenced code blocks in Markdown mode.
Intel Fortran Compilers Now Free for Students on All Platforms • July 1, 2015
The Intel Fortran compiler was previously free for non-commercial use on Linux only, but now OS X and Windows are also included.
Lossless Optimization of PNG Image File Sizes • June 29, 2015
Brief comparison of pngout and optipng, command-line utilities for lossless compression (optimization) of PNG image files.
Visualizing Color Codes with rainbow-mode for Emacs • June 26, 2015
rainbow-mode is a minor mode which changes the background color of text representing color codes in various forms.
Git Workflows on iOS with Working Copy • June 25, 2015
A comprehensive Git client for iPhone and iPad with support for iOS 8 share extensions and the iCloud document picker.
How to write a book in Emacs • June 24, 2015
An article on planning, writing, editing, and publishing a book in Emacs by Mickey Petersen.
k • June 23, 2015
Directory listings for zsh with git features.
Drafts Actions for OmniFocus and TextExpander • June 23, 2015
Links to Drafts actions for integration with OmniFocus and TextExpander on iOS.
Update to Bicubic Interpolation Code (TOMS 760) • June 21, 2015
Regarding a typo in the Fortran 90 translation of TOMS algorithm 760.
Integrating OS X and Emacs Dired • June 15, 2015
A keyboard shortcut for using OS X open in Dired.
Highlights: A New App for Annotating PDFs, with Two-Way Markdown Sync • June 10, 2015
Highlights is a new app that is a promising for academics with mostly digital workflows who work with PDF files and like to write in Markdown.
New GitHub Repositories • June 4, 2015
Both Deft and Markdown Mode for Emacs are now on GitHub.
Working with Large LaTeX Documents (in Emacs) • September 8, 2014
Some tricks for handling large files in Emacs.
Gnuplot Line Styles for Display and Printing • August 22, 2014
A simple way to see the available line styles for any Gnuplot terminal.
An Interface Issue in ELSUNC • August 14, 2014
A bug fix for Alan Miller's elsunc.f90.
Running Marked 2 from the Command Line • August 14, 2014
A replacement for the mark script from Marked version 1.
Reproducibility vs. Replication • October 5, 2013
Dave Giles recently reminded us of the distinction between replication and reproducibility.
Emacs F90 Mode Quick Reference Update • October 3, 2013
A substantial update to my f90-mode quick reference.
A Small Update to simann.f90 • October 2, 2013
I have applied a small patch to fix a bug in Alan Miller's simann.f90.
Software and Hardware Volume Settings • October 1, 2013
How to set software and hardware volume for best audio quality.
Box and Beard Plot • September 30, 2013
A play on the box and whiskers plot.
Polynomial Zeros in Quadruple Precision • February 28, 2013
An enhancement to Alan Miller's rpoly.f90.
Title Case in Emacs • February 9, 2013
An Emacs Lisp library for converting text to title case.
Semicolons • February 7, 2013
Mary Norris, writing for The New Yorker on semicolons, quotes a book titled Punctuation..?
MathML and Chrome: On Again, Off Again • February 6, 2013
MathML has been disabled again in Google Chrome.
Solid State Drive Hosting Services • February 5, 2013
A2 Hosting is now offering SSD hosting plans.
Emacs Help Functions • February 4, 2013
An overview of the Emacs help system.
Citing Forthcoming Articles with BibTeX • January 19, 2013
Using @Article entries in BibTeX for "forthcoming" or "in press" articles.
ReadKit • January 19, 2013
ReadKit is a simple Mac app for reading articles from Instapaper, Pocket, and Readability.
Source Code Pro by Adobe • January 14, 2013
A monospace typeface designed for programming, complementary to the Source Sans family.
A Markdown Previewer with MathML Support • January 4, 2013
Marked is a Markdown previewer for OS X which can load MathJax to support MathML in previews.
Securely Erasing a Full Terabyte • December 13, 2012
On securely erasing drives using wipe and monitoring drive health.
MathML is Coming to Google Chrome • October 26, 2012
MathML has been enabled in Google Chrome Canary.
Emacs Speaks Statistics (ESS) in MacPorts • August 28, 2012
A new MacPorts port for Emacs Speaks Statistics (ESS).
Installing OS X Lion on a Mac Mini Second Hard Drive • May 19, 2012
Adding a second hard drive to a mid 2011 Mac Mini and installing OS X Lion on it.
LaTeX on the iPad • March 29, 2012
A collection of apps and a remote compile server shell script to build a complete LaTeX editing, compiling, and viewing system.
Default Virtual Host in Apache • March 26, 2012
How to configure the default virtual host in Apache.
Markdown and web.py Tutorial • February 24, 2012
Build a simple web app which serves Markdown content as HTML.
Price Return vs. Total Return • February 24, 2012
Financial tools should report total returns, not simply price returns.
iOS Alternatives to Google Reader • February 23, 2012
A survey of feed reading apps on iOS that work independently of Google Reader.
Locate via Spotlight on OS X • February 5, 2012
Using the Spotlight database to implement locate on OS X.
Lightweight Launchers for Linux • January 31, 2012
Verve command line for Xfce4 and Synapse launcher.
Google's New Privacy Policy • January 25, 2012
Wherein Google's new privacy policy induces me to leave.
Parallel gzip and bzip2 • November 9, 2011
Using parallel versions of gzip and bzip2 on Linux.
Printing Left-Justified Values in Fortran • July 31, 2011
Using internal writes to print left-justified strings and numerical values in Fortran.
Kindle DX Graphite Review • February 1, 2011
A review of the Kindle DX for reading PDF files for academic use.
Emacs F90 Mode Quick Reference • January 21, 2011
Commands and abbrevs for Fortran programming in Emacs.
Debugging Memory Issues with Valgrind • December 22, 2010
Example Fortran and C programs with exceeded array bounds and memory leaks.
Version Control in Scientific Computing • December 21, 2010
Using version control systems to enhance code clarity and ensure reproducibility of results.
Writing Efficient Code • December 19, 2010
Notes on writing efficient Fortran and C code in scientific applications.
Your Apps Are Watching You • December 18, 2010
A Wall Street Journal investigation of iPhone and Android apps.
The Uncertain Future of Delicious • December 17, 2010
Rumors circulated yesterday that Yahoo! would shut down Delicious.
Unlimited Polymorphic Data Structures in Fortran • March 20, 2010
Using unlimited polymorphic pointers to create generic data structures in Fortran.
Lightweight Markup Languages • March 16, 2010
A list of several lightweight markup languages.
Stack Overflows in Fortran • March 13, 2010
Some stack overflows can be avoided by allocating large automatic arrays on the heap.
Parsing Command-Line Options in Fortran 2003 • September 17, 2009
A simple example which makes use of Fortran 2003's new command-line interface.
SSH SOCKS Proxy Tunnel • August 29, 2009
Browse securely using the built-in SOCKS proxy support of OpenSSH.
Google Groups URLs • July 26, 2009
How to link to a Usenet message in Google Groups using the Message-ID.
The Fortran Wiki • April 29, 2009
Announcing the opening of the Fortran Wiki.
Dates and Times in SQLite • April 1, 2009
Notes on using SQLite, a lightweight relational database.
Markdown • March 29, 2009
Examples of Markdown syntax and an exhaustive collection of external links.
2009-03-11 • March 11, 2009
Parallel compilation with GNU Make.
2009-02-29 • February 28, 2009
emacs-snapshot
2009-02-26 • February 26, 2009
Elastic tabstops
The Greek Alphabet in LaTeX • February 5, 2009
A page containing the Greek alphabet in LaTeX for reference.
Dynamic Abbreviation in Emacs • January 29, 2009
dabbrev-expand will change the way you write.
Parallel Computing in Fortran with OpenMP • January 27, 2009
A simple parallel Monte Carlo exercise for getting started with OpenMP in Fortran.
Void Pointers in Fortran with the Transfer Intrinsic • January 26, 2009
A method for emulating C's type casting using the transfer intrinsic.
Maximum Likelihood Estimation in R • January 5, 2009
An example of maximum likelihood estimation in R which estimates the parameters of an AR(1) process using simulated data.
Tools for Converting LaTeX to XML • December 10, 2008
A survey of available tools for converting LaTeX to XHTML+MathML or, more generally, LaTeX to XML.
2008-12-07 • December 7, 2008
Free software tools for converting LaTeX documents to XHTML+MathML.
Fortran Unit Testing with fUnit • December 6, 2008
A short guide to test-first development in Fortran using fUnit.
2008-12-01 • December 1, 2008
COIN-OR; Definr
2008-11-30 • November 30, 2008
Bazaar branch diff.
Packaging and Distribution of Fortran Libraries • November 25, 2008
Thoughts on best practices for packaging and distributing modern Fortran libraries.
xml-ping • November 24, 2008
A simple Perl script for sending XML-RPC pings to update services.
Fortran Language Definition for GNU Source-highlight • November 22, 2008
An updated Fortran language definition for syntax highlighting via Source-highlight.
Calculating the Log Sum of Exponentials • November 21, 2008
How to avoid numeric overflow when taking the log of a sum of exponentials.
Collected Markdown Makefile Wisdom • November 20, 2008
A summary of methods for building websites using Markdown and Make.
2008-11-17 • November 17, 2008
midori
Managing Websites with Git • November 16, 2008
Using Git hooks to automatically rebuild websites after updates.
2008-11-16 • November 16, 2008
Screenshots from the command-line; tufte-latex; Bera Mono; zsh word separators
Emacs color-theme-less • November 16, 2008
A minimalistic color theme for Emacs.
chsh -s /usr/bin/zsh • November 16, 2008
Changing from bash to zsh.
Advanced Emacs • November 14, 2008
Advanced and lesser known editing functions of GNU Emacs
2008-11-14 • November 14, 2008
Literate programming links
LaTeX to MathML using itex2MML • November 4, 2008
Notes on LaTeX to XHTML+MathML conversion posted to the pandoc-discuss mailing list.
Debian OpenSSH Vulnerability • October 21, 2008
Some background on the Debian OpenSSH vulnerability and instructions on generating new SSH keys.
Double Free or Corruption Error • September 18, 2008
How to diagnose double free errors caused by invalid array indexing.
Efficient BibTeX • August 16, 2008
Suggestions for a more efficient BibTeX workflow.
LaTeX Tips • July 28, 2008
A collection of LaTeX tips and tricks.
A2 Hosting Ubuntu Virtual Private Server Guide • May 8, 2008
A complete guide to setting up a cheap Ubuntu VPS server at A2 Hosting.
A Simple Fortran Control File Example • May 6, 2008
A Fortran program to load a control file with line labels.
Git Colors • April 29, 2008
How to enable color output in Git.
2008-04-15 • April 15, 2008
How to be a good referee and demand-based parking rates in San Francisco.
Git • April 5, 2008
Distributed version control with Git.
2008-04-05 • April 5, 2008
Epiphany on WebKit, Debian MathML fonts, and newsbeuter.
2008-03-30 • March 30, 2008
LaTeX documents and version control.
Extensionless URIs in Movable Type 4 • March 30, 2008
Modifying archive mappings to support extensionless, future-proof URIs.
bmf: Bayesian Mail Filter • March 29, 2008
A simple efficient Bayesian mail filter
2008-03-29 • March 29, 2008
tinyapps.org, ext3grep, a Blosxom history lesson, and some Blosxom derivatives.
Linux Hostname Configuration • March 5, 2008
An attempt to clarify the process of properly setting hostnames in Linux.
MySQL to SQLite Migration • February 26, 2008
How to convert a MySQL database to SQLite.
Tips for Processing Large Datasets • February 26, 2008
Avoid reading entire files into memory or uncompressing large files.
Blosxom: Less is More • January 22, 2008
In it's elegant simplicity, Blosxom makes for an effective minimalist content management system capable of serving XHTML+MathML+SVG.
def predicate_p • January 19, 2008
A Python alternative to Ruby's question marked predicate functions.
Atom Feeds of Comments in Blosxom • January 16, 2008
Generate Atom feeds of recent comments in Blosxom simply by creating a new flavour and modifying the feedback plugin.
XHTML+MathML+SVG in Movable Type 4 • January 13, 2008
A short guide to serving XHTML+MathML+SVG content in Movable Type 4.
bzr-feed HOWTO • January 2, 2008
A short introduction to bzr-feed
bzr-feed Patch for Shared Repositories • December 19, 2007
A patch for bzr-feed to enable shared repository support.
LaTeX in Inkscape • December 10, 2007
Create vector graphics containing LaTeX equations using Inkscape.
Scientific Computing in Python • December 10, 2007
An overview of various Python packages for scientific computing.
Typesetting Algorithms in LaTeX • December 7, 2007
A couple of packages for typesetting algorithms in LaTeX.
Migrating from RCS to Bazaar • October 22, 2007
How to convert an RCS-managed project to a Bazaar repository.
In Rainbows • October 14, 2007
Radiohead have released their new album, “In Rainbows.”
Subprime Mortgage Worries • August 15, 2007
Subprime mortgage worries continue to spread fear in markets around the world. What is the problem and who is to blame?
EXT3 Undelete • August 9, 2007
How to recover deleted files from an ext3 partition in Linux.
PDF Forms in Linux • June 3, 2007
An update on the status of PDF form editing in Linux.
Setting Up a 32-bit chroot Environment in Ubuntu • May 30, 2007
Notes on setting up a chroot environment to run 32-bit programs in a 64-bit version of Ubutnu Linux.
Feed Upgrades • May 25, 2007
The site now emits valid Atom 1.0 and RSS 2.0 feeds.
Emacs Keybindings in Gnome • February 21, 2007
How to enable Emacs-style keyboard shortcuts in Gnome.
MathML • February 21, 2007
Notes on browser support for MathML.
Structured Procrastination • February 10, 2007
Rather than fight procrastination directly, harness it and channel it towards highly productive activities.
Rails Migrations and MySQL Types • February 8, 2007
A test to determine how the types defined in Rails migrations translate into MySQL types.
Using Legacy Primary Keys in Rails • February 5, 2007
Rails, primary keys, legacy databases
Beck - The Information • October 14, 2006
Beck - The Information (2006)
Soft Paternalism • April 8, 2006
Soft paternalism and the role of the state in directing personal behavior
Music and Audioscrobbler on the Linux Console • March 30, 2006
Using mpd, mpdscribble, and ncmpc on the Linux console
Securing sshd • March 25, 2006
Methods to increase the security of an sshd server.
Printing Even and Odd Pages of a PDF • March 9, 2006
Instructions for manual duplex printing of PDF files in Linux
nVidia MCP51 and ALSA • March 7, 2006
Instructions for using the nVidia MCP51 with the ALSA intel8x0 driver.
Blosxom Security Measures • March 2, 2006
Several basic measures that can be taken to secure a blosxom weblog.
Printing a Fortran Array with write • February 6, 2006
How to print an array on a single line in Fortran 77.
In Praise of Low-Fidelity • February 5, 2006
Advocating simplicity and efficiency.
Google Transit • January 16, 2006
Google Transit lets you plan a trip using public transit.
Fortran 77 • January 16, 2006
A few introductory Fortran 77 links.
Work for Your Coffee • January 13, 2006
Walk to the coffee shop for practical exercise.
Time Magazine: How to Tune Up Your Brain • January 13, 2006
A summary of a Time article about productivity and focus.
Converting PNG Scans to PDF • January 6, 2006
How to convert PNG images to PDF files using free tools in Linux.
Blosxom • January 6, 2006
Introductory post about the weblog software Blosxom.
Initializing an Array of Pointers to a Class • June 7, 2004
How to initialize a variable-sided array of class pointers.
ipw2100 mini-HOWTO • May 31, 2004
A short guide to install the Intel PRO/Wireless 2100 Driver for Linux.
GNU/Linux on the Sony Vaio PCG-V505DX • March 30, 2004
Notes on installing GNU/Linux on the Sony Vaio PCG-V505DX laptop.