- PVSM.RU - https://www.pvsm.ru -
По результатам исследованиям работы программистов около 20% времени тратиться на непосредственное написание кода и около 80% времени — на просмотр старого, его анализ. Исходя из данной предпосылки текстовый редактор в первую очередь должен предоставить удобные средства навигации по коду. Большая часть описанных фич как раз имеет дело с навигацией и анализом.
В данной статье я постараюсь продемонстрировать максимум удобных в ежедневном применении возможностей редактора Emacs для языка Python, и более конкретно для редактирования Django проектов.
Как говорится в пословице: «обещанного три года ждут». Хотя три года и не прошло, но уже изрядно много с моей предыдущей статьи «Emacs для начинающих: введение» [1]. Я не буду «растекаться мыслью по древу» а постараюсь максимально кратко показать как работают различные фичи Emacs в применении к Python.
Формат статьи:
Для тех же, кому интересно применить рецепты целиком — мой конфиг доступен (Mercurial) тут [2], а здесь: рецепт по его примененнию [3].
Довольно удобная фича. В любом месте если забылось какие то детали по документации можно вызвать один из вариантов показа документации:
Показываю данные фичи по отдельности так как они независимы друг от друга.
Рецепт включения: по рецепту включения rope отдельныйи разговор и описан в:
После включения rope начинают работать его keybindings и меню:
Пакет ставиться отсюда: https://github.com/tsgates/pylookup [37]. У него две активные составляющие: 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 [38]):
(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)
Устанавливаем 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/
Есть замечательный модуль pdbtrack который «следит» за передвижениями по коду программы во время отладки по клавишам n,s и другим. Да и кстати, умеючи работать с pdb можно достичь большего чем в аналогичных визуальных средствах отладки.
pdbtrack включается автоматически с включением главного режима python-mode.
Для того чтобы он вызвался в emacs, надо поставить строку типа:
import pdb; pdb.set_trace() в Вашем коде. Выполняемая программа должна обязательно выполняться в emacs/shell.
rgrep — быстрый поиск строки по всем файлам с определённым расширением. Тут стоит заметить что начиная с версии emacs 23.x разработчики что то поменяли в интерфейсе вызова и теперь разделить расширения пробелом, как например [*.html *.py] стало невозможно, если не знать конечно обходного пути:
чтобы ввести пробел в rgrep — экранируйте оный клавишей C-q
rgrep удивительно быстро работает, и даже в нашем самом большом проекте с десятками тысяч файлов он находит искомое за доли секунды, что немаловажно для часто выполняемых поисков.
У меня rgrep привязан на клавишу: C-f7
occur показывает вхождение данной строки в текущем файле. Для того, чтобы его было удобно вызывать я сделал макрос, который автоматически выделяет текущее слово и далее вызывает occor по нему. У меня данная функция привязана на клавишу: C-z o
Блоки бывают:
Также блоки можно запоминить в разные регистры, соответственно можно работать с разными блоками одновременно.
Да. Применяется не очень часто, но когда применяется, экономит Вам массу времени, которое было бы потрачено на гуляние вверх-вних по klipper/parcellite или и того хуже (если у вас один буфер обмена).
Клавиши:
Визуальный режим включается кнопкой C-enter. Появляется прямоугольая область в которой можно заполнять текст, удалять,
или копировать весь прямоугольник. В данном режиме работают все станратные кнопки работы с блоком — Alt+Y чтобы запомнить
блок и Ctrl+Y чтобы вставить.
Есть второй вариант квадратных блоков, несколько урезанный, но работающий для терминального режима. Работает так: начитаете
выделять блок как обычно (C-space) но при этом работа с блоком по клавишам:
Некоторой удобной заменой именованного блока является встроенный в emacs аналог klipper, под названиам killring:
(require 'browse-kill-ring)
(global-set-key (kbd "C-c k") 'browse-kill-ring)
Стоит заметить что ситуацию с блокам и привязками клавиш к операциям запутана по нескольким объективным, историческим
причинам:
В результате часто даже такая банальная вещь как копирование блоками становиться сложным для освоения этапом в изучении
emacs.
Подливает воды в огонь также то, что в xorg True way для копирования блоков: Control Insert чтобы скопировать и Shift Insert
чтобы встатить блок. При этом мышь копирует в один буфер обмена а клавиатурные выделения попадают в другой.
Для начинающих я часто советую осваивать сразу «True way» и не пытаться включить так называемый cua-mode, призванный освободить C-c C-v от
стандартный emacs key bindinds, лишая конечного пользвателя массы удобного функционала. Если уж изучать emacs, то выучить
две дополнительные клавиши:
не является супер проблемой. Для тех, для кого является — включайте смело Cua-mode и работайте дальше, но скорее всего Вы всё равно
вернётесь к теме и вернёте стандартные клавиши, когда почувствуете что не хватает удобных клавиатурных комбинаций клавиш.
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"))
Клавиши:
Конфигурация:
(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)
)
)
Клавиши (работает не только в pyhon, а вообще много где):
Определение смотреть тут: idomenu.el [39]
настроено у меня по клавише Scroll_Lock:
(global-set-key [Scroll_Lock] 'speedbar)
Настроено через Rope и bookmark на клавишах:
Недостатком настройки является то, запись истории переходов глобальна и каждый переход оставляет мусор в 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)
(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)
Работает в любом режиме, не относиться напрямую к Python, просто удобная функция. Вызывается по:
(global-set-key [(control shift f)] 'find-name-dired)
Очень удобно, особенно для того чтобы открыть связанный файл, например template файл для view в Django.
(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)
Устанавливается:
(make-face 'mode-line-80col-face)
Начинает работать с момента установки Rope.
<span style="color: #66cc66;">(</span>global-set-key <span style="color: #ff0000;">"M- "</span> 'hippie-expand<span style="color: #66cc66;">)</span>
(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)
Для поддержки интеграции с flymake необходимо будет установить pyflakes, pylint пакеты и настроить их расположение в вашей
копии файла:
pyflymake.py [40]
А также установить вот этот Lisp код:
cfg_flymake.el [41]
К сожалению, даже после массы переработок данное решение не является идеальным. Иногда flymake пишет _flymake файлы не к месту на
сетевых сервисах, иногда просто некорректно отрабатывает. Но по сути в 98% случаев он очень полезен так как позволяет
раньше обнаружить сделанную ошибку.
Модуль устанавливается в систему: pep8.
; pep8
(require 'python-pep8)
(global-set-key (kbd "C-c p 8") 'pep8)
Аналогично. Вначале устанавливаем системный пакет pylint а далее уже:
; pylint
(require 'python-pylint)
(global-set-key (kbd "C-c p l") 'pylint)
1) Запускать проект необходимо из django-shell — чтобы был доступен pdb.
2) Есть несколько разных модулей показа синтаксиса django templates.
Я постарался описать наиболее связанные с редактированием Python файлов фичи. Многие не вошли в этот обзор, хотя относяться напрямую к работе с Python проектом, например такая фича как работа с системой управления версиями — она заслуживает отдельной статьи, что я и собираюсь сделать в [возможно ближайшем] будущем.
Статья не закончена, по мере поступления комментариев я обязательно внесу изменения и дополнения.
В любом месте программу на python, если это отдельно стоящий скрипт можно запустить через клавишу C-c c.
При генерации ошибки в таком случае курсор станет на место ошибки.
Вариант номер два: запускать программу из опции compile. В моём конфиге она настроена как:
(global-set-key [C-f9] 'compile)
В случае использования функции compile можно будет использовать переход по ошибкам по F8/Shift-F8.
В обоих вариантах вызов pdb работать не будет т к программы запускаются без связки с терминалом.
Чего я ожидаю от комментариев читателей:
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
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/14873
Ссылки в тексте:
[1] «Emacs для начинающих: введение»: https://www.pvsm.ru/post/139697/
[2] мой конфиг доступен (Mercurial) тут: http://avk-emacs.hg.public.halogen-dg.com/
[3] рецепт по его примененнию: http://alex.koval.kharkov.ua/blog/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D0%B0-emacs-%D0%BE%D1%82-avk/
[4] 1. Интегрированная документация: #docs
[5] 1.1. Rope pydoc: #rope-showdoc
[6] 1.2. Pylookup — индекс документации по стандартной библиотеке Python: #pylookup
[7] 1.2.1. Для индексации также Django документации: #django-doc
[8] 2. Python дебаггер: pdb: #pdb
[9] 3. Rgrep: #rgrep
[10] 4. Occur: #occur
[11] 5. Блоки в Emacs: #regions
[12] 6. Yasnippet — автоматизация ввода с помошью snippets: #yasnippet
[13] 7. Навигация по коду python: #nav
[14] 7.2. По функциям и классам текущего файла через IM-python: #nav-func-class
[15] 7.3. По функциям и классам текущего файла через Speedbar: #nav-speedbar
[16] 7.4. Переход в место определения переменной[класса, метода]: #code-def
[17] 7.5. Bookmarks: #bookmarks
[18] 7.6. Поиск файла по шаблону имени: #find-name-dired
[19] 7.7. Открыть файл проекта: rope-file-find: #rope-file-find
[20] 8.1. Python Ident влево/вправо: #indent
[21] 8.2. Борьба с пустым текстом: #whitespace
[22] 8.3. Визуализация превышения длинны строки: #longlines
[23] 8.4. Автодополнения: #autocomplete
[24] 8.4.1. Автодополнения Rope: #autocomplete-rope
[25] 8.4.2. Автодополнения hippie-expand: #autocomplete-hippie
[26] 8.5. Комментарии в тексте: #autocomments
[27] 9. Тестирование качества кода: #code-testing
[28] 9.1. интеграция с Flymake: pyflymake: #pyflymake
[29] 9.2. вызов pep8: #pep8
[30] 9.3. вызов pylint: #pylint
[31] 10. Django специфика: #django
[32] 11. Режим компиляции для python и быстрый запуск: #compile
[33] 12. В завершение: #finalization
[34] Enabling Rope in Emacs 24.x: http://alex.koval.kharkov.ua/blog/enabling-rope-in-emacs-24x/
[35] http://habrahabr.ru/post/76370/: https://www.pvsm.ru/post/76370/
[36] Emacs as a Python IDE: http://emacswiki.org/emacs/PythonProgrammingInEmacs#toc2
[37] https://github.com/tsgates/pylookup: https://github.com/tsgates/pylookup
[38] cfg_pylookup.el: http://avk-emacs.hg.public.halogen-dg.com/hgweb.cgi/file/2636c7c71779/configs/cfg_pylookup.el
[39] idomenu.el: http://avk-emacs.hg.public.halogen-dg.com/hgweb.cgi/file/2636c7c71779/idomenu.el
[40] pyflymake.py: http://avk-emacs.hg.public.halogen-dg.com/hgweb.cgi/file/2636c7c71779/pyflymake.py
[41] cfg_flymake.el: http://avk-emacs.hg.public.halogen-dg.com/hgweb.cgi/file/2636c7c71779/configs/cfg_flymake.el
Нажмите здесь для печати.