Emacs: как вычислить наименьшее s-выражение, в котором находится курсор, или следующее s-выражение

Какой хороший способ оценить (+ 100 (+ 100 100)) участие в

(+ (+ 1 2) (+ 100 (+ 100 100)))

?

Сейчас я делаю это с помощью Cx Ce, что означает, что мне нужно найти конечную скобку, что в большинстве случаев сложно. Options > Paren Matching Highlighting помогает, но все же мне нужно переместить курсор к конечной скобке, пока выделенное совпадение не станет начальной скобкой.

Одним из способов было бы иметь обратную версию Cx Ce, чтобы я мог поместить курсор в начальную скобку следующим образом:

(+ (+ 1 2) |(+ 100 (+ 100 100)))

и затем нажмите соответствующую связку клавиш.

Или я мог бы поместить курсор внутри выражения, но не внутри меньших выражений:

(+ (+ 1 2) (+ | 100 (+ 100 100)))

и нажмите связывание клавиш. Потому что цель на цель легче, если цель большая.

Как я могу сделать такую ​​команду? Или уже есть один?

Sidenote: курсор курсора и курсор курсора

Emacsers, которые используют курсор курсора (по умолчанию), могут задаться вопросом, куда я помещаю курсор с обозначением панели выше. В Emacs, вы можете выбрать курсор в поле или курсор в виде строки, (bar-cursor-mode t), Когда курсор строки находится между буквами A и B, курсор курсора находится на B. Таким образом, бар является левой стенкой окна.

Кстати, концепция линейного курсора полезна некоторым необычным способом: практика итерации от index1 до index2-1 в программировании удивляет новичков. Это помогает представить, что index1 и index2 обозначают столбцы (левые стены), а не прямоугольники.

4 ответа

Решение

Привязать ключ к одному или обоим из них:

(defun eval-next-sexp ()
  (interactive)
  (save-excursion
    (forward-sexp)
    (eval-last-sexp nil)))

(defun eval-surrounding-sexp (levels)
  (interactive "p")
  (save-excursion
    (up-list (abs levels))
    (eval-last-sexp nil)))

С тангенциальной связью я настоятельно рекомендую paredit для работы с s-выражениями. Команды редактирования структуры и привязки делают редактирование s-выражений быстрым. Это связывает C-вниз up-list, чтобы eval-surrounding-sexp выше почти так же, как C-down Cx Ce (единственное отличие состоит в том, что функция использует save-excursion для предотвращения движения).

Вы можете написать такую ​​команду примерно так:

(require 'thingatpt)
(defun eval-sexp-at-or-surrounding-pt ()
  "evaluate the sexp following the point, or surrounding the point"
  (interactive)
  (save-excursion
    (forward-char 1)
    (if (search-backward "(" nil t)
        (message "%s" (eval (read-from-whole-string (thing-at-point 'sexp)))))))

В Сосульках есть общий способ делать то, что вы хотите.

По умолчанию в минибуфере М-. привязан к команде, которая вставляет текст в (или около) точке в минибуфер (не вводит его и не делает с ним ничего; просто вставляет его).

Вы можете, например, использовать M-: для оценки Lisp sexp, а затем вы используете M-. захватить сексп в / около точки.

Если вы повторите M-. затем он отбрасывает то, что только что схватил, и захватывает какую-то другую вещь (текст) в / около точки и вставляет это. По умолчанию он проходит через эти вещи, в следующем порядке:

а. Символ Lisp или имя файла.

б. Активный регион (выделенный текст) или слово.

с. Самый ближайший список.

д. Следующий по величине список.

е. Следующий по величине список.

е. Какой бы файл или URL функция не ffap-guesser догадок.

г. Какой бы ни была функция URL thing-at-point-url-at-point догадок.

Что это значит для вашего примера (+ (+ 1 2) (+ 100 (+ 100 100))) ?

Если точка до 1 второго до последнего 100 Например, это сексы, которые последовательно вставляются в минибуфер, когда вы нажимаете M-. повторно, по порядку:

а. +

б. 100

с. (+ 100 100)

д. (+ 100 (+ 100 100))

е. (+ (+ 1 2) (+ 100 (+ 100 100)))?

Таким образом, чтобы вставить самый большой из включенных списков, вы должны сделать M-: M-. M-. M-. M-. M-. ударять М-. пять раз.

Для такого поведения, в частности для точного захвата списков, вам также понадобится библиотека Thing At Point +.

Есть встроенный eval-defun, По умолчанию он связан с C-M-x. Это похоже на то, что вы хотите, но уклоняется от определения верхнего уровня. Возможно, вы можете адаптировать это.

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