Как создать макрос emacs для текстовых шаблонов

Я новичок в 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, создать свои собственные макросы, сохранить их, вызвать их и т. Д., Но я все еще не могу понять, как создать макрос, который выполняет что-то вроде Я описал выше. Любые мысли будут высоко ценится! Заранее спасибо!

Такие макросы могут быть очень полезны для ускорения кодирования на любом языке. Я бы предпочел, чтобы макрос был динамическим описанным способом, чтобы вам не приходилось запоминать, сколько аргументов ему нужно и в каком порядке они идут при его вызове.

0

Решение

Я пользуюсь ясниппет (http://www.emacswiki.org/emacs/Yasnippet) для этого, но есть много других решений.

В yasnippet вы вводите ключевое слово для своего фрагмента (скажем, для), затем комбинацию клавиш yasnippet, затем у вас есть поле для заполнения, используя tab для перехода от одного поля к следующему.

Каждый фрагмент определен в своем собственном файле в некотором простом для изучения DSL.

1

Другие решения

Я не знаю ничего лучше, чем 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))
1

Вы можете увидеть похожие макросы в sgml-mode.el, например html-href-anchor, который вставляет якорь HREF (очевидно :-).

Вы получите более конкретные ответы, если пометите это как [elisp].

0

Если вы читаете это и задаетесь вопросом, как именно сделать то, что я просил с помощью 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 ++, но мне не понравилось, как она себя ведет.

Вывод, ясниппит — это круто и супер просто! Спасибо за предложение!

0
По вопросам рекламы [email protected]