在Emacs Paredit中交换括号和方括号

6
我该如何在paredit模式下定义一个命令,使括号和方括号互换?

应该用[...]替换(...)还是用[(...)]替换([...]) - Reactormonk
5个回答

11

所以任务就是将这个例子变成这样:

(blah
 (a (b)
    c))

变成这样:

(blah
 [a (b)
    c])

使用 paredit 模式,移动到表达式 (a ..) 的开头,然后执行以下操作:

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

如果没有 paredit,但仍希望在转换期间保持平衡的括号,请移动到 a,然后多次按下 C-M-SPC 直到出现错误,然后(假设 CUA 模式已打开):

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

这很复杂,所以我们将坚持使用paredit模式版本,并尝试将其制作成一个命令。键盘宏编辑器会告诉您正在使用的命令名称,因此您至少能够得出以下代码:

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

-- 指代我们尚未决定的代码部分。在阅读代码中每个函数的文档后,您可以了解要传递哪些参数,并且不需要调用 mark-sexp。重写函数说明文档并添加一个对 left-char 的调用后,您将得到以下代码:

(defun my-switch-to-square ()
  "Change |(..) to |[..]. | is point position."
  (interactive)
  (paredit-open-square 1)
  (right-char 1)
  (paredit-splice-sexp)
  (left-char 1))

6
以下代码实现了您的要求。您可以将swap-parens绑定到任何想要的按键组合。
(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"))))

2

我不确定你所说的“定义命令”的意思是什么?您可以像这样执行:

|(foo bar)

“|”代表的是点号。
;; Keyboard Macro Editor.  Press C-c C-c to finish; press C-x k RET to cancel.
;; Original keys: C-u [ C-f <M-up> C-b

Command: last-kbd-macro
Key: none

Macro:

C-u [       ;; paredit-open-square
C-f         ;; forward-char
<M-up>      ;; paredit-splice-sexp-killing-backward
C-b         ;; backward-char

说实话,这种使用场景更多是用于VIM的技巧。我从未在现实生活中使用过它。


0

bzr branch lp:s-x-emacs-werkstatt

这将提供一个受 paredit 启发的库,但提供更详细的命令

M-x ar-bracket-parentized-atpt RET

在光标处加上括号

查看 thing-at-point-utils.el 和其他文件中提供的内容


0
这里有一个通用版本,可以使用您喜欢的任何类似paredit的工具,在S表达式内的任何位置之间循环切换括号、方括号和花括号。它在这里使用了轻量级的 puni,但 smartparens 和 paredit 都有它们自己的等效 *-wrap-* 和 splice 函数。
(defun cycle-pairs ()
  "Toggle parens, braces, brackets."
  (interactive)
  (save-excursion
    (when (not (string-match-p (regexp-quote (char-to-string (char-after))) "([{"))
      (backward-up-list)
      (when (eq ?\" (char-after)) ; up again if inside string
        (backward-up-list)))
    (progn
      (cl-case (char-after)
        ;; These can be substituted
        (?\( (puni-wrap-square))
        (?\[ (puni-wrap-curly))
        (?\{ (puni-wrap-round))
        ;; (?\< "(")
        )
      (forward-char)
      (puni-splice)))) ; also substituted


这可以扩展来处理括号、引号等。自己编写这个的一个很大的优势是因为其他一些解决方案依赖于大量的软件包,而你可能不想将它们引入到你的Emacs中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接