Emacs Redux

Return to the Essence of Text Editing

Make Use of the Super Key

| Comments

Emacs users have a lot of power at their disposal, but in one department they are always short - the number of available non-complex keybindings that they can leverage.

Obviously nobody likes pressing keybindings like C-p C-v k (or something like that). One way to get your hands on some extra keybindings is to utilize the Super key (it’s the Windows key on Win keyboards and the Command key on Mac keyboards (although most people remap Command to Meta and Option to Super)). One great thing about Super is that you generally have two of them, which makes them touch-typing friend. Since almost no packages use those keys you’re left with plenty of options.

Prelude defines a bunch of global keybindings that use the Super key.

1
2
3
4
5
6
7
8
9
10
11
12
13
;; make some use of the Super key
(define-key global-map [?\s-d] 'projectile-find-dir)
(define-key global-map [?\s-e] 'er/expand-region)
(define-key global-map [?\s-f] 'projectile-find-file)
(define-key global-map [?\s-g] 'projectile-grep)
(define-key global-map [?\s-j] 'prelude-top-join-line)
(define-key global-map [?\s-k] 'prelude-kill-whole-line)
(define-key global-map [?\s-l] 'goto-line)
(define-key global-map [?\s-m] 'magit-status)
(define-key global-map [?\s-o] 'prelude-open-line-above)
(define-key global-map [?\s-w] 'delete-frame)
(define-key global-map [?\s-x] 'exchange-point-and-mark)
(define-key global-map [?\s-p] 'projectile-switch-project)

If you find pressing Super comfortable obviously you have the potential to add quite a lot more keybindings to this list.

P.S. Some keyboards (notably laptop ones) have a Fn key as well that’s also usable in Emacs keybindings. Somewhat funny that key is known in Emacs as Hyper (Star Wars fans are undoubtedly adding a Hyper-Space keybinding to their setups right about now).

Advise Multiple Commands in the Same Manner

| Comments

One of the well known features of Prelude is that it saves buffers with changes in them automatically when you jump between windows. This is achieved with several simple defadvices and without going into many details the advice code for that feature might look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
;; automatically save buffers associated with files on buffer switch
;; and on windows switch
(defadvice switch-to-buffer (before switch-to-buffer-auto-save activate)
  (prelude-auto-save))
(defadvice other-window (before other-window-auto-save activate)
  (prelude-auto-save))
(defadvice windmove-up (before other-window-auto-save activate)
  (prelude-auto-save))
(defadvice windmove-down (before other-window-auto-save activate)
  (prelude-auto-save))
(defadvice windmove-left (before other-window-auto-save activate)
  (prelude-auto-save))
(defadvice windmove-right (before other-window-auto-save activate)
  (prelude-auto-save))

Ouch - that a lot of redundant code! Luckily we can take care of the redundancy by introducing a macro to generate multiple advices with the same body:

1
2
3
4
5
6
7
8
9
(defmacro advise-commands (advice-name commands &rest body)
  "Apply advice named ADVICE-NAME to multiple COMMANDS.

The body of the advice is in BODY."
  `(progn
     ,@(mapcar (lambda (command)
                 `(defadvice ,command (before ,(intern (concat (symbol-name command) "-" advice-name)) activate)
                    ,@body))
               commands)))

Looks a bit scary, doesn’t it? But it allows us to reduce the original code down to:

1
2
3
4
;; advise all window switching functions
(advise-commands "auto-save"
                 (switch-to-buffer other-window windmove-up windmove-down windmove-left windmove-right)
                 (prelude-auto-save))

macroexpand can show us how the macro gets expanded:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(macroexpand '(advise-commands "auto-save"
                 (switch-to-buffer other-window windmove-up windmove-down windmove-left windmove-right)
                 (prelude-auto-save)))

(progn
  (defadvice switch-to-buffer
    (before switch-to-buffer-auto-save activate)
    (prelude-auto-save))
  (defadvice other-window
    (before other-window-auto-save activate)
    (prelude-auto-save))
  (defadvice windmove-up
    (before windmove-up-auto-save activate)
    (prelude-auto-save))
  (defadvice windmove-down
    (before windmove-down-auto-save activate)
    (prelude-auto-save))
  (defadvice windmove-left
    (before windmove-left-auto-save activate)
    (prelude-auto-save))
  (defadvice windmove-right
    (before windmove-right-auto-save activate)
    (prelude-auto-save)))

Obviously if we want the macro to be truly universal we should factor out the hardcoded before and activate defadvice params, but that’s beside the point. The point is that when you need to generate some code Emacs Lisp’s macros have your back.

Go to Column

| Comments

Almost every Emacs user knows that M-g M-g and M-g g (both bound to go-to-line) will take him to the line of his choosing (provided he knows the number of the target line, of course).

Surprisingly few Emacs users know that there is a similar way to jump to a column by its number - M-g TAB (bound to move-to-column). Interactively you cannot jump past the end of the line you’re currently on, but you can always cook your own version of the command to get around that limitation:

1
2
3
(defun go-to-column (column)
  (interactive "nColumn: ")
  (move-to-column column t))

Let’s bind that to some keycombo:

1
(global-set-key (kbd "M-g M-c") 'go-to-column)

Locate

| Comments

locate is one extremely popular Unix command that allows you to search for files in a pre-built database.

One little know fact is that Emacs provides a wrapper around the command you can invoke with M-x locate. You’ll be prompted to enter a search string and you’ll be presented with a list of matching filenames from locate’s database. Many of dired keybindings are available in the results buffer (which will be using locate-mode major mode).

If you’d like you may change the command invoked by Emacs to supply the results by altering the locate-command variable. Here’s how you can start using OSX’s mdfind (the command-line interface to Spotlight) instead of locate:

1
(setq locate-command "mdfind")

Obviously any command that takes a string argument and returns a list of files would do here. In all likelihood you’ll never want to use anything other than the default locate command, though.

Boost Performance by Leveraging Byte-compilation

| Comments

Emacs’s Lisp interpreter is able to interpret two kinds of code: humanly readable code (stored in files with .el extension) and machine optimized code (called byte-compiled code), which is not humanly readable. Byte-compiled code runs faster than humanly readable code. Java or .NET developers should already be familiar with the concept of byte-code, since it’s pretty central on those platforms.

You can transform humanly readable code into byte-compiled code by running one of the compile commands such as byte-compile-file. The resulting byte-code is stored into .elc files. One can also byte-compile Emacs Lisp source files using Emacs in batch mode.

Here’s how you can compile everything in your .emacs.d folder:

1
emacs -batch -f batch-byte-compile ~/.emacs.d/**/*.el

Of course we can easily create an Emacs command that does the same thing:

1
2
3
4
(defun byte-compile-init-dir ()
  "Byte-compile all your dotfiles."
  (interactive)
  (byte-recompile-directory user-emacs-directory 0))

user-emacs-directory is an Emacs variable that points to your init dir (usually ~/.emacs.d on UNIX systems). This command will recompile even files that were already compiled before (meaning a file with the same name and the .elc extension instead of .el existed). You can try the new command with M-x byte-compile-init-dir.

You have to keep in mind that Emacs will load code from the .elc files if present alongside the .el files, so you’ll have to take steps to ensure you don’t have stale .elc files lying around. I’d suggest the following solution:

1
2
3
4
5
6
7
8
9
10
(defun remove-elc-on-save ()
  "If you're saving an elisp file, likely the .elc is no longer valid."
  (add-hook 'after-save-hook
            (lambda ()
              (if (file-exists-p (concat buffer-file-name "c"))
                  (delete-file (concat buffer-file-name "c"))))
            nil
            t))

(add-hook 'emacs-lisp-mode-hook 'remove-elc-on-save)

This code will make Emacs delete the some_file.elc file, every time the some_file.el file in the same folder is saved.

A couple of closing notes:

  • If you don’t have any custom computationally intensive defuns in your init directory - it probably doesn’t make sense to byte-compile it.

  • Packages installed via package.el will be automatically byte-compiled during the installation process.

The code presented here is part of Prelude. As a matter of fact Prelude will byte-compile itself during the installation process (if you used the installed script, that is). Prelude will also recompile itself when M-x prelude-update is invoked.

Eval and Replace

| Comments

Sometimes people tend to overlook how well Emacs and Emacs Lisp are integrated. Basically there is no limit to the places where you can evaluate a bit of Emacs Lisp and reap the associated benefits. From time to time I find myself editing something and thinking - “Hey, it’d be really great of I could just insert the result of some Emacs Lisp expression at point!” (my thoughts are pretty crazy, right?). Here’s a contrived example - I might have to enter somewhere the result of 1984 / 16. I can calculate that manually or I can fire up M-x calc and get the result, or I can play extra smart and devise the following command (which I did not actually devise - I’m pretty sure I saw it in someone else’s config a while back):

1
2
3
4
5
6
7
8
9
(defun eval-and-replace ()
  "Replace the preceding sexp with its value."
  (interactive)
  (backward-kill-sexp)
  (condition-case nil
      (prin1 (eval (read (current-kill 0)))
             (current-buffer))
    (error (message "Invalid expression")
           (insert (current-kill 0)))))

Let’s bind that to C-c e:

1
(global-set-key (kbd "C-c e") 'eval-and-replace)

Now in the buffer I’m currently editing I can type (/ 1984 16) and press C-c e afterwards getting the result 124 replace the original expression. Pretty neat!

I’ll leave it up to you to think of more creative applications of the command.

This command is part of Prelude(it’s named prelude-eval-and-replace there).

Deleting Windows

| Comments

Every Emacs user knows that he can split the current window horizontally (with C-x 2) and vertically (with C-x 3) as much as he desires to. However, some Emacs users don’t know what to do with the extra windows they’ve created when they do not them.

To delete the selected window, type C-x 0 (delete-window). Once a window is deleted, the space that it occupied is given to an adjacent window (but not the minibuffer window, even if that is the active window at the time). Deleting the window has no effect on the buffer it used to display; the buffer continues to exist, and you can still switch to with C-x b or any other buffer navigation command.

C-x 4 0 (kill-buffer-and-window) is a stronger (and fairly unknown) command; it kills the current buffer and then deletes the selected window (basically it combines C-x k and C-x 0). Obviously it’s a good idea to use it on windows displaying buffers you’re no longer needing.

C-x 1 (delete-other-windows) deletes all the windows, except the selected one; the selected window expands to use the whole frame. (This command cannot be used while the minibuffer window is active; attempting to do so signals an error.) In the era of narrow screens I used that command fairly often when I needed to focus on a particular task. Now I keep my screen split in half vertically 99% of the time, but I still use C-x 1 from time to time when I’m about to resplit my screen in some uncommon way.

Windows displaying help buffers (generally created with commands like C-h ...) warrant a special mention. They can be deleted with a single keystroke - q. That would delete the help window altogether if it was created by the help command, or restore its original content if the window existing beforehand and was reused by the help command.

Open Line Above

| Comments

This post continues a topic that was introduced in smarter open-line few months back.

Often when editing code one wishes to open a line just above the current one, which is properly indented relative to the existing code, and position the cursor at its beginning. Such a feature is present in most IDEs, such as IntelliJ IDEA, Eclipse and NetBeans. It’s sometimes bound to Control+Shift+Enter. Last time I showed you how to implement a similar function called smart-open-line, this time will implement smart-open-line-above. Just add this snippet to your .emacs (or .emacs.d/init.el or whatever):

1
2
3
4
5
6
7
8
9
10
(defun smart-open-line-above ()
  "Insert an empty line above the current line.
Position the cursor at it's beginning, according to the current mode."
  (interactive)
  (move-beginning-of-line nil)
  (newline-and-indent)
  (forward-line -1)
  (indent-according-to-mode))

(global-set-key [(control shift return)] 'smart-open-line-above)

Evaluate the code (or restart Emacs) and you’ll be able to use M-x smart-open-line-above or Control+Shift+Enter (aka C-S-return).

Admittedly this keybinding kind of sucks, so here’s another option for you - M-o (used by default as the prefix for some font setting commands nobody ever uses) for smart-open-line and M-O for smart-open-line-above.

1
2
(global-set-key (kbd "M-o") 'smart-open-line)
(global-set-key (kbd "M-O") 'smart-open-line-above)

Another good option would be to fold the two commands into one and use a prefix argument to trigger the opening a new line above the current one.

This command is part of Prelude(it’s named prelude-smart-open-line-above there).

Using Emacs as a Database Client

| Comments

Most people that use Emacs are programmers - that’s a fact! Most programmers have to deal with relational databases - that’s also a fact!

Programmers often interact with the database they have to use via some dedicated client - be it a console or a GUI one. One fairly little known fact about Emacs is that it features a mode that wraps around terminal database clients, called SQLi. The mode allows you to interact with a relational database from the comfort of Emacs. Sure, you can run a terminal client like psql directly from ansi-term (for instance) as well - but if you’re using a client with no readline support (like the default clients for Oracle and DB2) you’ll certainly appreciate SQLi.

Let’s play a bit with SQLi. To create a PostgreSQL connection start by running M-x sql-postgres. You’ll be prompted for username, database, password and host and then you’ll be dropped in a buffer dedicated to the connection you’ve specified. Apart from being able to run all sorts of SQL in that buffer you’ll also be able to send to it SQL from .sql files you’re editing in Emacs.

Let’s see how you can do that in a bit more detail. First you have to associated an SQL file with a connection. While in some .sql file execute M-x sql-set-product and type postgres. Afterwards do M-x sql-set-sqli-buffer and select the name of the connection buffer you want to use (it’s probably called *SQL* if you have only one connection buffer). Now you’ll be able to use commands like sql-send-region (C-c C-r) from the .sql buffer and the code from the region will be executed in the associated connection buffer.

Have a look at the documentation of sql-mode for further details.

Continue a Comment on the Next Line

| Comments

When writing code from time to time we have to write comments as well. Most of the time programmers are using single-line comments, denoted by some special starting character(s), like #, //, etc. When you want to write a few lines of comments in Emacs you have two options:

Option A

  • Write the first line of the comment.
  • Go to the next line.
  • Insert the comment delimiter.
  • Continue writing the comment.

Option B (editor’s choice)

  • White the first line of the comment.
  • Press M-j (indent-new-comment-line).
  • Continue writing the comment on the second line.

The command breaks the line at point and indents the following line, continuing the comment if invoked within one. The indentation on the second line matches the indentation on the first line.

1
2
3
# first line
#     indented line|(we press `M-j` here)
#     |(we get here after pressing `M-j`)

This command is intended for styles where you write a comment per line, starting a new comment (and terminating it if necessary) on each line. If you want to continue one comment of the type /* */ across several lines, use C-j (newline-and-indent).

Outside of comments M-j behaves pretty much the same way as C-j.