4

In some of the modes I'm using, emacs helps me by auto closing some elements such as quotes, parenthesis.

However some times, out of habit I type the closing element my self and end up with ()) or """.

How can I set up emacs to ignore the extra key?

Thomas
  • 17,016
  • 4
  • 46
  • 70
vise
  • 12,713
  • 11
  • 52
  • 64

3 Answers3

8

While it is fun to roll your own, autopair has emerged as the canonical solution to this problem. It does everything you ask, and a few things, you didn't know you wanted. Emacs wiki entry.

Emacs 24 (currently in pretest) will be prepackaged with an electric pairing package. Autopair is still much more sophisticated than the builtin one.

event_jr
  • 17,467
  • 4
  • 47
  • 62
  • Very good. My answer came from the same wiki page you linked to, but I can't remember *when* I actually scooped the code. From a quick test, it looks like autopairs.el works just as well and offers more features at the same time. Thanks! – Tyler Oct 11 '11 at 00:52
  • As a long time user of autopair.el, I can tell you that the built-in electric pairing support in Emacs 24 is hardly inferior. – Bozhidar Batsov Oct 11 '11 at 04:27
  • Maybe I'm missing, but backspacing "(|)" here does not remove the pair, which autopair does. Also autopair has hooks to modify pairing behaviour. For example I have a function that pads braces with spaces for Ruby code, and there is another function that handles triple quotes for Python. – event_jr Oct 11 '11 at 07:16
2

EDIT: I had had the following in my .emacs for a while, and it worked fine so I didn't think too much about it. As event_jr points out in his answer, the same features (and apparently a bit more) can be had with the autopairs.el package, linked from the same page that I got this code from.

I have the following code in my .emacs to do this, taken from the emacs wiki:

(setq skeleton-pair t)

(setq skeleton-pair-alist
      '((?\( _ ?\))
    (?[  _ ?])
    (?{  _ ?})
    (?\" _ ?\")))

(defun autopair-insert (arg)
  (interactive "P")
  (let (pair)
    (cond
     ((assq last-command-char skeleton-pair-alist)
      (autopair-open arg))
     (t
      (autopair-close arg)))))

(defun autopair-open (arg)
  (interactive "P")
  (let ((pair (assq last-command-char
            skeleton-pair-alist)))
    (cond
     ((and (not mark-active)
       (eq (car pair) (car (last pair)))
       (eq (car pair) (char-after)))
      (autopair-close arg))
     (t
      (skeleton-pair-insert-maybe arg)))))

(defun autopair-close (arg)
  (interactive "P")
  (cond
   (mark-active
    (let (pair open)
      (dolist (pair skeleton-pair-alist)
    (when (eq last-command-char (car (last pair)))
      (setq open (car pair))))
      (setq last-command-char open)
      (skeleton-pair-insert-maybe arg)))
   ((looking-at
     (concat "[ \t\n]*"
         (regexp-quote (string last-command-char))))
    (replace-match (string last-command-char))
    (indent-according-to-mode))
   (t
    (self-insert-command (prefix-numeric-value arg))
    (indent-according-to-mode))))

(defun autopair-backspace (arg)
  (interactive "p")
  (if (eq (char-after)
      (car (last (assq (char-before) skeleton-pair-alist))))
      (and (char-after) (delete-char 1)))
  (delete-backward-char arg))

(global-set-key [backspace] 'autopair-backspace)
(define-key isearch-mode-map [backspace] 'isearch-delete-char) ;; required to fix behaviour in isearch

(global-set-key "("  'autopair-insert)
(global-set-key ")"  'autopair-insert)
(global-set-key "["  'autopair-insert)
(global-set-key "]"  'autopair-insert)
(global-set-key "{"  'autopair-insert)
(global-set-key "}"  'autopair-insert)
(global-set-key "\"" 'autopair-insert)
Tyler
  • 9,872
  • 2
  • 33
  • 57
1

I'm not sure if it's Emacs 24 feature only, but electric-pair-mode seems to do what you want.

Tassos
  • 3,158
  • 24
  • 29
  • I already tested out autopair and it works, but I'll check this as well when I'll have some free time on my hands. Thanks! – vise Oct 11 '11 at 12:28