2021-08-02 Reordering sentences in Emacs

I’m probably in a minority, but I am a heavy user of Emacs’ transpose-* commands, most notably transpose-words and transpose-chars. This is probably because I have spent a lot of time editing texts in Emacs – not writing, but editing, and wrong order of words is a very common mistake I often needed to fix.

One problem with transpose-words, though, is that it can only swap two words, usually two adjacent ones, or – with a suitable prefix argument – “drag” a word past a set number of words forward or backward. (Not many people know that it can also swap two non-adjacent words – see its docstring for how to do that.)

I’ve been meaning to write some Elisp code to help with that for a long time, and some time ago the time has come. (Ironically, I no longer work for the journal where I did most of the editing…) For the past few weeks, I’ve been working on a mode I called reorder-sentence-mode (since by default it allows to reorder words in the sentence the point is in). Here is how it works: you put the point anywhere in the sentence you want reordered (or activate a region if what you need is not the whole sentence) and say M-x reorder-sentence. Every word in the sentence/region is then “marked” with a letter (or digit, if we run out of letters), and a window with a temporary buffer caled *Reorder sentence* is shown. Pressing the letters copy the words designated by them to that buffer, and C-c C-c deletes the window and copies the reordered sentence to the buffer you started in.

This is the basic operation, but there are a few niceties, too. For instance, when you copy a word, it becomes “inactive”, and pressing the same letter again copies the next word instead. This means that if you want to copy 4 subsequent words, you can just press the key corresponding to the first of them four times in a row. If you press a key with a non-alphanumeric character (like space or some punctuation mark), that character is just inserted in the temporary buffer. If you press M-c or M-l, the next word is capitalized or downcased – very useful when you want to change the first word of a sentence. (These commands even accept a numeric argument, handling positive, negative and zero arguments in a pretty smart way!) Pressing C-c C-k cancels the “reordering session” altogether. Pressing <backspace> (or any key normally bound to undo) undoes the last change (though this doesn’t always work reliably – yet).


And here is the best thing. The code doing all that isn’t even long (less than 300 lines of code), but if you want to learn how it was written and why it is written the way it is, I have excellent news for you. This package was developed as part of the book teaching Emacs Lisp I am writing, Hacking your way around in Emacs. As of now, more than 40 pages of the book are dedicated to explaining the reordering code – better yet, building it from scratch with detailed commentary, teaching many Elisp constructs and techniques along the way.

But wait, there’s more! You don’t even have to buy the book to have the code (but you may want to know that the site I used to sell the book, Leanpub, offers a 45-day full-refund policy, so you don’t risk your money if you decide to buy it). While it’s not (yet) on Melpa (it still lacks a few minor things, one of them being a proper file header – I definitely wanted to teach writing Elisp first and writing package headers later, not the other way round!), you can actually download it (along with any other code that is/will be part of the book, excluding some small, throwaway examples) from GitLab. An important note: since the book is still being written and I often revisit earlier parts and make some corrections, I rebase the master branch of the code repository without any limitations, so that the Git history corresponds to what I do in the book. And by the way, if you worry that you’ll buy the book, read some part of it and then I’ll pull the rug from under your feet by introducing some important change in the parts you’ve already read, then don’t – every time I update the book I send an email with a list of notable changes since the last update to all people who bought it.

CategoryBlog, CategoryEnglish, CategoryEmacs, CategoryEmacsBook