Auto Save and Backup Every Save

Emacs has two useful ways of protecting you from data loss. The first is auto save, which saves a copy of a file every so often while you are editing it. If some catastrophe caused you to close Emacs or shut down your machine without saving the file then you can use M-x recover-file to recover the file from its auto save. By default, the auto save files are saved in the same directory as the original file, and are given a name of the form #file#. This is fine for me, but you can configure this.

I like to make auto saves often, so I make the following tweaks to my emacs config file:

;; auto save often
;; save every 20 characters typed (this is the minimum)
(setq auto-save-interval 20)

When you save a file, the auto save file is deleted.

The other way Emacs protects you is to make backups of your files. By default the backup file is made in the same directory as the original with a name like file~. The way the backup works is that Emacs makes a copy of a file the first time you save it in an Emacs session. It only makes that one backup though, so this is not very useful if you keep your session running for a long time and want to recover an earlier version of a file.

The following code sets some general backup options and then configures Emacs to make a backup of a file every time you save it. The code builds on bits from here and here, and the comments should be quite self-explanatory.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; backup settings                                                        ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; https://www.emacswiki.org/emacs/BackupFiles
(setq
 backup-by-copying t     ; don't clobber symlinks
 kept-new-versions 10    ; keep 10 latest versions
 kept-old-versions 0     ; don't bother with old versions
 delete-old-versions t   ; don't ask about deleting old versions
 version-control t       ; number backups
 vc-make-backup-files t) ; backup version controlled files

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; backup every save                                                      ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; http://stackoverflow.com/questions/151945/how-do-i-control-how-emacs-makes-backup-files
;; https://www.emacswiki.org/emacs/backup-each-save.el
(defvar bjm/backup-file-size-limit (* 5 1024 1024)
  "Maximum size of a file (in bytes) that should be copied at each savepoint.

If a file is greater than this size, don't make a backup of it.
Default is 5 MB")

(defvar bjm/backup-location (expand-file-name "~/emacs-backups")
  "Base directory for backup files.")

(defvar bjm/backup-trash-dir (expand-file-name "~/.Trash")
  "Directory for unwanted backups.")

(defvar bjm/backup-exclude-regexp "\\[Gmail\\]"
  "Don't back up files matching this regexp.

Files whose full name matches this regexp are backed up to `bjm/backup-trash-dir'. Set to nil to disable this.")

;; Default and per-save backups go here:
;; N.B. backtick and comma allow evaluation of expression
;; when forming list
(setq backup-directory-alist
      `(("" . ,(expand-file-name "per-save" bjm/backup-location))))

;; add trash dir if needed
(if bjm/backup-exclude-regexp
    (add-to-list 'backup-directory-alist `(,bjm/backup-exclude-regexp . ,bjm/backup-trash-dir)))

(defun bjm/backup-every-save ()
  "Backup files every time they are saved.

Files are backed up to `bjm/backup-location' in subdirectories \"per-session\" once per Emacs session, and \"per-save\" every time a file is saved.

Files whose names match the REGEXP in `bjm/backup-exclude-regexp' are copied to `bjm/backup-trash-dir' instead of the normal backup directory.

Files larger than `bjm/backup-file-size-limit' are not backed up."

  ;; Make a special "per session" backup at the first save of each
  ;; emacs session.
  (when (not buffer-backed-up)
    ;;
    ;; Override the default parameters for per-session backups.
    ;;
    (let ((backup-directory-alist
           `(("." . ,(expand-file-name "per-session" bjm/backup-location))))
          (kept-new-versions 3))
      ;;
      ;; add trash dir if needed
      ;;
      (if bjm/backup-exclude-regexp
          (add-to-list
           'backup-directory-alist
           `(,bjm/backup-exclude-regexp . ,bjm/backup-trash-dir)))
      ;;
      ;; is file too large?
      ;;
      (if (<= (buffer-size) bjm/backup-file-size-limit)
          (progn
            (message "Made per session backup of %s" (buffer-name))
            (backup-buffer))
        (message "WARNING: File %s too large to backup - increase value of bjm/backup-file-size-limit" (buffer-name)))))
  ;;
  ;; Make a "per save" backup on each save.  The first save results in
  ;; both a per-session and a per-save backup, to keep the numbering
  ;; of per-save backups consistent.
  ;;
  (let ((buffer-backed-up nil))
    ;;
    ;; is file too large?
    ;;
    (if (<= (buffer-size) bjm/backup-file-size-limit)
        (progn
          (message "Made per save backup of %s" (buffer-name))
          (backup-buffer))
      (message "WARNING: File %s too large to backup - increase value of bjm/backup-file-size-limit" (buffer-name)))))

;; add to save hook
(add-hook 'before-save-hook 'bjm/backup-every-save)

Files are backed up to a customisable directory in subdirectories per-session once per Emacs session, and per-save every time a file is saved. You can specify a maximum file size for files that will be backed up, and a regular expression to specify files that will not be backed up. I use the latter to avoid making backups of my emails by using the regular expression \\[Gmail\\] which matches emails I compose with mu4e. You can set this to nil if you want to disable this.

Uniquify your buffer names

If you open more than one file that has the same name (say test.txt), then by default Emacs will add a number to the end of the buffer name to distinguish them, so you would see test.txt <1> and test.txt <2> and so on. This is not very useful as it is easy to lose track of which file is which.

Luckily it is easy to fix with some simple tweaks (I’ve taken these from the configuration files for prelude). Add these to your emacs config file and your buffer names will be made unique by adding just enough of the path to the file. So you might see docs/test.txt and scratch/test.txt. Much nicer!

;; meaningful names for buffers with the same name
;; from prelude
;; https://github.com/bbatsov/prelude
(require 'uniquify)
(setq uniquify-buffer-name-style 'forward)
(setq uniquify-separator "/")
(setq uniquify-after-kill-buffer-p t)    ; rename after killing uniquified
(setq uniquify-ignore-buffers-re "^\\*") ; don't muck with special buffers

Volatile Highlights

The package volatile highlights temporarily highlights changes to the buffer associated with certain commands that add blocks of text at once. An example is that if you paste (yank) a block of text, it will be highlighted until you press the next key. This is just a small tweak, but gives a nice bit of visual feedback.

You can install it in the normal way:

;; volatile highlights - temporarily highlight changes from pasting etc
(use-package volatile-highlights
  :config
  (volatile-highlights-mode t))

Quickly move a file to the current directory

Often I’ll download a file in my browser, and then want to move that file to the directory in which I am working in emacs. I wrote a little helper function to streamline this, called bjm/move-file-here, given below or at this github gist. Call the function and it will prompt you with a list of files in your starting directory (defaulting to ~/downloads, but configurable with bjm/move-file-here-start-dir) sorted to have the most recent first. The chosen file will then be moved to the current directory if you are in dired, or else the directory of the current buffer.

The function needs the packages dash.el and swiper installed. Here is the code – comments are welcome.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; move file here                                                         ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'dash)
(require 'swiper)

;; start directory
(defvar bjm/move-file-here-start-dir (expand-file-name "~/downloads"))

(defun bjm/move-file-here ()
  "Move file from somewhere else to here.
The file is taken from a start directory set by `bjm/move-file-here-start-dir' and moved to the current directory if invoked in dired, or else the directory containing current buffer. The user is presented with a list of files in the start directory, from which to select the file to move, sorted by most recent first."
  (interactive)
  (let (file-list target-dir file-list-sorted start-file start-file-full)
    ;; clean directories from list but keep times
    (setq file-list
          (-remove (lambda (x) (nth 1 x))
                   (directory-files-and-attributes bjm/move-file-here-start-dir)))

    ;; get target directory
    ;; http://ergoemacs.org/emacs/emacs_copy_file_path.html
    (setq target-dir
          (if (equal major-mode 'dired-mode)
              (expand-file-name default-directory)
            (if (null (buffer-file-name))
                (user-error "ERROR: current buffer is not associated with a file.")
              (file-name-directory (buffer-file-name)))))

  ;; sort list by most recent
  ;;http://stackoverflow.com/questions/26514437/emacs-sort-list-of-directories-files-by-modification-date
  (setq file-list-sorted
        (mapcar #'car
                (sort file-list
                      #'(lambda (x y) (time-less-p (nth 6 y) (nth 6 x))))))

  ;; use ivy to select start-file
  (setq start-file (ivy-read
                    (concat "Move selected file to " target-dir ":")
                    file-list-sorted
                    :re-builder #'ivy--regex
                    :sort nil
                    :initial-input nil))

  ;; add full path to start file and end-file
  (setq start-file-full
        (expand-file-name start-file bjm/move-file-here-start-dir))
  (setq end-file
        (expand-file-name (file-name-nondirectory start-file) target-dir))
  (rename-file start-file-full end-file)
  (message "moved %s to %s" start-file-full end-file)))

Undo-send and schedule email in mu4e

One of the things I missed when I switched from thunderbird to mu4e was the ability to undo sent emails. I’m sure I’m not the only one that has spotted a glaring error, or a CC’d person that shouldn’t be CC’d the moment after I hit send! Of course you can’t truly undo a sent email, but if you buffer emails for a short period of time before actually sending them then you can retrieve them and edit or cancel them before sending again. This is what the send later extension in thunderbird does, and also the “undo send” function in gmail.

I looked into whether something like this existed for mu4e, I found gnus-delay, but it turned out not to work in mu4e. However it did not take too much effort to modify it to work, and hence mu4e-delay was born. Credit to the authors of gnus-delay who wrote most of the code this is based on.

Once you initialise the package, you can use C-c C-l (mnemonic l for send later) in place of C-c C-c to send mail. This moves the mail to the drafts folder and adds a header keyword specifying the time at which a mail should be sent, defaulting to 2 minutes in the future. A timer runs every minute (default) checking all mails in the drafts folder and sending those that are due. If you wish to “undo send” just find it in the drafts folder and then edit it to remove the delay header and save it. This will prevent it from being sent until you re-send (or delay) it.

The package also provides the function mu4e-delay-add-delay-header which can be called interactively to add any date and time to the delay header keyword, scheduling an email for an arbitrary point in the future.

The mail is sent with smtpmail or sendmail/postfix depending on which you have configured with send-mail-function. Since smtpmail causes emacs to freeze while mail is sent, you are strongly encouraged to use postfix (or similar) to handle your email sending.

A known limitation of mu4e-delay is that attachments are not sent properly when the mail is delayed. I’ve not worked out why this is yet (suggestions welcome!). The package checks to see if you have an attachment and warns you about this. With attachments you currently need you use C-c C-c to send as normal.

I’ll finish with a word of caution. Emails are important and I’d hate you to get into trouble because something went wrong an email did not get sent. I strongly recommend (at least at first) setting the variables mu4e-delay-bcc-address to bcc all outgoing mail to a spare email address so you can check things are being sent correctly. You can also set mu4e-delay-backup-directory to backup all delayed mail to a given directory rather than deleting it. I have used this package for several months without problems, but be careful!

To install the package, download it from github and put the mu4e-delay.el file somewhere on your system and then add the following to your init.el file

(add-to-list 'load-path "/path/to/directory")
(require 'mu4e-delay)

I’m keeping this package off MELPA for now until I get feedback that other people are using it without problems, so please let me know in the comments or on github whether it is working for you (or not).

My other articles on mu4e are collected here.

Using postfix instead of smtpmail to send email in mu4e

The standard setup for mu4e uses smtpmail to actually send the messages. This works fine for the most part, but by default it does not run asynchronously, so emacs pauses when a mail is sent. Usually this is very brief, but for messages with large attachments it can be very noticeable. This was particularly annoying to me when I started developing a package to add a two minute delay to all outgoing mail to give an “undo send” functionality (I’ll post more about this package soon). When the two minute timer finished and the mail was sent, I would be working on something else, and emacs would hang briefly, which was a bit annoying.

It is possible to configure mu4e to send the mail asynchronously, but apparently this can be unreliable. A better solution is to run your own mail server to handle outgoing mail. This is supported in mu4e, and mu4e hands off the mail to the server to send, so it happens instantly from the user’s point of view, regardless of the size of the mail. Another benefit is that mail sent while you are offline is handled automatically; the server queues the mail and then sends it when you reconnect.

I am using OS X Yosemite, and setting up a mail server was quite easy. The postfix mail server is installed by default on OS X, so it was just a matter of configuring it to work with my gmail account. I followed these helpful instructions, noting the advice in the comments that for Yosemite, the extra line

smtp_sasl_mechanism_filter = login

is needed.

Now we tell mu4e to use postfix to handle sending mail by adding the following to our emacs config file:

;;send mail using postfix
(setq send-mail-function 'sendmail-send-it)
(setq message-send-mail-function 'message-send-mail-with-sendmail)

(Note the references to “sendmail” are because this was the name of one of the original mail servers on unix/linux. Postfix is a more modern mail server that is compatible with sendmail.)

This should be all you need to switch to using postfix to send your mail. Some useful commands (to run at the command line, not using M-x in emacs) are

sudo postfix start
sudo postfix stop

to start and stop the server, and

mailq

to list the current queue of unsent mail. This will generally be empty, but if you have been offline you might see some mails in there. They should send automatically once the server notices you are back online, but if not, use

mailq -q

to send all mail in the queue. See the man pages for more functionality.

So there you are. This might not be for everyone, but if you don’t mind fiddling with some config files, I highly recommend moving over to postfix for sending your mail.

Super-efficient movement using avy

One of the revelations I came to after a while of using emacs is that you can use searching (or swiping) to efficiently move to another place in the visible buffer. In other words, you can see the place that you want the cursor to be so you do a search for a word close to that position to move the cursor there – not because you want to find that word.

The package avy gives an even more efficient way to do this. There are a few options, but with the configuration below, I look at the place I want the cursor to be, hit M-s and type the first character of a word close to that position, and then the short string that appears in order to select the word that I want and the cursor jumps there. Once you get used to it, it almost feels like you can move the cursor just by looking where you want it to go!

In the animation below I want to move the cursor to the start of the word “formed” near the bottom of the window, so I hit M-s and then f. avy then overlays letter combinations on all words starting f and I type “la” to move to the word I want.

avy.gif

Here is my configuration code for avy

(use-package avy
  :ensure t
  :bind (("M-s" . avy-goto-word-1)))