По результатам исследованиям работы программистов около 20% времени тратиться на непосредственное написание кода и около 80% времени — на просмотр старого, его анализ. Исходя из данной предпосылки текстовый редактор в первую очередь должен предоставить удобные средства навигации по коду. Большая часть описанных фич как раз имеет дело с навигацией и анализом.
В данной статье я постараюсь продемонстрировать максимум удобных в ежедневном применении возможностей редактора Emacs для языка Python, и более конкретно для редактирования Django проектов.
Как говорится в пословице: «обещанного три года ждут». Хотя три года и не прошло, но уже изрядно много с моей предыдущей статьи «Emacs для начинающих: введение». Я не буду «растекаться мыслью по древу» а постараюсь максимально кратко показать как работают различные фичи Emacs в применении к Python.
Формат статьи:
- описание фичи
- пример как её включить в Вашем конфиге
- и сопутствующая видео демонстрация работы. Warning: качество звука на всех видео так себе. Исправлю, но позже...
Для тех же, кому интересно применить рецепты целиком — мой конфиг доступен (Mercurial) тут, а здесь: рецепт по его примененнию.
Содержание
- 1. Интегрированная документация
- 1.1. Rope pydoc
- 1.2. Pylookup — индекс документации по стандартной библиотеке Python
- 1.2.1. Для индексации также Django документации
- 2. Python дебаггер: pdb
- 3. Rgrep
- 4. Occur
- 5. Блоки в Emacs
- 6. Yasnippet — автоматизация ввода с помошью snippets
- 7. Навигация по коду python
- 7.2. По функциям и классам текущего файла через IM-python
- 7.3. По функциям и классам текущего файла через Speedbar
- 7.4. Переход в место определения переменной[класса, метода]
- 7.5. Bookmarks
- 7.6. Поиск файла по шаблону имени
- 7.7. Открыть файл проекта: rope-file-find
- 8.1. Python Ident влево/вправо
- 8.2. Борьба с пустым текстом
- 8.3. Визуализация превышения длинны строки
- 8.4. Автодополнения
- 8.4.1. Автодополнения Rope
- 8.4.2. Автодополнения hippie-expand
- 8.5. Комментарии в тексте
- 9. Тестирование качества кода
- 9.1. интеграция с Flymake: pyflymake
- 9.2. вызов pep8
- 9.3. вызов pylint
- 10. Django специфика
- 11. Режим компиляции для python и быстрый запуск
- 12. В завершение
1. Интегрированная документация
Довольно удобная фича. В любом месте если забылось какие то детали по документации можно вызвать один из вариантов показа документации:
- pylookup — индексированный Sphinx вариант для стандартной библиотеки Python
- pydoc — встроенная документация из объекта (посредством ropemacs)
Показываю данные фичи по отдельности так как они независимы друг от друга.
1.1. Rope pydoc
Рецепт включения: по рецепту включения rope отдельныйи разговор и описан в:
После включения rope начинают работать его keybindings и меню:
- В меню данная функция доступна через: [Rope]->[Shown documentation]
- Keybinding: C-c d
1.2. Pylookup — индекс документации по стандартной библиотеке Python
Пакет ставиться отсюда: https://github.com/tsgates/pylookup. У него две активные составляющие: pylookup.el размещаем в директорую, читаемую emacs для загрузки Lisp, а pylookup.py — куда нибудь, где она будет доступна по пути для пользователя.
Индексируется так:
./pylookup.py -d /var/db/pylookup/pylookup.db -u /usr/share/doc/python-docs-2.*/html
В emacs настраиваем загрузку модуля и удобную клавишу для вызова. У меня настроено
по клавишам Control+Shift+Menu.
Включается так (см также: cfg_pylookup.el):
(eval-when-compile (require 'pylookup))
(setq pylookup-program "/usr/local/bin/pylookup.py")
(setq pylookup-db-file "/var/db/pylookup/pylookup.db")
(global-set-key [(control shift menu)] 'pylookup-lookup)
1.2.1. Для индексации также Django документации:
Устанавливаем django-docs:
cd ~/
svn co http://code.djangoproject.com/svn/django/trunk/docs/ django-docs
cd django-docs
make html
cd _build/html
ln -s genindex.html genindex-all.html
А команду сверху дополняем:
./pylookup.py -d /var/db/pylookup/pylookup.db -u /usr/share/doc/python-docs-2.*/html -u ~/django-docs/_build/html/
2. Python дебаггер: pdb
Есть замечательный модуль pdbtrack который «следит» за передвижениями по коду программы во время отладки по клавишам n,s и другим. Да и кстати, умеючи работать с pdb можно достичь большего чем в аналогичных визуальных средствах отладки.
pdbtrack включается автоматически с включением главного режима python-mode.
Для того чтобы он вызвался в emacs, надо поставить строку типа:
import pdb; pdb.set_trace() в Вашем коде. Выполняемая программа должна обязательно выполняться в emacs/shell.
3. Rgrep
rgrep — быстрый поиск строки по всем файлам с определённым расширением. Тут стоит заметить что начиная с версии emacs 23.x разработчики что то поменяли в интерфейсе вызова и теперь разделить расширения пробелом, как например [*.html *.py] стало невозможно, если не знать конечно обходного пути:
чтобы ввести пробел в rgrep — экранируйте оный клавишей C-q
rgrep удивительно быстро работает, и даже в нашем самом большом проекте с десятками тысяч файлов он находит искомое за доли секунды, что немаловажно для часто выполняемых поисков.
У меня rgrep привязан на клавишу: C-f7
4. Occur
occur показывает вхождение данной строки в текущем файле. Для того, чтобы его было удобно вызывать я сделал макрос, который автоматически выделяет текущее слово и далее вызывает occor по нему. У меня данная функция привязана на клавишу: C-z o
5. Блоки в Emacs
Блоки бывают:
- обычные
- квадратные
Также блоки можно запоминить в разные регистры, соответственно можно работать с разными блоками одновременно.
5.1. Множественные блоки
Да. Применяется не очень часто, но когда применяется, экономит Вам массу времени, которое было бы потрачено на гуляние вверх-вних по klipper/parcellite или и того хуже (если у вас один буфер обмена).
Клавиши:
- C-x r s char — запомнить блок в именованный буфер symbol, например C-x rs1 — запомнить в блок по имени 1.
- C-x r i char — вставить из именованного блока
5.1. Квадратные блоки
5.1.1. Визуальные квадратные блоки
Визуальный режим включается кнопкой C-enter. Появляется прямоугольая область в которой можно заполнять текст, удалять,
или копировать весь прямоугольник. В данном режиме работают все станратные кнопки работы с блоком — Alt+Y чтобы запомнить
блок и Ctrl+Y чтобы вставить.
5.1.2. Невизуальные квадратные блоки
Есть второй вариант квадратных блоков, несколько урезанный, но работающий для терминального режима. Работает так: начитаете
выделять блок как обычно (C-space) но при этом работа с блоком по клавишам:
- C-x r r char — запомнить прямоугольный блок в именованный регистр
- C-x r i char — вставить из регистра
5.2. Просмотр kill ring
Некоторой удобной заменой именованного блока является встроенный в emacs аналог klipper, под названиам killring:
(require 'browse-kill-ring)
(global-set-key (kbd "C-c k") 'browse-kill-ring)
5.3. Запутанная ситуация с блоками и клавишами копирования
Стоит заметить что ситуацию с блокам и привязками клавиш к операциям запутана по нескольким объективным, историческим
причинам:
- Знакомые всем Windows кнопки для работы с блоками C-c C-v не работают по умолчанию
- В xorg существует два буфера обмена: главный(primary) и второстепенный(secondary)
- Klipper, Parcellite также занимаясь управлением выделениями часто меняют последовательность, добавляя бардака ко всему
- Emacs поменял процедуры работы с xorg primary/secondary selection в своей текущей версии 0.24
В результате часто даже такая банальная вещь как копирование блоками становиться сложным для освоения этапом в изучении
emacs.
Подливает воды в огонь также то, что в xorg True way для копирования блоков: Control Insert чтобы скопировать и Shift Insert
чтобы встатить блок. При этом мышь копирует в один буфер обмена а клавиатурные выделения попадают в другой.
Для начинающих я часто советую осваивать сразу «True way» и не пытаться включить так называемый cua-mode, призванный освободить C-c C-v от
стандартный emacs key bindinds, лишая конечного пользвателя массы удобного функционала. Если уж изучать emacs, то выучить
две дополнительные клавиши:
- Alt-w чтобы запомнить блок
- C-w чтобы его вставить
не является супер проблемой. Для тех, для кого является — включайте смело Cua-mode и работайте дальше, но скорее всего Вы всё равно
вернётесь к теме и вернёте стандартные клавиши, когда почувствуете что не хватает удобных клавиатурных комбинаций клавиш.
6. Yasnippet — автоматизация ввода с помошью snippets
Yasnippet — это удобный способ автоматизировать ввод частых, но сложных для запоминания блоков текста.
Ставиться как независимый emacs пакет, обычно доступен в репозитории вашей системы.
Конфигурируется как:
(add-to-list 'load-path "/usr/share/emacs/site-lisp/yasnippet")
(autoload 'yas/initialize "yasnippet" "Do necessary initialization.")
(autoload 'yas/load-directory "yasnippet"
"Load snippet definition from a directory hierarchy." t)
(require 'yasnippet) ;; not yasnippet-bundle
(yas/initialize)
(yas/load-directory "/usr/share/emacs/etc/yasnippet/snippets")
(yas/load-directory "~/.emacs.d/yasnippets/")
(setq hippie-expand-try-functions-list
(cons 'yas/hippie-try-expand hippie-expand-try-functions-list))
(global-set-key [(t)] 'indent-for-tab-command)
(setq yas/trigger-key (kbd "M-n"))
7. Навигация по коду python
7.1. Вверх-вниз по функциям
Клавиши:
- Alt+Down — на функцию(класс) вниз
- Alt+Up — на функцию(класс) вверх
- C-c a — в начало класса
- C-c e — в конец класса
Конфигурация:
(defun py-to-start-of-class()
(interactive)
(py-beginning-of-def-or-class 'class)
)
(defun py-to-end-of-class()
(interactive)
(py-end-of-def-or-class 'class)
)
(add-hook 'python-mode-hook
'(lambda ()
(local-set-key [(s menu)] 'rope-code-assist)
(local-set-key [(s up)] 'python-move-to-start-of-class)
(local-set-key [(s down)] 'python-move-to-end-of-class)
(local-set-key [(meta down)] 'py-end-of-def-or-class)
(local-set-key [(meta up)] 'py-beginning-of-def-or-class)
(local-set-key (kbd "C-c C-a") 'py-to-start-of-class)
(local-set-key (kbd "C-c C-e") 'py-to-end-of-class)
(local-set-key (kbd "s-q") 'py-shift-region-left)
(local-set-key (kbd "s-w") 'py-shift-region-right)
)
)
7.2. По функциям и классам текущего файла через IM-python
Клавиши (работает не только в pyhon, а вообще много где):
- C-c v — показать список определений в текущем файле
Определение смотреть тут: idomenu.el
7.3. По функциям и классам текущего файла через Speedbar
настроено у меня по клавише Scroll_Lock:
(global-set-key [Scroll_Lock] 'speedbar)
7.4. Переход в место определения переменной[класса, метода]
Настроено через Rope и bookmark на клавишах:
- Alt+Enter — ерейти в место определения
- Alt+Shift+Enter — ернуться назад
Недостатком настройки является то, запись истории переходов глобальна и каждый переход оставляет мусор в bookmarks,
надо будет переписать этот момент на Lisp с массивом. Но пока работает и так.
(defun rope-goto-definition-save-place ()
""" save current place as 'save-place' bookmark and rope-goto-definition """
(interactive)
(bookmark-set "save-place" 1)
(rope-goto-definition)
)
(defun rope-return ()
""" save current place as 'save-place' bookmark and rope-goto-definition """
(interactive)
(bookmark-jump "save-place")
)
(global-set-key [(M return)] 'rope-goto-definition-save-place)
(global-set-key [(M shift return)] 'rope-return)
7.5. Bookmarks
- C-z b — поставить ссылку
- C-z Up — перейти на ссылку выше (в текущем файле)
- C-z Down — перейти на ссылку ниже (в текущем файле)
- C-z space — перейти на глобальный список ссылок
(require 'bm)
(global-set-key (kbd "C-z b") 'bm-toggle)
(global-set-key (kbd "C-z <up>") 'bm-previous)
(global-set-key (kbd "C-z C-p") 'bm-previous)
;(global-set-key [(control shift down)] 'bm-next)
;(global-set-key [(control shift n)] 'bm-next)
(global-set-key (kbd "C-z <down>") 'bm-next)
(global-set-key (kbd "C-z C-n") 'bm-next)
(global-set-key (kbd "C-z <SPC>") 'bm-show-all)
7.6. Поиск файла по шаблону имени
Работает в любом режиме, не относиться напрямую к Python, просто удобная функция. Вызывается по:
- C-S-f — поиск файла по имени
(global-set-key [(control shift f)] 'find-name-dired)
7.7. Открыть файл проекта: rope-file-find
Очень удобно, особенно для того чтобы открыть связанный файл, например template файл для view в Django.
- C-x p f — ope-find-file — найти файл посредством пакета Rope
8. Работа с текстом python
8.1. Python Ident влево/вправо
- s-q, C-c <, C-c C-l — двинуть блок влево
- s-w, C-c >, C-c C-r — двинуть блок вправо
8.2. Борьба с пустым текстом
- C-z w d — брать пустой текст
(define-key global-map "C-zws" 'show-trailing-whitespace)
(define-key global-map "C-zwh" 'hide-trailing-whitespace)
(define-key global-map "C-zwd" 'delete-trailing-whitespace)
8.3. Визуализация превышения длинны строки
Устанавливается:
(make-face 'mode-line-80col-face)
8.4. Автодополнения
8.4.1. Автодополнения Rope
Начинает работать с момента установки Rope.
8.4.2. Автодополнения hippie-expand
<span style="color: #66cc66;">(</span>global-set-key <span style="color: #ff0000;">"M- "</span> 'hippie-expand<span style="color: #66cc66;">)</span>
8.5. Комментарии в тексте
- C-S-z, C-# — омментировать или раскомментировать выделенный блок кода
(global-set-key [(control #)] 'comment-or-uncomment-region)
(global-set-key [(control shift z)] 'comment-or-uncomment-region)
; hippie expand
(global-set-key "M- " 'hippie-expand)
9. Тестирование качества кода
9.1. интеграция с Flymake: pyflymake
Для поддержки интеграции с flymake необходимо будет установить pyflakes, pylint пакеты и настроить их расположение в вашей
копии файла:
pyflymake.py
А также установить вот этот Lisp код:
cfg_flymake.el
К сожалению, даже после массы переработок данное решение не является идеальным. Иногда flymake пишет _flymake файлы не к месту на
сетевых сервисах, иногда просто некорректно отрабатывает. Но по сути в 98% случаев он очень полезен так как позволяет
раньше обнаружить сделанную ошибку.
9.2. вызов pep8
Модуль устанавливается в систему: pep8.
; pep8
(require 'python-pep8)
(global-set-key (kbd "C-c p 8") 'pep8)
9.3. вызов pylint
Аналогично. Вначале устанавливаем системный пакет pylint а далее уже:
; pylint
(require 'python-pylint)
(global-set-key (kbd "C-c p l") 'pylint)
10. Django специфика
1) Запускать проект необходимо из django-shell — чтобы был доступен pdb.
2) Есть несколько разных модулей показа синтаксиса django templates.
11. Что не вошло в эту статью
Я постарался описать наиболее связанные с редактированием Python файлов фичи. Многие не вошли в этот обзор, хотя относяться напрямую к работе с Python проектом, например такая фича как работа с системой управления версиями — она заслуживает отдельной статьи, что я и собираюсь сделать в [возможно ближайшем] будущем.
Статья не закончена, по мере поступления комментариев я обязательно внесу изменения и дополнения.
11. Режим компиляции для python и быстрый запуск
В любом месте программу на python, если это отдельно стоящий скрипт можно запустить через клавишу C-c c.
При генерации ошибки в таком случае курсор станет на место ошибки.
Вариант номер два: запускать программу из опции compile. В моём конфиге она настроена как:
(global-set-key [C-f9] 'compile)
В случае использования функции compile можно будет использовать переход по ошибкам по F8/Shift-F8.
В обоих вариантах вызов pdb работать не будет т к программы запускаются без связки с терминалом.
12. В завершение
Чего я ожидаю от комментариев читателей:
- Укажите мне что я забыл (или не знал), я добавлю.
- Кто не ленивый сделать подобный обзор по vim, Sublime, и тп? В первую очередь интересуют фичи, описанные тут, и те [полезные] фичи, которые отсутствуют в Emacs но присутствуют где то ещё.
P.S. Качество звука подкачало, писал с помощью ffmpeg -vf crop=970:505:7:15 -f alsa -i hw:0 -f x11grab -r 25 -s 1680x1050 -i :0.0 -s 1280x720 -vcodec libx264 -vpre lossless_ultrafast filename.avi и
на микрофон на ноуте. Во первых громко слышны нажатия клавиш, во вторых звук тихий и иногда слышны посторонние шумы. Увы… Возможно я пересниму видео, использовав
гарнитуру, но пока что есть — то есть. Лучше так чем вообще без них, правда?
Автор: avkoval