如何替换匹配的括号?


10

我使用Emacs在LaTeX中编写(并重写)了许多数学公式。我经常遇到想要更改一对匹配括号以提高可读性的情况。我的Emacs足够好,可以向我显示匹配的定界符,但是如何以编程方式更改它呢?

例如,一次性更改外部定界符:

( (\sqrt{a} + b)^{-1} + c^{-1} )

[ (\sqrt{a} + b)^{-1} + c^{-1} ]

2
请注意这也将是有趣的,如果这样的代码可以改变如\bigl(...\bigr)\Bigl(...\Bigr)
安德鲁·斯旺

1
在这里,我举了一个使用PEG简化LaTeX语法的示例:emacs.stackexchange.com/questions/36541/…这将是解决此问题的一种方法。
wvxvw

@wvxvw我写这个问题时看着您的方法,确实看起来很有趣!也希望那里有些东西,也许更简单。由于突出显示了Emacs,因此它已经知道匹配的定界符。也许可以利用?
曼卡州


Emacs知道突出显示匹配的定界符,因为该模式实现了forward-sexp-function(我猜是TeX模式实现),或者它将scan-sexps用于查找可能的匹配项。在后一种情况下,匹配并不总是正确的。因此,如果您只需要匹配匹配的定界符,则可以检查点下字符的语法。如果是$,则它必须具有一个匹配项,您可以用来forwad-sexp进行匹配。
wvxvw

Answers:




6

我使用下面的代码并绑定yf/replace-or-delete-pairM-D

用法示例:指向on时(,我命中M-D [,这()对成为一[]对。如果您M-D RET改为点击,则该对将被删除。

该代码使用语法表,这意味着对于某些对,您必须自己指定结束括号。例如,在HTML模式下,()可以通过更换<>击中M-D <。但是,在许多模式<>下都不是公认的对,M-D <而是会说“不知道如何关闭<”。然后就可以键入了>

(defun yf/replace-or-delete-pair (open)
  "Replace pair at point by OPEN and its corresponding closing character.
The closing character is lookup in the syntax table or asked to
the user if not found."
  (interactive
   (list
    (read-char
     (format "Replacing pair %c%c by (or hit RET to delete pair):"
             (char-after)
             (save-excursion
               (forward-sexp 1)
               (char-before))))))
  (if (memq open '(?\n ?\r))
      (delete-pair)
    (let ((close (cdr (aref (syntax-table) open))))
      (when (not close)
        (setq close
              (read-char
               (format "Don't know how to close character %s (#%d) ; please provide a closing character: "
                       (single-key-description open 'no-angles)
                       open))))
      (yf/replace-pair open close))))

(defun yf/replace-pair (open close)
  "Replace pair at point by respective chars OPEN and CLOSE.
If CLOSE is nil, lookup the syntax table. If that fails, signal
an error."
  (let ((close (or close
                   (cdr-safe (aref (syntax-table) open))
                   (error "No matching closing char for character %s (#%d)"
                          (single-key-description open t)
                          open)))
        (parens-require-spaces))
    (insert-pair 1 open close))
  (delete-pair)
  (backward-char 1))


0

匹配的括号用表示show-paren-mode。逻辑方法是将功能更改为相同基础逻辑和功能的基础。突出显示匹配的括号时,可以调用以下toggle-parens定义的函数:

(defun toggle-parens ()
  "Toggle parens () <> [] at cursor.

Turn on `show-paren-mode' to see matching pairs of parentheses
and other characters in buffers. This function then uses the same
function `show-paren-data-function' to find and replace them with
the other pair of brackets.

This function can be easily modified and expanded to replace
other brackets. Currently, mismatch information is ignored and
mismatched parens are changed based on the left one."
  (interactive)
  (let* ((parens (funcall show-paren-data-function))
         (start (if (< (nth 0 parens) (nth 2 parens))
                    (nth 0 parens) (nth 2 parens)))
         (end (if (< (nth 0 parens) (nth 2 parens))
                  (nth 2 parens) (nth 0 parens)))
         (startchar (buffer-substring-no-properties start (1+ start)))
         (mismatch (nth 4 parens)))
    (when parens
      (pcase startchar
        ("(" (toggle-parens--replace "[]" start end))
        ("[" (toggle-parens--replace "()" start end))))))

(defun toggle-parens--replace (pair start end)
  "Replace parens with a new PAIR at START and END in current buffer.

A helper function for `toggle-parens'."
  (goto-char start)
  (delete-char 1)
  (insert (substring pair 0 1))
  (goto-char end)
  (delete-char 1)
  (insert (substring pair 1 2)))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.