Como substituir parênteses correspondentes?

10

Eu escrevo (e reescrevo) muitas fórmulas matemáticas no LaTeX com o Emacs. Frequentemente encontro situações em que quero alterar um par de parênteses para melhorar a legibilidade. Meu Emacs tem a gentileza de me mostrar o delimitador correspondente, mas como faço para alterá-lo programaticamente?

Por exemplo, altere os delimitadores externos de uma só vez:

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

para

[ (\sqrt{a} + b)^{-1} + c^{-1} ]
Mankka
fonte
2
Nota também seria interessante se esse código poderia mudar por exemplo, \bigl(...\bigr)para \Bigl(...\Bigr)etc.
Andrew Swann
11
Aqui dei um exemplo de gramática simplificada do LaTeX usando o PEG: emacs.stackexchange.com/questions/36541/…. Essa seria uma maneira de abordar esse problema.
Wdxvw
@wvxvw Eu olhei para a sua abordagem quando escrevi esta pergunta e, de fato, parece interessante! Também espero que exista algo, talvez mais simples, por aí. O Emacs já está ciente do delimitador correspondente, pois é destacado. Talvez isso possa ser aproveitado?
Mankka
O Emacs sabe destacar o delimitador de correspondência porque o modo é implementado forward-sexp-function(o que, suponho, o modo TeX), ou será usado scan-sexpspara encontrar a possível correspondência. No caso posterior, a correspondência nem sempre estará correta. Portanto, se tudo o que você precisa é corresponder aos delimitadores correspondentes, é possível verificar a sintaxe do personagem sob o ponto. Se for $, tem que ter uma correspondência, e você pode usar forwad-sexppara chegar à sua correspondência.
Wdxvw

Respostas:

5

Eu uso o código abaixo e vinculo yf/replace-or-delete-paira M-D.

Exemplo de uso: com o ponto ativado (, eu acerto M-D [e o ()par se torna um []par. Se você acertar M-D RET, o par será removido.

Esse código usa a tabela de sintaxe, o que significa que, para alguns pares, você precisará especificar o parêntese de fechamento. por exemplo, no modo html, ()pode ser substituído <>por pressionando M-D <. No entanto, em muitos modos, <>não é um par reconhecido e M-D <diz "Não sei como fechar <". Você pode então apenas digitar >.

(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
fonte
7

Para aqueles que usam o mal, você pode usar o surround do mal, que oferece o c smovimento (mudar, surround).

Para o seu exemplo, basta fazer c s ( [(movimento, do tipo de paren para o tipo de paren)

Anntoin Wilkinson
fonte
Apenas o que eu precisava !!! Obrigado!
Hilman
2

ar-parentized2bracketed-atpt faria a tarefa.

Ele vem junto ar-braced2parentized-atpte basicamente todas as respectivas combinações.

Obtenha-o em thingatpt-transform-delimited.el de

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

Uma classe abstrata de comandos transforma todas as formas delimitadas, por exemplo:

ar-delimited2bracketed-atpt

Esses comandos são entregues no mesmo repositório por

thingatpt-transform-generic-delimited.el

Andreas Röhler
fonte
0

Os parênteses correspondentes são visualizados com show-paren-mode. A abordagem lógica é basear a função para alterar parênteses para a mesma lógica e função subjacentes. Quando as parênteses correspondentes estão destacadas, você pode chamar a função toggle-parensdefinida abaixo:

(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)))
Heikki
fonte