2010-06-17

automatic pairing of brackets and quotes

Some text-editors, notably TextMate for MacOS, have a nice feature where inserting a opening ( will automatically insert the closing ), and put the cursor in between them (and does same for [], {}, and various quote-marks).

Not surprisingly, there are some implementations for emacs as well; the best one I have found so far is called autopair, which was written by João Távora. It usually does things just right. Do things 'just right' is essential for such a tool; even small annoyances can disturb your flow. Autopair tries to do whatever makes the most sense for a given mode (programming language etc.), but it can be tuned as well.

After installation, you can automatically activate it for all modes with (in your .emacs):

(require 'autopair)
(autopair-global-mode 1)

Now, evaluate this or restart emacs, and enjoy the autopairing-magic!

Except for autopairing, autopair also takes care of autocleaning; that is, if I press ( it turns that into () (the pairing part), and if I press Backspace then, it removes the whole () (the cleaning part). This makes things much less annoying if you type a pair by accident. Autopairing is the kind of thing that can get annoying quickly if it does not things exactly right – and autopair succeeds!

Another nice trick it offers is autowrapping – that is, I select a word, press ", and automatically it's turned into "word". To enable that, you need to add the following:

(setq autopair-autowrap t)

Note: you might want to see the notes below about delete-selection-mode and cua-mode.

Anyway, autopair with autowrap makes for a really smooth editing experience, I love it! There are two small issues for me though. First, when the cursor in front of some non-whitespace, I'd like autopairing not to happen, and second, somehow I can't seem to get "-autopairing to work in org-mode; of course, that could be my own fault. These things might be tunable; I haven't tried very hard yet.

delete-selection-mode

Important to mention here is that autopair is (by default) not fully compatible with delete-selection-mode. As you may know, that is the mode that causes emacs to replace the current selection with a character typed, similar to what most other programs do. I think many people have it enabled in their .emacs with something like:

(delete-selection-mode 1)

If you want to keep on using that together with autopair, add the following to your .emacs:

(put 'autopair-insert-opening 'delete-selection t)
(put 'autopair-skip-close-maybe 'delete-selection t)
(put 'autopair-insert-or-skip-quote 'delete-selection t)
(put 'autopair-extra-insert-opening 'delete-selection t)
(put 'autopair-extra-skip-close-maybe 'delete-selection t)
(put 'autopair-backspace 'delete-selection 'supersede)
(put 'autopair-newline 'delete-selection t)

But, not that that still won't give you the autowrap behavior mentioned above. For that, we can use cua-mode.

cua-mode

We discussed CUA-mode before, focusing on its nice rectangle-editing features. But CUA-mode can also be an alternative for delete-selection-mode, and it goes together more nicely with autopair; so, instead of delete-selection-mode and the put's, add the following to your .emacs:

(setq cua-enable-cua-keys nil)           ;; don't add C-x,C-c,C-v
(cua-mode t)                             ;; for rectangles, CUA is nice

See the linked CUA-mode article for the 'why' of that first line. With this change, autopair should be working smoothly, including autowrap.

further customization

As I have hinted at, autopair can be tuned for different modes, and can differentiate between it's behaviour in literal strings, code, comments etc. The default are usually sane, but if you're interested, have a look at the documentation, in particular autopair-extra-pairs and the More tricks-section in the documentation.

15 comments:

p4bl0 said...

Thanks. I was using skeleton-pair and was not satisfied with it. Mostly because of the deleting that doesn't work.

a said...

I should give it a shot. FWIW, I use paredit for lisp and love that - check it out.

Erik said...

I'm not entirely sure I understand how the auto-skipping works - to get out of, say, a '()' pair, are you supposed to hit ')'? That would sort of defeat what I assumed would be the purpose - to require fewer key presses.

djcb said...

@Erik: well, when your have typed foo(, automatically foo() appears, with the cursor between the (). Now, if you want to go past the (), simply press the right arrow key or C-f.

As an extra convenience, e.g. if you're typing quickly, and type foo() [ie., you manually enter the right-)] autopair will still do the right thing and move past the right-), so the end result is still foo() and not foo())

Just try it :)

Alex Ott said...

Look to paredit - this is wonderful mode, especially when you're working with Lisps. It allows to manipulate s-expressions, etc.

Anonymous said...

Wow, that is the exhaustive answer to all bracket pairing questions. So far I only used M-(, which only creates () and places the point in the middle.

Unknown said...

Very nice!

Thanks for the update.

Anonymous said...

I've been using this for a few weeks, and generally like it. The only annoyance is that autoskip doesn't work with "$" in LaTeX mode; since "$$" is also a valid delimiter. I was trying to fix it via some customizations, as per the docs, but haven't succeeded thus far.

Oscar said...

I discovered autopair a few weeks ago too - it's extremly handy!

It's funny, it feels like the younger users of emacs are more prone to introduce features from modern editors that the old emacs users loathe. Like SlickCopy, autopair and visual-line-mode. Just a tiny reflection.

Anyways - autopair mode is good almost everywhere, except for IRC. Since I use ERC for my IRC needs, and since I got pretty tired of typing :( C-d to avoid having my sad smilies looking like :(), I found this on the autopair-homepage and adopted it for ERC usage instead. So, here it is, hope it helps someone!

(add-hook 'erc-mode-hook
#'(lambda () (setq autopair-dont-activate t)))

João Távora - 6311 said...

In the very latest version (not 0.3) , which you can download from http://autopair.googlecode.com/svn/trunk/autopair.el, the problems with delete-selection-mode and cua-mode have hopefully been addressed, that is it should work correctly and likewise with both extensions, although I have used some monkey-patching techniques.

I will release that version if I get enough positive feedback...

I also encourage people to use http://code.google.com/p/autopair/issues/list so I can keep track of issues and the wishlist.

djcb said...

@Oscar: good point about old vs new. I think the conservatism has been good for
emacs (after all GNU/Emacs is still relevant after more than a quarter
century). On the other hand, I hope some new ideas can be introduced without
breaking things for long-time users. I would say transient-mark-mode,
delete-selection-mode, visual-line-mode, CUA's rectangle editing stuff make for
a better editing experience.

@capitaomorte: thank you for creating autopair!

Anonymous said...

This mode's great but I have the same problem with org-mode. I've added an issue on the project's page. If anyone find a workaround, please, post a comment !

Anonymous said...

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

June 25th 2010 in emacs-fu.blogspot.com

Hi.

A similar, lisp-specific minor mode is paredit, which offers several
other commands for handling S-expressions:
http://mumble.net/~campbell/emacs/paredit.el.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEAREIAAYFAkwlEOUACgkQZ4DA0TLic4gKZQCdFWNvm43bJ54ElLCAfzklPTJc
/LsAn0ZCwXFnu1q4LtGu07F51u4WyyUg
=hhgY
-----END PGP SIGNATURE-----

Anonymous said...

Looks a lot like: http://github.com/rejeep/wrap-region

Fuco said...

Hi.

I'm gonna necro this blog post and provide another alternative. There's a recently started new project that deals with auto-insertion of pairs, wrapping of regions, navigation around balanced expressions and much much more. The list of features is too long to give here, so I'll just link to the smartparens github repo where you can read detailed readme.

It is superset of the aforementioned AutoPair and provide most of the core features of paredit (and extended to all kinds of different pairs, not only those recognized by emacs syntax-tables).