editing

Aligning text

Emacs has a flexible tool, align-regexp, for aligning text but it is surprisingly fiddly to use. For example to align a section of text like this:

the quick brown fox
jumped over the lazy
dogs the quick brown

into columns like this:

the     quick  brown  fox
jumped  over   the    lazy
dogs    the    quick  brown

you would highlight the text and use C-u M-x align-regexp \(\s-*\)\s- RET 1 RET 0 RET y. See what I mean!

The function is of course documented (use C-h f align-regexp to read it), but I found it a bit hard to follow. The \(\s-*\)\s- string is the regular expression that is used to align on, and the final \s- in that string tells emacs to align on a whitespace character. You could replace that with e.g. & to align on & characters. The other three options (i) control how the columns are justified (generally can leave this as 1); (ii) add spaces between columns; and (iii) repeat the alignment throughout the line.

To make life easier, I wrote a couple of simple wrappers around align-regexp for common tasks. The first aligns on whitespace, and the second aligns on & (useful for LaTeX tables).

(defun bjm/align-whitespace (start end)
  "Align columns by whitespace"
  (interactive "r")
  (align-regexp start end
                "\\(\\s-*\\)\\s-" 1 0 t))

(defun bjm/align-& (start end)
  "Align columns by ampersand"
  (interactive "r")
  (align-regexp start end
                "\\(\\s-*\\)&" 1 1 t))
Advertisement

Join line to following line

I wrote a while ago about using M-^ to join the current line to the previous line. In fact, when editing I find that I most often want to join a line to the following line. I used to do this by using C-e to move to the end of the line and then C-d to delete until I got the next line joined to the current one. It is easier to do this with a single key using a simple function, which I set to C-j. Add the following to your emacs config file:

;; join line to next line
(global-set-key (kbd "C-j")
            (lambda ()
                  (interactive)
                  (join-line -1)))

You can keep hitting C-j to keep joining the next line.

Update

I originally used M-j as the keybinding for this, but Kaushal Modi pointed out in the comments that C-j is a better choice.

Fix touch-typing semicolon typo

I’ve started learning to touch type (for the nth time) and I find I make a lot of typos. Most are easily fixed with flyspell’s C-;, but I quite often hit ; instead of l, which flyspell can’t fix as it looks like the end of a word. I wrote a quick bit of code to replace the most recent ; with l

;;fix ; typos
(defun bjm-semicolon-to-l ()
  "Change the most recent semicolon behind the point to an l character. Useful for fixing a common touch-typing error"
  (interactive)
  (let ((bjm-start-pos (point)))
    (search-backward ";")
    (delete-char 1)
    (insert "l")
    (goto-char bjm-start-pos)))

(global-set-key (kbd "C-:") 'bjm-semicolon-to-l)

This is pretty simplistic, but it shows how easy it is to add a very personalised bit of extra functionality to emacs with minimal lisp skills!

Update

Grant Rettke pointed out in the comments that it is simpler to handle moving the point back to where you started by using save-excursion. The updated code is:

;;fix ; typos
(defun bjm-semicolon-to-l ()
  "Change the most recent semicolon behind the point to an l character. Useful for fixing a common touch-typing error"
  (interactive)
  (save-excursion
    (search-backward ";")
    (delete-char 1)
    (insert "l")))

Thanks Grant!

Jump back to previous typo.

We recently looked at using flyspell to quickly fix the most recent typo with C-;. Sometimes flyspell can’t find a correction for the word you want, so you need to fix it by hand.

Flyspell offers the function flyspell-goto-next-error which moves the point forward to the next error, and is bound to C-, (although this keybinding is taken over in org-mode). However, I only want to move back to the previous error, but flyspell offers no function for this. This is easily fixed with a very slightly modified version of the code from this answer by hatschipuh on stackexchange.

This code jumps you to the end of the most recent misspelled word.

;; move point to previous error
;; based on code by hatschipuh at
;; http://emacs.stackexchange.com/a/14912/2017
(defun flyspell-goto-previous-error (arg)
  "Go to arg previous spelling error."
  (interactive "p")
  (while (not (= 0 arg))
    (let ((pos (point))
          (min (point-min)))
      (if (and (eq (current-buffer) flyspell-old-buffer-error)
               (eq pos flyspell-old-pos-error))
          (progn
            (if (= flyspell-old-pos-error min)
                ;; goto beginning of buffer
                (progn
                  (message "Restarting from end of buffer")
                  (goto-char (point-max)))
              (backward-word 1))
            (setq pos (point))))
      ;; seek the next error
      (while (and (> pos min)
                  (let ((ovs (overlays-at pos))
                        (r '()))
                    (while (and (not r) (consp ovs))
                      (if (flyspell-overlay-p (car ovs))
                          (setq r t)
                        (setq ovs (cdr ovs))))
                    (not r)))
        (backward-word 1)
        (setq pos (point)))
      ;; save the current location for next invocation
      (setq arg (1- arg))
      (setq flyspell-old-pos-error pos)
      (setq flyspell-old-buffer-error (current-buffer))
      (goto-char pos)
      (if (= pos min)
          (progn
            (message "No more miss-spelled word!")
            (setq arg 0))
        (forward-word)))))

I bind this to C-, to replace flyspell-goto-next-error. See this stackexchange question for methods to ensure your keybinding overrides the bindings by major modes like org.

Delete blank lines and shrink whitespace

We looked previously at deleting spaces between words, and a related task is to delete one or more blank lines at the position of the cursor.

Emacs has a built-in command for this, delete-blank-lines, which is bound to C-x C-o. From the help for the function

On blank line, delete all surrounding blank lines, leaving just one. On isolated blank line, delete that one. On nonblank line, delete any immediately following blank lines.

However, the best solution to deleting both blank lines and spaces between words is to install the package shrink-whitespace which gives you the best of both worlds. As illustrated in this animation, if the cursor is between words it will delete spaces leaving one space, and calling it again will remove that space too (similar to cycle-spacing). If the cursor is between lines it will delete blank lines leaving one blank line, and calling it again will remove that line too.

delete-blank-lines.gif

I have bound this to M=SPACE in my emacs config file using

;; delete blank lines and whitespace
(global-set-key (kbd "M-SPC") 'shrink-whitespace)

Check and fix spelling as you type

To check spelling and highlight errors as you type, enable flyspell with M-x flyspell-mode. It has the incredibly useful feature that typing C-; will cycle through corrections for the most recent spelling error. This lets you correct typos without needing to move the cursor back to them. This become absolutely essential once you get used to it!

To enable flyspell automatically, add the following lines to your emacs config file.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; flyspell spell checking                                                ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;enable flyspell in text mode
(add-hook 'text-mode-hook 'flyspell-mode)
;;enable flyspell in org-mode
(add-hook 'org-mode-hook 'flyspell-mode)
;;enable for tex-mode
(add-hook 'latex-mode-hook 'flyspell-mode)
;;or if you use AUCTeX for latex
(add-hook 'LaTeX-mode-hook 'flyspell-mode)

Update

Commenter hmelman points out that we only need to enable flyspell for text-mode and it will be enables for org, latex and LaTeX modes since they derive from text mode:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; flyspell spell checking                                                ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;enable flyspell in text mode (and derived modes)
(add-hook 'text-mode-hook 'flyspell-mode)

Dealing with DOS line endings

I ran into a problem with ediff, in that it was showing two files to be entirely different even though I knew only a few lines should differ. The problem was that the colleague who sent the second file was using Windows, and so every line in file B ended with a DOS style carriage return (or newline characters) instead of a unix style one as in file A. These carriage return characters are usually invisible, but you can see them if you evaluate the following piece of elisp

(setq inhibit-eol-conversion t)

and then reopen the file. DOS carriage returns appear at the end of each line as ^M. (An alternative would be to use cat -t on the file in a terminal to also show the carriage return characters.)

The DOS carriage returns are easily removed by using M-x set-buffer-file-coding-system and then entering unix and saving the file.

Basic spell checking

Use M-x ispell-buffer to run spell-check on the whole buffer, or M-$ to check the spelling of the word at the cursor position. The spell check will suggest corrections for the words, or let you save the word to your personal dictionary (by hitting i).

Emacs can use several back-ends to do the actual spell checking, and there is a good comparison of them here. For myself, I have found hunspell to give the best suggested corrections. I installed hunspell with macports

sudo port install hunspell

and then added the following to my emacs config file:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; spelling                                                               ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; use hunspell
(setq-default ispell-program-name "hunspell")
(setq ispell-really-hunspell t)
;; tell ispell that apostrophes are part of words
;; and select Bristish dictionary
(setq ispell-local-dictionary-alist
      `((nil "[[:alpha:]]" "[^[:alpha:]]" "[']" t ("-d" "en_GB") nil utf-8)))