Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swap parentheses and square brackets in Emacs Paredit

How can I define a command in paredit mode that swaps parentheses and square brackets?

like image 893
namin Avatar asked Dec 04 '22 00:12

namin


2 Answers

So the task is to turn this, for example:

(blah
 (a (b)
    c))

into this:

(blah
 [a (b)
    c])

With paredit mode, move to start of the expression (a ..) and then:

C-M-SPC [ <right> M-s

Without paredit, but still wanting to maintain balanced parens during transitions, move to a and then press C-M-SPC multiple times until error and then (assuming that CUA mode is on):

C-x <timeout> <right> <backspace> <backspace> [ ] <left> C-v

Well that is complex, so let's stick with paredit mode version, and try to make a command out of it. Keyboard Macro Editor tells you the names of commands being used, so you would be able to come up with at least the following code:

(defun my-switch-to-square ()
  "Change (..) to [..]."
  (interactive)
  (mark-sexp --)
  (paredit-open-square --)
  (right-char --)
  (paredit-splice-sexp --))

-- indicates part of code we have not yet decided. After you read documentation of each function in the code, you learn what arguments to pass, and that there is no need to call mark-sexp. After rewriting docstring and adding a call to left-char, the code you end up with would be:

(defun my-switch-to-square ()
  "Change |(..) to |[..]. | is point position."
  (interactive)
  (paredit-open-square 1)
  (right-char 1)
  (paredit-splice-sexp)
  (left-char 1))
like image 190
Jisang Yoo Avatar answered Dec 05 '22 15:12

Jisang Yoo


The following code does what you request. You can bind swap-parens to whatever key binding you want.

(defvar swap-paren-pairs '("()" "[]"))
(defun swap-parens-at-points (b e)
  (let ((open-char (buffer-substring b (+ b 1)))
        (paren-pair-list (append swap-paren-pairs swap-paren-pairs)))
    (while paren-pair-list
      (if (eq (aref open-char 0) (aref (car paren-pair-list) 0))
          (save-excursion
            (setq to-replace (cadr paren-pair-list))
            (goto-char b)
            (delete-char 1)
            (insert (aref to-replace 0))
            (goto-char (- e 1))
            (delete-char 1)
            (insert (aref to-replace 1))
            (setq paren-pair-list nil))
        (setq paren-pair-list (cdr paren-pair-list))))))

(defun swap-parens ()
  (interactive)
  (cond ((looking-at "\\s(")
         (swap-parens-at-points (point) (save-excursion (forward-sexp) (point))))
        ((and (> (point) 1) (save-excursion (forward-char -1) (looking-at "\\s)")))
         (swap-parens-at-points (save-excursion (forward-sexp -1) (point)) (point)))
        ((message "Not at a paren"))))
like image 23
Trey Jackson Avatar answered Dec 05 '22 13:12

Trey Jackson