hack on match-paren

I used to use a short code "match-paren" (http://grok2.tripod.com/) when I program, especially in Lisp where parentheses are everywhere. I like this piece of code, for its simplicity and usefulness: if you bind this code to something like M-[, and when you press M-[ on a "(", the cursor goes to the matching ")" automatically. This also works when mark is activated, so you can highlight the region between two matching "(" and ")" very easily. The original code is as follows:

(defun match-paren (arg)
"Go to the matching paren if on a paren."
(interactive "p")
(cond ((looking-at "\\s\(") (forward-list 1) (backward-char 1))
((looking-at "\\s\)") (forward-char 1) (backward-list 1))))

Then sometimes I found that the code does not always work intuitively, especially when I want to highlight a region with the matching "(" and ")", so I did the following hack:
(1) when you keep hitting the key-binding, e.g., M-[, the cursor jump back and forth between its original locations, not like the original code
(2) when the mark is active, the cursor jump to the matching parenthesis and move forward one step after reaching ")" or backward one step after reaching "(", so the highlighted region contains everything between (and including) the matching "(" and ")". I found this especially useful when you want to cut a list out when programming in Lisp.

Here is my hack.

(defun da-match-paren (arg)
"Go to the matching paren if on a paren."
(interactive "p")
(cond ((and mark-active (looking-at "\\s\(")) (forward-list 1))
((and mark-active (looking-back "\\s\)")) (backward-list 1))
((looking-at "\\s\(") (forward-list 1) (backward-char 1))
((looking-at "\\s\)") (forward-char 1) (backward-list 1))
))
(global-set-key (kbd "M-[") ‘da-match-paren)

Advertisements

7 thoughts on “hack on match-paren

    • I never used paredit, but I looked at the wiki page and the demo (http://img8.imageshack.us/img8/9479/openparen.gif), it’s pretty cool. Actually I have similar implementation for automatically generating () [] {} …, i.e., some code like:

      (defun my-general-mode-auto-pair ()
      “Auto pair the matching parentheses.”
      (interactive)
      (make-local-variable ‘skeleton-pair-alist)
      (setq skeleton-pair-alist ‘(
      (?’ _ “‘”)
      (?\” _ “\””)
      (?\( _ “)”)
      (?\[ _ “]”)
      (?{ \n > _ \n ?} >)))
      (setq skeleton-pair t)
      (local-set-key (kbd “(“) ‘skeleton-pair-insert-maybe)
      (local-set-key (kbd “{“) ‘skeleton-pair-insert-maybe)
      (local-set-key (kbd “‘”) ‘skeleton-pair-insert-maybe)
      (local-set-key (kbd “\””) ‘skeleton-pair-insert-maybe)
      (local-set-key (kbd “[“) ‘skeleton-pair-insert-maybe))

      I use this para-match as a short implementation for jumping back and forth. I may give paredit a try. Thanks for the note.

    • Yeah, I love that mode and it’s always on. Sometimes I just found ( and ) are pretty far away and I want to jump to the other side of the block, and sometimes I want to mark the whole block. That’s why I hacked this code. Thanks for the note.

  1. The built-in sexp functions do the same thing and have default bindings:

    C-M-f – forward-sexp
    C-M-b – backward-sexp
    C-M-@ – mark-sexp

    With point on a (, C-M-f jumps you to the closing paren. It also works with strings or curly braces for C-style languages.

    Emacs also has insert-pair, which serves the same purpose as your skeleton-pair code (and has many pairs predefined). I prefer to explicitly request pair insertion, so it’s bound to M-(, M-[, M-“, M-‘, C-c {, etc.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s