Я изменяю некоторый код elisp из linum.el:
(custom-set-variables '(linum-format 'dynamic))
(defadvice linum-update-window (around linum-dynamic activate)
(let* ((w (length (number-to-string
(+ (count-lines (point-min) (point-max)) 1))))
(linum-format (concat " %" (number-to-string w) "d ")))
ad-do-it))
Я смог исправить ошибку, когда отступ был один за другим, изменив (count-lines (point-min) (point-max))
на (+ (count-lines (point-min) (point-max)) 1)
. Это было легко.
Но теперь я хочу изменить его так, чтобы минимальная ширина равнялась 2, добавляя условное условие (concat " %" (number-to-string w) "2d ")
if, если число строк равно <10.
Это должно быть легко! Добавьте одно условие и скопируйте / вставьте конкат. Кусок пирога, верно? Я имею в виду, я знаю, что я должен делать, но я редко прикасаюсь к elisp, и я всегда пугаюсь, когда мне нужно что-то изменить с большим количеством скобок.
«Правильный» стиль, насколько я понимаю, состоит в том, чтобы структурировать код на основе отступа и обернуть завершающие скобки в конце строки, а не самостоятельно. Исходя из других языков стиля C, я борюсь с чтением и написанием кода таким образом. Итак, мой вопрос: что я делаю не так? Как я должен редактировать elisp и перемещаться по коду так, чтобы мне не приходилось сидеть там и считать все скобки?
Когда я работаю с чем-то в elisp, которое становится слишком глубоким, мне приходится закрывать дверь, открывать жалюзи и начинать располагать скобки в стиле K & R, чтобы я мог не только читать, но и изменять чертову вещь, не сходя с ума.
Очевидно, я делаю все это неправильно. Как я могу без страха дотронуться до elisp?
Обратите внимание, что мой вопрос заключается в том, как перемещаться и редактировать elisp, а не как вопрос стиля. В качестве руководства по стилю я уже использую следующее: https://github.com/bbatsov/emacs-lisp-style-guide
Обновления:
Как правильно отформатировать elisp перед тем, как смущать себя на emacs.stackexchange:
Отметьте свой elisp и выполните M-x indent-region
.
Решение проблемы:
Для тех, кто хочет знать, как выполнить выравнивание по правому краю для linum с минимальной шириной два, вот решение:
(defadvice linum-update-window (around linum-dynamic activate)
(let* ((w (length (number-to-string
(+ (count-lines (point-min) (point-max)) 1))))
(linum-format (if (> w 1)
(concat " %" (number-to-string w) "d ")
" %2d ")))
ad-do-it))
источник
%2d
потому что, как только ширина переходит к 3 или более символам, она переходит от «выровнять по правому краю» к «выровненному по левому краю»highlight-parentheses
;rainbow-delimiters
; и т.д. Вот моя собственная упрощенная версия,highlight-parentheses
которая разрешает прокрутку без удаления скобок, которые были раскрашены в последний раз: stackoverflow.com/a/23998965/2112489 В будущем это один вопрос для каждого клиента / потока.Ответы:
Существует ряд дополнительных пакетов, которые могут помочь, такие как paredit, smartparens и lispy. Эти пакеты облегчают навигацию и манипулирование кодом lisp, так что вы можете думать в s-выражениях и позволить редактору беспокоиться о балансировке символов в скобках.
В Emacs также есть множество встроенных команд для работы с полами и списками, которые стоит изучить и которые могут помочь вам лучше привыкнуть к структуре кода lisp. Они обычно связаны с
C-M-
префиксом, таким как:C-M-f
/C-M-b
двигаться вперед / назад по полуC-M-n
/C-M-p
двигаться вперед / назад по спискуC-M-u
/C-M-d
двигаться вверх / вниз на один уровеньC-M-t
поменять местами два полаC-M-k
убить сексC-M-SPC
отметить сексC-M-q
сделать отступ в сексеПример кода, который вы предоставили, может быть более понятным, если вы исправите отступ: поставьте точку в начале
(defadvice...
и нажмите,C-M-q
чтобы заново сделать отступ для всего выражения. Чтобы заменить(concat...
I, я должен начать указывать точку в начале этого секса и нажимать,C-M-o
чтобы разделить строку, сохраняя отступ. Затем добавьте свой(if...
и используйте приведенные выше команды, чтобы перейти к концу списка, добавить еще один закрывающий элемент, вернуться к началу, сделать отступ и т. Д.Вы также можете захотеть включить
show-paren-mode
, что будет выделять соответствующую пареню, когда точка находится в начале или конце списка. Вы можете выделить целое выражение, а не соответствующее имя, поэтому попробуйте выполнить настройкуshow-paren-style
.Как упомянул @Tyler в комментариях к другому ответу, вы должны взглянуть на руководство, чтобы узнать больше об этих и связанных с ними командах.
источник
C-M-q
может быть вызван с префиксным аргументом (C-u C-M-q
), чтобы красиво печатать выражение в точке. Это разбьет все на отдельные строки и отступ, так что вложение будет очень очевидным. Как правило, вы не хотите, чтобы ваш код lisp выглядел так, но может быть полезно понять немного кода, не добавляя в него полный код K & R. (И вы всегдаC-x u
можете отменить).Хороший способ редактировать LISP - это манипулировать AST вместо отдельных символов или строк. Я делал это с моим пакетом LISPY, который я начал 2 года назад. Я думаю, что на самом деле может потребоваться немало практики, чтобы научиться делать это хорошо, но даже использование только основ должно уже помочь вам.
Я могу объяснить, как бы я сделал это изменение:
Шаг 1
Стартовая позиция обычно должна иметь точку перед сексом на высшем уровне. Здесь
|
суть.Вы хотите, чтобы код был правильно вставлен, поэтому нажмите iодин раз. Это переопределит это красиво.
Шаг 2
Вы захотите пометить
"d "
область, так как объект, способный к манипулированию, -lispy
это либо список, который не нужно помечать, либо последовательность символов и / или списки, которые необходимо пометить областью.Нажмите, atчтобы сделать это. Команда aпозволяет пометить любой отдельный символ в родительском списке и tявляется индексом этого конкретного символа.
Шаг 3
()
, нажмите (.if
.()
.> w 10
.Шаг 4
Чтобы клонировать строку:
Если вы хотите причудливо деактивировать регион и поставить точку в самом начале строки, вы можете нажать idm:
Или вы могли бы сделать m C-b C-b C-bв этом случае, или C-g C-b C-b C-b. Я думаю, что idmлучше, так как это одинаково, независимо от длины строки. Я думаю, C-x C-x C-f C-g что также будет работать независимо от длины строки.
Наконец, вставьте,
2
чтобы получить код конца:Резюме
Полная последовательность была: at( C-f,
if
, (,> w 10
, C-f C-m M-m cidm,2
.Обратите внимание, что если вы посчитаете вставку кода, единственными ключами, не связанными с манипулированием AST, были два C-fи один C-m.
источник
Со временем вы привыкнете к этому, но, конечно, вы можете многое сделать, чтобы ускорить его:
вдавливание
В этом безумии есть метод. В lisp вы можете сделать это:
Предположим, что
1
это действительно большое выражение, и вы хотите сделать отступ в отдельной строке.Это вводит в заблуждение.
1
отступ в один слот, хотя это целых три уровня вложенности выше! Лучше поставить его своим родителем.Если мы используем эту схему в вашем собственном коде, мы получим это:
Обратите внимание на сильную корреляцию между отступом и уровнем вложенности. Строки с большим уровнем вложенности всегда имеют больший отступ, чем строки с меньшим.
Одно это очень поможет. Вы можете легко увидеть «форму» кода, и большинство других языков научили вас связывать отступы с блоками и блоками с некоторой формой вложенности (явной или подразумеваемой).
В качестве упражнения я удалил несущественные скобки из кода. Вы должны быть в состоянии как прочитать код, так и указать пропущенные скобки, учитывая базовые знания Elisp (а именно, что такое функции и значения, а также структуру
let*
).источник
newline-and-indent
для emacs-lisp-mode и lisp-взаимодействия-mode решает ваш первый пример, PythonNut. И TAB сделает всю оставшуюся работу.Я включил это как другой ответ.
Иногда отступы вас не подведут. Тогда вы можете использовать что-то вроде
rainbow-delimiters
:Это делает уровень вложенности любого парена явным и легко сканируемым.
Однако есть одна довольно большая проблема: паренсы смешно отвлекают. Здесь есть баланс внимания.
rainbow-delimiters
обычно уделяет большое внимание паренсу за счет остальной части вашего кода! Но если вы тонируете радугу лицом вниз, их становится все труднее сканировать.Если вы можете найти один набор граней, который хорошо уравновешивает, тогда обязательно используйте его.
Тем не менее, одно из решений (которое заставляет меня хихикать от радости) - это иметь два набора лиц и переключаться между ними на лету. Когда вы делаете что-то другое, лица становятся размытыми и уходят на второй план:
Но когда вы ставите точку на скобке, она пробивает скобки, чтобы вы могли видеть уровни вложенности:
И вот код для этого:
источник
Если вы делаете отступ для своего кода, тогда вам действительно нужно правильно сделать отступ. Разработчики Lisp ожидают, как должен выглядеть правильный отступ. Это не значит, что код выглядит одинаково. Есть еще разные способы форматирования кода.
Я ожидал бы, что отступ показывает сдерживание в некотором роде. Но не в вашем коде.
По умолчанию ваш код может иметь такой отступ. Другие ответы описывают, как вы можете сделать это с помощью Emacs:
Я ожидаю, что
let
связанные переменные начинаются в том же вертикальном столбце. Я хотел бы также ожидать , что тело изlet
менее отступа. Мы узнаем, какlet
должен быть отступ. Если вы немного потренируетесь, это визуальный шаблон, который легко распознать.Основные визуальные блоки в коде являются
defadvice
,let*
и куча вызовов функций. Вdef
имени говорится, что это определение, за которым следуют имя, список аргументов и тело.Так мне нравится видеть
let*
Будет:let*
, список привязок и тела.Так мне нравится видеть:
Более подробный:
Для вызова функции мне нравится видеть:
или
или
Какой из них использовать, зависит от того, как долго аргументы. Мы не хотим делать строки слишком длинными, и каждый аргумент в отдельной строке позволяет нам иметь больше структуры.
Поэтому вам нужно написать свой код, используя эти шаблоны, и вы должны убедиться, что читатель может легко идентифицировать эти шаблоны в вашем коде.
Круглые скобки должны напрямую заключать их конструкции.
Избегайте пробельных примеров:
или
или
В Лиспе круглые скобки не имеют синтаксической функции языка, они являются частью синтаксиса структуры данных списка (s-выражений). Таким образом мы пишем списки и форматируем списки. Для форматирования содержимого списка мы используем знания о языке программирования Lisp.
let
Выражение должно быть отформатирован иначе , чем вызов функции. Тем не менее, оба списка являются списками, и скобки должны непосредственно включать списки. Есть несколько примеров, в которых имеет смысл иметь одну скобку в строке, но используйте это редко.Используйте скобки, чтобы помочь вам найти границы выражения. Позвольте им помочь вам переходить от списка к списку, редактировать списки, вырезать и копировать списки, заменять списки, делать отступы / форматировать списки, выбирать списки, ...
источник
Для базовой помощи с отступом используйте TAB и "CMq" (
indent-pp-sexp
); Привязка "Cm"newline-and-indent
избавит вас от необходимости нажимать клавишу TAB после новой строки.Вы можете перемещаться по полу с помощью «CM-left / right / up / down / home / end», что очень полезно.
Если вы беспокоитесь о сохранении баланса скобку, использовать что - то вроде smartparens (это немного более прощающий , что paredit , который первоначально может чувствовать себя как носить смирительную). Он также поставляется с большим количеством привязок для навигации и редактирования на уровне пола.
Наконец, для выделения паренов, начните с включения опции (меню Параметры-> Выделить соответствующие скобки или
show-paren-mode
.) Вы также можете использовать один из пакетов, упомянутых в списке комментариев в его комментарии, например, «подсветка скобок» или «разделители радуги». ».источник
В дополнение к тому, что другие дали в качестве ответов, вот мои 2 цента:
emacs-lisp-mode
является существенным.blink-matching-paren
включен (неnil
) по умолчанию. Оставь это так.show-paren-mode
, чтобы выделить левую часть, соответствующую правой части перед курсором.Я не пользуюсь электрическим сопряжением или радугой или чем-то подобным. Для меня это беспокойство, а не помощь.
В частности
electric-pair-mode
, мне неудобно беспокоиться. Но некоторые люди любят это. И я полагаю, что это может быть полезно в некоторых других контекстах сопряжения, кроме скобок Lisp (я так думаю, но я не убежден и в таких случаях использования).Вы найдете то, что работает лучше для вас. Основные вещи, которые я хочу сказать: (1) автоматический отступ - это ваш друг, так же как и какой-то способ определить левую часть, которая соответствует правой части до точки.
В частности, видя, что автоматическое отступление делает для вас, вы сразу же узнаете, что вам больше никогда не захочется ставить правильные символы в ряд. Такой стиль кодирования, который вездесущ в других языках, просто шумный.
Помимо автоматического отступа, который вы получаете с
RET
иTAB
, получите удобное использованиеC-M-q
. (ИспользованиеC-h k
в ,emacs-lisp-mode
чтобы узнать, что делают эти ключи.)источник
Я заметил, что некоторые люди уже упоминали радужные разделители, это также мой любимый режим при редактировании кода lisp.
На самом деле я люблю круглые скобки, лучше всего в Lisp это круглые скобки, с ними интересно иметь дело, если ты знаешь как:
установите evil-mode и его плагин evil -round, чтобы вы могли легко редактировать круглые скобки, например, press
ci(
удалит все внутри()
,va(
выберет вещи, завернутые в «()» и «()». и вы можете нажать,%
чтобы перейти между соответствующими скобкамииспользуйте flycheck или flymake, непрямые скобки будут подчеркнуты в реальном времени
источник
Сложность в том, что вы хотите добавить некоторый код до и после определенного
sexp
. В этой ситуации секс есть(concat " %" (number-to-string w) "d ")
. Вы хотите вставить оператор if(if (> w 1)
перед ним и оператор else" %2d ")
после него.Основная сложность заключается в том, чтобы изолировать это
sexp
, лично я использую приведенную ниже команду для изоляцииsexp
Просто поместите курсор в начало
(concat " %" (number-to-string w) "d ")
, т. Е. На первое(
, а затем примените вышеуказанноеisolate-sexp
. Вы получаетеЗатем добавьте соответствующий код до и после этого
sexp
, т.е.И вуаля. Полученный таким образом код, возможно, не красив, но вероятность потеряться меньше.
источник