Поменяйте скобки и квадратные скобки в Emacs Paredit

Как определить команду в режиме паредита, которая меняет скобки и квадратные скобки?

5 ответов

Решение

Следующий код делает то, что вы запрашиваете. Вы можете связать 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"))))

Так что задача состоит в том, чтобы включить это, например:

(blah
 (a (b)
    c))

в это:

(blah
 [a (b)
    c])

В режиме паредита, перейти к началу выражения (a ..) а потом:

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

Без паредита, но все еще желая сохранить сбалансированные парены во время переходов, перейдите к 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))

Я не уверен, что вы подразумеваете под "определить команду"? Вы можете сделать это так:

|(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. Я никогда не использовал этот IRL.

bzr ветвь lp:sx-emacs-werkstatt

поставит библиотеку, вдохновленную paredit, но предоставляя более подробные команды

Mx ar-bracket-parentized-atpt RET

ставит скобки вокруг парентезы в точку

загляните внутрь thing-at-point-utils.el и других файлов, что еще предусмотрено

Вот общая версия, в которой можно использовать любой двоюродный брат, похожий на paredit, который вам нравится, для переключения между круглыми, квадратными и фигурными скобками - из любого места внутри sexp. Здесь используется облегченный puni , но у smartparens и paredit есть свои эквиваленты.*-wrap-*и функции сращивания.

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

Другие вопросы по тегам