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:
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:
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.
}
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:
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.
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.
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).
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.
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:
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
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.”
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
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:
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:
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.
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
Turn off snippet suggestions in the TextExpander preferences
and delete the Suggested Snippets group.
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”.
A common problem on OS X is to paste plain text without the
associated style information. Some apps have an item in the Edit menu
called “Paste and Match Style”, but many don’t. It’s also
inconvenient to have to use the menu for this. Ideally, one could use
a keyboard shortcut just like ⌘V for pasting text with
styling intact. Fortunately, there are several good options including
a system-wide shortcut, a simple Keyboard Maestro macro and a
a more complicated one, and even a dedicated app. As it
happens, I already had an app installed with similar functionality:
Paste is a clipboard history manager with an option to paste as
plain text (⌘↩) or to remove formatting and styles from all
copied text.
Some brief notes: The system-wide shortcut doesn’t work everywhere
since some apps don’t have the “Paste and Match Style” menu item. If
you already own Keyboard Maestro, then one of the two macros
should serve you well. Otherwise, I’d suggest looking into either
Get Plain Text or Paste. I’m using the latter and although
it’s a little flashy for my taste it does get the job done when I need
to find something I copied previously and, now, for stripping styles
from things I copy.
Last week, I wrote a function for
sending tasks to OmniFocus from Emacs. This involved creating
and running short AppleScript snippet on the fly to communicate with
OmniFocus. Once this basic structure is available, it’s fairly easy to
connect with other applications. The next application on my list was
Fantastical 2.
A Newly Parsed Calendar Event from Emacs
The send-region-to-fantastical function below takes first line of
the region and sends it to Fantastical which opens the mini window
(from the menu bar) and, using its natural language parsing, creates a
new event which you can then review and add to your calendar. Any
remaining lines in the region are added to the event as a note.
Finally, it appends a note indicating that the task came from Emacs
along with a timestamp.
Sending the Emacs Region to OmniFocus
(defun send-region-to-fantastical (beg end)"Send the selected region to Fantastical.Parse the first line to create the event and use the secondand subsequent lines as the event note."(interactive "r")(let*((region (buffer-substring-no-properties beg end))(match (string-match "^\\(.*\\)$" region))(event (substring region (match-beginning 1)(match-end 1)))(notes (if(< (match-end 0)(length region))(concat (substring region (+(match-end 0)1) nil)"\n\n")"")))(do-applescript(format "set theDate to current date set eventText to %s set eventNotes to %s set eventNotes to (eventNotes) & \"Added from Emacs on \" & (theDate as string) tell application \"Fantastical\" parse sentence (eventText) notes (eventNotes) end tell"(applescript-quote-string event)(applescript-quote-string notes)))))
I call send-region-to-fantastical by pressing C-c f via the
following global keybinding:
Wouldn’t it be great if you could take the current region in Emacs and
use it to create a new task in OmniFocus? I thought so, and it turns
out this problem has been solved at leastthreetimes
before. However, I either had some trouble getting the previous
solutions to work or wished they worked differently. For example
omnifocus-capture.el by Ken Case defines a function which sends
the region to OmniFocus’s quick entry window, but then you still have
to trigger the quick entry keyboard shortcut to save the task to the
OmniFocus Inbox (or elsewhere). That introduced too much friction for
my taste, so I decided to write a different function based on Ken’s
original one.
A Task from Emacs in Quick Entry Limbo
The communication between Emacs and OmniFocus needs to happen using
AppleScript, so I first borrowed Ken’s applescript-quote-string
function for properly escaping strings in AppleScript (with a couple
of very minor modifications):
(defun applescript-quote-string (argument)"Quote a string for passing as a string to AppleScript."(if(or (not argument)(string-equal argument ""))"\"\"";; Quote using double quotes, but escape any existing quotes or;; backslashes in the argument with backslashes.(let((result "")(start 0) end)(save-match-data(if(or (null (string-match "[^\"\\]" argument))(< (match-end 0)(length argument)))(while (string-match "[\"\\]" argument start)(setq end (match-beginning 0) result (concat result (substring argument start end)"\\"(substring argument end (1+ end))) start (1+ end))))(concat "\"" result (substring argument start)"\"")))))
Then I defined a new send-region-to-omnifocus function. The most
important difference for me is that the task is sent straight to the
OmniFocus Inbox rather than sitting around in the quick entry window
waiting to be entered. This is a personal preference of mine, since I
tend to first “capture” tasks quickly and process them later, when I
clean them up and assign projects and contexts.
An Inbox Task from Emacs with a Title
The new function is also different in how it handles the contents of
the region. It uses the first line of the region as the task name and
any subsequent lines as the task note. It also appends both a note
indicating that the task was added from Emacs and a timestamp.
Finally, the new function is also a little more efficient. Ken’s
original function created the AppleScript as a string, wrote it to a
temporary file, and then ran the script in a shell using osascript.
Instead, this version generates the AppleScript in a string and calls
do-applescript directly (which perhaps did not exist when the
original function was written).
Sending the Emacs Region to OmniFocus
(defun send-region-to-omnifocus (beg end)"Send the selected region to OmniFocus.Use the first line of the region as the task name and the secondand subsequent lines as the task note."(interactive "r")(let*((region (buffer-substring-no-properties beg end))(match (string-match "^\\(.*\\)$" region))(name (substring region (match-beginning 1)(match-end 1)))(note (if(< (match-end 0)(length region))(concat (substring region (+(match-end 0)1) nil)"\n\n")"")))(do-applescript(format "set theDate to current date set taskName to %s set taskNote to %s set taskNote to (taskNote) & \"Added from Emacs on \" & (theDate as string) tell front document of application \"OmniFocus\" make new inbox task with properties {name:(taskName), note:(taskNote)} end tell"(applescript-quote-string name)(applescript-quote-string note)))))
I call send-region-to-omnifocus by pressing C-c o via the
following global keybinding:
NASA’s Jet Propulsion Laboratory (JPL) has released two large math
libraries under an open source (BSD) license.
Via Degenerate Conic:
MATH77 is a library of Fortran 77 subroutines implementing various
numerical algorithms. It was developed over decades at JPL, and
contains some very high-quality and time-tested code. The code is
released under a BSD-type license. There is also a C version for
people who love semicolons.
This goldmine includes basic mathematical functions, random number
generators, linear algebra routines, solvers for systems of nonlinear
equations, curve fitting, interpolation, and quadrature routines, and
much more. The libraries are available at Netlib and are
accompanied by 619 pages of detailed documentation.
As is widely known, OS X has a collection of keyboard shortcuts
involving the arrow keys for editing most text fields including web
forms, input boxes, plain text documents, and so on. For example,
⌘← moves the cursor to the beginning of the current line.
Although they are hidden in plain sight, it seems less widely
known that OS X also natively supports certain Emacs keyboard
shortcuts in those same text areas. For example, to move to the
beginning or end of the current line you can press ⌃A or
⌃E. To delete everything on the current line after the
cursor use ⌃K. To transpose the characters on the left and
right of the cursor, press ⌃T. To recenter the viewport on
the current line, press ⌃L. Shortcuts like these can be
faster than using ones involving the arrow keys, which requires moving
ones fingers away from the home row of the keyboard.
The table below compares the Emacs keybindings with the OS X ones (the
Emacs-like ones and more standard ones). For OS X shortcuts we use
the usual symbols for the Command ⌘, Shift ⇧,
Option ⌥, Control ⌃, Caps Lock ⇪,
Delete ⌫, and Function Fn keys and write all
letter keys in uppercase. Emacs keybindings are expressed in the
usual notation for Control C, Meta (Alt) M,
Shift S prefixes and the Delete DEL key and we
write the letter keys in lowercase.
Emacs and OS X Keyboard Shortcuts Compared
Entity
Direction
Emacs
OS X
Moving the cursor: move the cursor by character, word, line, etc.
char
left
C-b
⌃B
←
right
C-f
⌃F
→
word
left
M-b
⌃⌥B
⌥←
right
M-f
⌃⌥F
⌥→
line
begin
C-a
⌃A
⌘←
end
C-e
⌃E
⌘→
up
C-p
⌃P
↑
down
C-n
⌃N
↓
doc
begin
M-<
⌘↑
end
M->
⌘↓
Selecting text: extend the selection1 by character, word, paragraph, and line
char
left
C-b
⌃⇧B
⇧←
right
C-f
⌃⇧F
⇧→
word
left
M-b
⌃⌥⇧B
⌥⇧←
right
M-f
⌃⌥⇧F
⌥⇧→
line
begin
C-a
⌃⇧A
⇧⌘←
end
C-e
⌃⇧E
⇧⌘→
up
C-p
⌃⇧P
⇧↑
down
C-n
⌃⇧N
⇧↓
Deleting text: remove characters, words, and lines
char
left
C-h, DEL
⌃H
⌫
right
C-d
⌃D
word
left
M-DEL
⌥⌫
right
M-d
Fn+⌥⌫
line
backwards
C–0 C-k
⌘⌫
forwards
C-k
⌃K
Search: find text and move between search results
result
first
C-s
⌘F
next
C-s
⌘G
previous
C-r
⇧⌘G
Scrolling: move and recenter the viewport
page
up
M-v
Fn+↑
down
C-v
⌃V
Fn+↓
recenter
C-l
⌃L
Miscellaneous: other insertion, editing, and kill ring2 commands
To enter transient-mark-mode in Emacs, press C-SPC first. ↩
The kill ring is an Emacs concept, much like the OS X pasteboard (clipboard), but with a history that can be cycled. The OS X kill and yank commands here make use of a kill ring which is separate from the pasteboard and which can contain only a single element (i.e., no history). ↩