Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intelligent auto closing matching characters

Tags:

emacs

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?

like image 559
vise Avatar asked Dec 21 '22 07:12

vise


2 Answers

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.

like image 82
event_jr Avatar answered Dec 27 '22 10:12

event_jr


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)
like image 34
Tyler Avatar answered Dec 27 '22 11:12

Tyler