Сниппеты в emacs

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

Например, в LaTeX это такие конструкции как

\begin{document}
\end{document}

С подобными кусочками кода в emacs тоже не бывает проблем. Однако, что если вам не хочется при создании нового документа заполнять его стандартным содержимым? Не весть как интересно наполнять стартовые файлы LaTeX или HTML, не правда ли?

Для такого случая можно заранее подготовить необходимые файлы-сниппеты, а при создании нового документа просто вставлять их содержимое в буфер текстового редактора. И здесь не обойтись без написания какой-нибудь полезной функции на emacs lisp.

Рассмотрим несколько несложных примеров.

Вставка текста прямо из функции

В случае постоянного использования одного и того же языка программирования заготовочные файлы иметь вовсе не обязательно: можно получить нужную последовательность символов непосредственно из функции.

Для этой нехитрой задачи воспользуемся командой вставки текста insert. В двойных кавычках укажем нужный фрагмент кода. Например:

(defun newpy () ; определить функцию newpy
  "Create new python document" ; комментарий
  (interactive) ; работать интерактивно
  ; вставить строки
  (insert "#!/usr/bin/env python # -*- coding: utf-8 -*-"))

Теперь при нажатии M-x (после рестарта emacs) можно смело вводить имя только что созданной функции и наблюдать, как указанный текст будет вставлен в текущем буфере на той строке, где стоит курсор.

Если читатель относит себя к любителям горячих сочетаний клавиш, он может также определить заветную комбинацию для быстрого вызова функции:

(global-set-key (kbd "C-c s") 'newpy)

Получение текста из файла

Обратимся к иному методу получения данных: вставке из определённого файла.

Создадим функцию newtex, которая будет забирать данные из указанного файла при помощи insert-file-contents. При необходимости строки будут разделены.

(defun newtex()
  "Get data from the file ex.tex"
  (interactive)
    ; вставить данные из файла ex.tex
    (insert-file-contents "~/ex.tex")
    ; разделить строки
    (split-string (buffer-string) "\n" t))

Разделять строки совершенно необязательно: ведь заранее заготовленный сниппет уже приведён к соответствующему виду. Определить комбинацию клавиш можно так же, как это уже было показано ранее.

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

В следующем примере даётся функция snip, которая принимает аргумент ext. Она взаимодействует с пользователем, получает от него имя расширения файла (аргумент) и открывает соответствующий ему файл. Для выбора файла используется конструкция if.

(defun snip (ext) ; ожидает аргумента ext
  "Get data from the file."
  (interactive "sExtension: ") ; приглашение для ввода строки
  (if (equal ext "html") ; проверить на равенство
      (insert-file-contents "~/ex.tex")
  )
  (if (equal ext "py")
      (insert-file-contents "~/ex.py")
  )
  ; если аргумента нет
  (if nil (message "argument is nil")))

Так, в несколько строчек кода вместилась весьма полезная функция, способная сделать работу с emacs ещё чуточку продуктивнее. Можно ли использовать для сегодняшней цели сторонние «фичи» emacs автору неведомо. Но нужны ли они, если и так всё просто?