Date Редакция Категория comp Теги Cpp / emacs

GNU Emacs – программа, чьи многофункциональность и возможности настройки давно стали легендарными. Действительно, в каком ещё текстовом редакторе помимо его традиционных функций можно: читать электронную почту, играть в игры, прослушивать и создавать (!) музыку. Расширяемость Emacs, в частности, позволяет превратить его в полноценную среду разработки программ.

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

Идеальный пользователь Emacs.

Цель данного текста: помочь разобраться, как в Emacs набирать программный код, компилировать его, запускать программу и использовать отладчик.

Заметим, что Emacs, по преимуществу, клавиатурный редактор. Конечно, в нём есть меню и панель инструментов, но зачастую удобнее и быстрее обходится без них. Не потому, что меню неудобные и не потому что "так поступают настоящие программисты", а потому что – действительно удобнее. К удобству мы и будем стремиться.

Так выглядит Emacs сразу после открытия.

Обозначения клавиш

В документации по Emacs клавиша 'Ctrl' обозначается как 'C'. Например, вместо 'Ctrl-a' пишут 'C-a'. Обозначение 'M' ("мета") соответствует клавише 'Alt' или 'Esc'. То есть команда 'M-x' может быть выполнена как 'Alt-x' или как 'Esс, x'. Последняя запись означает, что 'Esc' не нужно удерживать в момент нажатия 'x'.

Emacs Остальные
C-клавиша = Ctrl-клавиша
M-клавиша = Alt-клавиша или Esc-клавиша

Создание, открытие и сохранение файлов

Файл создаётся/открывается комбинацией команд C-x C-f, после чего в минибуфере вводится имя нового файла. Минибуфер – самое нижнее из окон Emacs – маленькое окно, расположенное непосредственно над статусной строкой (на рисунке выше в минибуфере написано: "For information about GNU Emacs...").

Другой способ открыть файл: C-x D. В результате мы попадаём в каталог пользователя. Далее нужный каталог и файл можно выбрать с помощью мыши.

Сочетание клавиш Действие
C-x C-f Открыть файл или создать его, если файл с введенным именем отсутствует.
C-x D Выбрать каталог
C-x C-s Сохранить файл
C-x C-w имя_файла Сохранить как... Сохранить данный буфер в файле имя_файла

Важно!

Отменить команду Emacs можно комбинацией C-g. Если Emacs не реагирует на ваши команды, то вернуть его в рабочее состояние можно также с помощью C-g.

Выход из Emacs: C-x C-с

Перемещение по тексту

Работают привычные команды и "стрелочки". Кроме того:

Сочетание клавиш Команда Действие
C-p previous-line Вверх на одну строку
C-n next-line Вниз на строку
C-f forward-char Вперёд на один символ
C-b backward-char Назад на один символ
C-a begining-of-line Начало строки
C-e end-of-line Конец строки
C-v scroll-up Вниз на одну страницу
M-v previous-page Вверх на одну страницу
M-f next-word Вперёд на одно слово
M-b previous-word Назад на одно слово
M-< beginning-of-buffer В начало буфера
M-> end-of-buffer В конец буфера
M-g g номер_строки goto-line Перейти к строке номер_строки

Полная форма команды (столбец "Команда") используется для запуска с помощью префиксного сочетания M-x, например M-x save-buffer (нажимаем M-x, после чего набираем в минибуфере: save-buffer).

Буферы, о которых упоминается в таблице воспринимайте как обычные окна. Подробнее о буферах мы поговорим немного позже.

В Emacs существует очень много команд, которые могут занять все возможные C- и M- комбинации. Для решения этой проблемы используется команда X (eXtend - расширять). Она существует в двух видах:

Сочетание клавиш Действие
C-x Символьное расширение. Далее следует один или несколько символов, например следующая команда
M-x Вызов команды по названию. После нажатия M-x нужно ввести название команды

Выделение текста

Клавиатурой: отметим начало фрагмента C-SPC или C-@, выделим текст курсором, и поставим следующую метку. Но, на мой взгляд, проще выделять фрагмент с помощью мыши.

Копирование, удаление и вставка

Как только фрагмент выделен, его можно копировать, вырезать и вставлять в нужное место документа

Сочетание клавиш Действие
C-w Вырезать фрагмент
M-w или C-Ins Скопировать фрагмент
C-y или S-Ins Вставить фрагмент

S-Ins – это привычный Shift-Ins. Как видно, наряду с emacs'овскими работают и традиционные комбинации копирования и вставки.

Команда C-k удаляет символы от текущего символа до конца строки. Чтобы вернуть удаленный текст и поместить его туда, где стоит курсор, нажмите C-y. Буквы в командах обусловлены названием соответствующих операций в Emacs: вместо копирования (cut) и вставки (paste) они называются "удаление" (killing) и "возврат" (yanking).

C-y вернет только самое последние удаление. Но и предыдущий текст не потерян. Вы можете вернуть его с помощью команды M-y. После того как вы нажали C-y и вернули текст, удаленный в последнюю очередь, M-y будет заменять только что возвращенный кусок текста на более ранние "удаления".

Отменить изменения в тексте можно командой C-x u. Если вы повторяете её несколько раз, то каждое повторение отменяет ещё одну команду.

Сочетание клавиш Действие
C-k Удалить от текущего символа до конца строки
M-k Удалить от текущего символа до конца предложения
C-y Вернуть удалённый текст, начиная с позиции курсора
C-x u Отмена изменений в тексте

Поиск и замена

Сочетание клавиш Действие
C-s Поиск "вперед" (search)
C-r Поиск "назад" (reverse)
M-x строка_замена Замена найденной поиском строки на строка_замена
M-% Поиск и замены

Компиляция кода

Перейдём собственно к С++. Создадим файл source.cpp и наберём в нём следующий код

#include <iostream>

using namespace std;

int main()
{
  cout << "Hello, world!" << endl
}

Сохраним файл (C-x C-s) и скомпилируем его (M-x compile, затем наберём в минибуфере: g++ source.cpp -o source -g -Wall).

Сообщение компилятора откроется в новом окне. Если компилятор обнаружил синтаксические ошибки (посмотрите на код внимательнее!), то перемещаться по ним можно с помощью команды "C-x `". Чтобы переместиться в место кода, вызвавшее ошибку, достаточно кликнуть на сообщение об ошибке.

Вверху окно с кодом, внизу – результаты компиляции. В минибуфере записано: Compilation finished.

Комбинация C-l устанавливает текущую строку в центр видимого окна

Окна, буферы и файлы

"Окна" (windows) в Emacs'е означают не отдельные перекрывающиеся окна в оконной системе, а разделенные участки внутри одного окна (или "фрейма").

Сочетание клавиш Действие
C-x 1 Переключиться в режим одного окна (того, в котором находится курсор)
C-x 2 Переключиться в режим двух окон
C-x o Переключение между окнами (other - другой)

С помощью команды C-M-v можно листать текст во втором окне не выходя из первого.

Emacs хранит содержимое каждого открытого файла в структуре под названием "буфер" (buffer). Открытие файла создает новый буфер в Emacs'е. При открытии нового файла старый не закрывается. Переключиться в него можно с помощью списка буферов.

Сочетание клавиш Действие
C-x C-b Список буферов (можно переключаться между буферами)
C-x C- Следующий буфер
C-x C- Предыдущий буфер

Если вы внесли изменения в один файл, а потом открыли другой, то это не приведет к записи первого файла. Все изменения остаются внутри Emacs'а, в буфере, связанном с этим файлом. Значит нужен простой способ сохранить буфер первого файла. Команда C-x s позволяет сохранить измененные буферы.

Если вы уже закончили работу с файлом и хотите избавиться от связанного буфера, наберите C-x k (снова killing!).

Сочетание клавиш Действие
C-x s Сохранить изменённые буферы
C-x k Закрыть буфер

Запуск и отладка

Emacs предоставляет фронтенд для отладчика gdb. Естественно, для этого gdb должен быть установлен на вашей машине. Кроме того, желательно при компиляции указывать ключ -g для добавления в исполняемый файл отладочной информации.

Итак, чтобы войти в режим отладки, введите M-x gdb. Emacs достаточно разумен, чтобы отреагировать на это (в минибуфере)

gdb --annotate=3 source

Подтвердим эту команду Enter'ом. В результате, в новом окне запустится gdb.

Запущен gdb.

Ключ annotate управляет уровнем подробности пояснений, которые даёт gdb (annotate=3 – максимальная подробность).

Краткая сводка команд gdb:

команда описание
run [<параметры>] запуск программы на выполнение. Могут указываться необязательные параметры командной строки и операции перенаправления ввода-вывода
help [<раздел>] вызов раздела справки отладчика. help без параметров выводит список разделов
list [<имя функции/процедуры/файла>:] [номер строки] вывод исходного кода функции/процедуры/файла или всей программы, начиная с указанной строки. По умолчанию распечатываются следующие 10 строк программы. Распечатываемый файл становится текущим файлом исходного текста отлаживаемой программы
break <номер строки/имя функции> установка точки останова на указанной строке текущего исходного файла программы
clear <номер строки/имя функции> снятие точки останова с указанной строки текущего исходного файла программы
set args [<параметры>] предварительная установка параметров командной строки
print <выражение> вывод значения выражения, которое может включать и переменные и вызовы функций программы
next [] выполнение очередной строки программы без захода в функцию (step over). Необязательный параметр n указывает число строк программы для выполнения (по умолчанию — 1). Перед выполнением next/step программа должна быть запущена командой run
step [] выполнение очередной строки программы с заходом в функцию (step into).
set var <имя>=<выражение> присваивание значения переменной
ptype <имя-переменной> вывод типа переменной (на языке программирования)
bactrace или bt вывод содержимого стека вызовов
continue продолжение выполнения программы после остановки
quit выход из отладчика

Подавляющее большинство команд сокращается до одной буквы: run – r, step – s и т. п.

Полезные мелочи

Отступы

Emacs позволяет автоматически расставить отступы в уже готовой программе. Для этого выделите весь текст в текущем буфере (C-x H) и нажмите M-x indent-region.

Комментарии

Закомментировать несколько строк одновременно можно командой (M-x comment-region или C-c C-c). Комментировать/Раскомментировать строки, в зависимости от их текущего состояния, можно командой . О том, как привязать команду к определенной комбинации клавиш мы поговорим позднее.

Дополнение по Tab

Также как и многие популярные оболочки Linux (bash, csh, tcsh, ...) Emacs предлагает дополнение команд по клавише Tab.

Чтение руководства

Вы можете читать страницы man'a прямо в Emacs с помощью команды M-x man.

Работа в командной строке

... не выходя из Emacs: M-x shell

Простейшая настройка

Режимы работы

Существуют различные режимы работы Emacs, Например, режим для редактирования исходного кода на C++ – C++ mode, режим работы с текстовыми документами – Text mode и т. п. (mode - англ.: режим).

Режимы работы делятся на основные и вспомогательные. В каждый момент времени активен только один основной режим, и его название всегда написано в строке состояния.

Каждый основной режим заставляет некоторые команды работать по-разному. Например, так как в разных языках программирования комментарии ставятся по-разному, то и команда комментирования участка кода в разных режимах работает по-своему. Каждому основному режиму соответствует образованная от его названия расширенная команда, переключающая Emacs в этот режим, например,

Сочетание клавиш Режимы
M-x c++-mode Режим правки кода C++
M-x text-mode Текстовый режим

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

Для нас сейчас важно то, что существуют глобальные настройки Emacs и настройки для отдельных режимов работы.

Файл .emacs

Файл .emacs используется для хранения основных настроек Emacs. Это текстовый файл, в котором располагаются команды на языке Emacs Lisp, запускаемые при каждом старте редактора.

В рамках этой статьи мы не будем разбираться с Lisp'ом (да и не сможем этого сделать), а ограничимся списком "рецептов" для решения часто встречающихся задач. Приведенные фрагменты кода нужно вставить в текстовый файл ~/.emacs, который, возможно, придётся создать.

Настройка клавиш

Сопоставим команде compile клавишу F9, а команде запуска отладчика (gdb) – F5:

 (global-set-key [(f9)] 'compile)
 (global-set-key [(f5)] 'gdb)

Каталог для поиска исходников

По умолчанию, команда C-x C-f (find-file) предлагает начать поиск файлов из каталога пользователя ~/. Но мои исходники хранятся в каталоге ~/work и удобнее было бы начинать поиск именно с него. Устанавливаем:

 (setq command-line-default-directory "~/work")

Шаблон исходника

Если надоело писать каждый раз #include ..., создайте файл с шаблоном cpp-кода, а в .emacs включите

 (add-hook 'find-file-hooks 'cpp-load-template)
 (defun cpp-load-template ()
   (interactive)
   (when (and 
         (string-match ".cpp$" (buffer-file-name))
         (eq 1 (point-max)))
     (insert-file "~/.emacs.d/template.cpp")))

Вместо .cpp пишем нужное расширение, а шаблон кода находится в файле template.cpp. Файл шаблона можно хранить где угодно, но каталог ~/.emacs.d/ - стандартное место для хранения пользовательских файлов, относящихся к Emacs.

Шаблон фрагмента кода

Отдельные фрагменты кода (например, заголовки циклов) можно также превратить в шаблоны и вставлять нажатием одной кнопки. Для этого устанавливается YASnippet – система управления шаблонами Emacs. Шаблоны YASnippet поддерживают C, C++, C#, Perl, Python, Ruby, SQL, LaTeX, HTML, CSS и мн. др.

Шаблон команды компилирования

Если программа проста и составлять для неё makefile нет смысла, а набирать g++ ... при каждом запуске Emacs надоело, вставим в .emacs следующий код

 (add-hook 'c++-mode-hook
  (lambda ()
    (unless (file-exists-p "Makefile")
      (set (make-local-variable 'compile-command)
       (let ((file (file-name-nondirectory buffer-file-name)))
         (concat "g++ -g -O2 -Wall -o " 
             (file-name-sans-extension file)
             " " file))))))

Ввод команд без переключения раскладки

По умолчанию, находясь в русской раскладке невозможно ввести команды Emacs. Ниже приведен код, решающий эту проблему (источник){rel="nofollow"}.

 ; Map Modifier-CyrillicLetter to the underlying Modifier-LatinLetter, so that
 ; control sequences can be used when keyboard mapping is changed outside of
 ; Emacs.
 ;
 ; For this to work correctly, .emacs must be encoded in the default coding
 ; system.
 ;
 (mapcar*
  (lambda (r e) ; R and E are matching Russian and English keysyms
    ; iterate over modifiers
    (mapc (lambda (mod)
     (define-key input-decode-map
       (vector (list mod r)) (vector (list mod e))))
   '(control meta super hyper))
    ; finally, if Russian key maps nowhere, remap it to the English key without
    ; any modifiers
    (define-key local-function-key-map (vector r) (vector e)))
    "йцукенгшщзхъфывапролджэячсмитьбю"
    "qwertyuiop[]asdfghjkl;'zxcvbnm,.")

Теперь русские буквы автоматически транслируются в соответствующие английские. Например, последовательность C-ч и' переводится вC-x b' и запускает команду 'switch-to-buffer'.

Для Emacs > 24.1 есть другое решение.

Стиль отступов в коде

По умолчанию используется стиль "gnu", распространенный в GNU-проектах. Подробнее о стилях отступов см. на emacswiki.org и в Википедии.

Настроим стиль отступов из книги Страуструпа "The C++ Programming Language":

(setq c-default-style "stroustrup")

Пробелы вместо табуляций

(setq-default indent-tabs-mode nil)

Теперь, даже нажимая TAB, в исходный файл будет добавляться не символ табуляции, а соответствующее ему число пробелов.

И, наконец...

Вы попробовали всё это, но так и не привыкли к особенностям Emacs? Тогда попробуйте ErgoEmacs. Это всё тот же Emacs, но меню, комбинации клавиш и терминология приведены в соответствии с современными.



Комментарии

comments powered by Disqus