Как заставить Emacs развернуть блок кода?
-
09-06-2019 - |
Вопрос
Допустим, у меня есть строка в буфере emacs, которая выглядит следующим образом:
foo -option1 value1 -option2 value2 -option3 value3 \
-option4 value4 ...
Я хочу, чтобы это выглядело вот так:
foo -option1 value1 \
-option2 value2 \
-option3 value3 \
-option4 value4 \
...
Я хочу, чтобы каждая пара параметр / значение находилась в отдельной строке.Я также хочу, чтобы эти последующие строки имели соответствующий отступ в соответствии с режимом, а не добавляли фиксированное количество пробелов.Я бы предпочел, чтобы код работал с текущим блоком, останавливаясь на первой непустой строке или строке, которая не содержит пары параметр / значение, хотя я мог бы согласиться на то, что он работает в выбранном регионе.
Кто-нибудь знает о функции elisp для этого?
Решение
Ни у кого не было того, что я искал, поэтому я решил стереть пыль со своего руководства по elisp и сделать это сам.Кажется, это работает достаточно хорошо, хотя результат не совсем тот, о котором я просил.В этой версии первый вариант отображается в строке сам по себе вместо того, чтобы оставаться в первой строке, как в моем первоначальном вопросе.
(defun tcl-multiline-options ()
"spread option/value pairs across multiple lines with continuation characters"
(interactive)
(save-excursion
(tcl-join-continuations)
(beginning-of-line)
(while (re-search-forward " -[^ ]+ +" (line-end-position) t)
(goto-char (match-beginning 0))
(insert " \\\n")
(goto-char (+(match-end 0) 3))
(indent-according-to-mode)
(forward-sexp))))
(defun tcl-join-continuations ()
"join multiple continuation lines into a single physical line"
(interactive)
(while (progn (end-of-line) (char-equal (char-before) ?\\))
(forward-line 1))
(while (save-excursion (end-of-line 0) (char-equal (char-before) ?\\))
(end-of-line 0)
(delete-char -1)
(delete-char 1)
(fixup-whitespace)))
Другие советы
В этом случае я бы использовал макрос.Вы можете начать запись макроса с помощью C-x ( и прекратить запись с помощью C-x ).Если вы хотите воспроизвести макрос, введите C-x e.
В этом случае я бы ввел C-a C-x ( C-s v a l u e C-f C-f \ RET SPC SPC SPC SPC C-x)
Это позволило бы записать макрос, который выполняет поиск "значения", перемещается вперед на 2, вставляет косую черту и перевод строки и, наконец, помещает новую строку через пробел, чтобы выровнять.Затем вы могли бы повторить этот макрос несколько раз.
Редактировать:Я только что понял, что ваш буквальный текст может быть не так прост для поиска, как "value1".Вы также можете искать пробелы и циклически просматривать обращения.Например, нажмите C-s несколько раз после первого матча, чтобы пропустить некоторые матчи.
Примечание:Поскольку ваш пример является "ad-hoc", это решение тоже будет таким.Часто вы используете макросы, когда вам нужно специальное решение.Один из способов сделать применение макроса более последовательным - поместить все исходные инструкции в одну строку (также это можно сделать с помощью макроса или вручную).
Редактировать:Спасибо за комментарий по поводу ( против C-(, вы были правы в моей ошибке!
Лично я занимаюсь подобными вещами постоянно.
Но я не пишу функцию для этого, если только я не буду делать это каждый день в течение года.
Вы можете легко сделать это с помощью query-replace, вот так:
m-x (запрос-замена " -option" "^Q^J -option")
Я говорю ^Q^ J, поскольку именно это вы введете, чтобы заключить в кавычки новую строку и поместить ее в строку.
Затем просто нажмите "y", чтобы заменить строки, и "n", чтобы пропустить странные угловые случаи, которые вы найдете.
Другой рабочей лошадкой является функция query-replace-regexp, которая может выполнять замены регулярных выражений.
а также grep-query-replace, который выполнит запрос-замену путем синтаксического анализа выходных данных команды grep.Это полезно, потому что вы можете выполнить поиск для "foo" в 100 файлах, затем выполнить запрос-замену для каждого вхождения переход от файла к файлу.
Возможно, ваш режим уже поддерживает это.По крайней мере, в режиме C и режиме Makefile M-q (заполняющий абзац) вставит продолжения строк в столбец заполнения и завершит ваши строки.
В каком режиме вы это редактируете?