Я новичок в lisp, и у меня возникают проблемы с выяснением, как создать макрос в emacs со следующей функциональностью: допустим, я устал писать шаблон в c ++ для цикла for:
for (int i = 0; i < N; i++) {
}
Назовите этот макрос «forloop», тогда я хотел бы сделать следующее: когда я набираю «M-x forloop», макрос печатает
for (int
в буфере и ждет ввода. Затем я набираю «i» и нажимаю return, после чего макрос продолжается и печатает
for (int i = 0; i <
И снова ждет ввода. Наконец, после того, как я набрал «N» и нажал «Return», макрос завершил работу, напечатав остаток:
for (int i = 0; i < N; i++) {
}
После продолжительного чтения и тестирования я смог написать простые функции lisp, создать свои собственные макросы, сохранить их, вызвать их и т. Д., Но я все еще не могу понять, как создать макрос, который выполняет что-то вроде Я описал выше. Любые мысли будут высоко ценится! Заранее спасибо!
Такие макросы могут быть очень полезны для ускорения кодирования на любом языке. Я бы предпочел, чтобы макрос был динамическим описанным способом, чтобы вам не приходилось запоминать, сколько аргументов ему нужно и в каком порядке они идут при его вызове.
Я пользуюсь ясниппет (http://www.emacswiki.org/emacs/Yasnippet) для этого, но есть много других решений.
В yasnippet вы вводите ключевое слово для своего фрагмента (скажем, для), затем комбинацию клавиш yasnippet, затем у вас есть поле для заполнения, используя tab для перехода от одного поля к следующему.
Каждый фрагмент определен в своем собственном файле в некотором простом для изучения DSL.
Я не знаю ничего лучше, чем yasnippet
для этой проблемы.
Вот соответствующий фрагмент:
# -*- mode: snippet -*-
#name : for (...; ...; ...) { ... }
# --
for (unsigned int ${1:i}=0; $1<${2:N}; ++$1)$0
Обратите внимание, что есть два аргумента (ноль — точка выхода),
оба имеют значения по умолчанию, но вы можете изменить их, просто набрав.
yasnippet
Я настоятельно рекомендую связать yas/expand
в C-O, так что
не конфликтует с auto-complete-mode
,
Связывание по умолчанию для этого ярлыка практически бесполезно, но оно находится в
отличная позиция:
(global-set-key "\C-o" 'aya-open-line)
(defun aya-open-line ()
(interactive)
(cond ((expand-abbrev))
((yas/snippets-at-point)
(yas/next-field-or-maybe-expand-1))
(((yas/expand)))))
Таким образом, ярлык для расширения и перехода к следующему полю
это то же самое, что делает вас очень быстрым.
Также обратите внимание, что expand-abbrev
имеет приоритет: вы можете заполнить
таблица сокращений для c++-mode
за то, что вы используете.
Аббревиатуры не принимают аргументов, но все они живут в одной таблице,
вместо каждого яснипета, живущего в своем собственном файле, так что это
очень легко редактировать сокращения.
Я бы не рекомендовал ставить брекеты в yasnippet
,
так как иногда они вам нужны, а иногда нет.
Я использую эту функцию вместо:
(defun ins-c++-curly ()
"Insert {}."(interactive)
(if (looking-back "\\()\\|try\\|else\\|const\\|:\\)$")
(progn
(insert " {\n\n}")
(indent-according-to-mode)
(forward-line -1)
(indent-according-to-mode))
(insert "{}")
(backward-char))
Вы можете увидеть похожие макросы в sgml-mode.el
, например html-href-anchor
, который вставляет якорь HREF (очевидно :-).
Вы получите более конкретные ответы, если пометите это как [elisp].
Если вы читаете это и задаетесь вопросом, как именно сделать то, что я просил с помощью yasnippit, вот мой файл yasnippit:
# name: fori ... { ... }
# key: fori
# --
for (int ${1:intname} = 0; ${1:$(yas-substr text "[^: ]*")} < ${2:max}; ${1:$(yas-substr text "[^: ]*")}++) {
$0
}
Обратите внимание, что в yasnippit уже есть функция для for в режиме c ++, но мне не понравилось, как она себя ведет.
Вывод, ясниппит — это круто и супер просто! Спасибо за предложение!