Как заменить соответствующие скобки?

10

Я пишу (и переписываю) множество математических формул в LaTeX с помощью Emacs. Я часто сталкиваюсь с ситуациями, когда я хочу изменить пару соответствующих скобок, чтобы улучшить читаемость. Мой Emacs достаточно любезен, чтобы показать мне соответствующий разделитель, но как мне изменить его программно?

Например, измените внешние разделители за один раз:

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

в

[ (\sqrt{a} + b)^{-1} + c^{-1} ]
Mankka
источник
2
Обратите внимание, что было бы также интересно, если бы такой код мог измениться, например \bigl(...\bigr)на \Bigl(...\Bigr)и т. Д.
Эндрю
1
Здесь я привел пример упрощенной грамматики LaTeX с использованием PEG: emacs.stackexchange.com/questions/36541/… это был бы один из способов решения этой проблемы.
wvxvw
@wvxvw Я смотрел на твой подход, когда писал этот вопрос, и действительно, он выглядит интересно! А также надеюсь, что есть что-то, возможно, проще, там. Emacs уже знает о соответствующем разделителе, поскольку он выделен. Может быть, это может быть использовано?
Манкка
Emacs знает, как выделить соответствующий разделитель, потому что либо режим реализует forward-sexp-function(что, я предполагаю, TeX mode), либо он будет использовать scan-sexpsдля поиска возможного соответствия. В последнем случае совпадение не всегда будет правильным. Итак, если все, что вам нужно, это сопоставить совпадающие разделители, вы можете проверить синтаксис символа под точкой. Если это так $, то у него должно быть совпадение, и вы можете использовать forwad-sexpего для сопоставления.
wvxvw

Ответы:

2

Используйте smartparensпакет. Он включает в себя функцию под названием sp-rewrap-sexp, которая именно то, что вам нужно. На домашней странице проекта ( https://github.com/Fuco1/smartparens ) есть несколько картинок GIF, наглядно показывающих функциональность.

DXU
источник
7

Для тех, кто использует зло, вы можете использовать злое окружение, которое дает вам c sдвижение (изменить, окружить).

Для вашего примера просто сделайте c s ( [(движение, от типа парен, к типу парен)

Антуан Уилкинсон
источник
Как раз то, что мне было нужно !!! Спасибо!
Хилман
6

Я использую код ниже и привязываю yf/replace-or-delete-pairк M-D.

Пример использования: с точкой (я нажимаю, 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))
YoungFrog
источник
2

ar-parentized2bracketed-atpt сделал бы задачу.

Он приходит вместе со ar-braced2parentized-atptвсеми соответствующими комбинациями.

Получите его из thingatpt-transform-delimited.el из

URL: https://github.com/andreas-roehler/thing-at-point-utils

Абстрактный класс команд преобразует все разделенные формы, например:

ar-delimited2bracketed-atpt

Эти командиры доставляются в том же репо

thingatpt-преобразование унифицированная-delimited.el

Андреас Рёлер
источник
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)))
Хейкки
источник