Як написати плагін до gedit
Директорія
Плагіни до gedit розміщуються в двох місцях:
/usr/lib/gedit-2/plugins/
– для всієї системи~/.gnome2/gedit/plugins/
– для конкретного користувача.
Вибираємо другий варіант. Директорію plugins
в нашому випадку треба створити.
Файл інформації
Тепер в нашій директорії треба створити файл: sample.gedit-plugin
. (sample – назва нашого плагіну). Що плагін буде робити – придумаємо по дорозі. Його вміст:
[Gedit Plugin] Loader=python Module=sample IAge=2 Name=Sample Description=A Python plugin example Authors= Bunyk T.O. <tbunyk@gmail.com> Copyright= Public domain Website=https://bunyk.wordpress.com/
- Два перші рядки кажуть що це пайтонівський плагін до ґедіта.
Module
– файл плагіна (без розширення py). Також можна задати не файл, а каталог, в якому має бути файл__init__.py
IAge
– версія плагіна, і в інструкції писало що має бути завжди 2Name
– ім’я що буде показане в списку плагінівDescription
– аналогічно- Три останні рядки – інформація про автора та плагін.
Файл з кодом
Тепер треба створити файл з кодом плагіна. (sample.py
, як ми вказали в полі Module
). Його вміст:
import gedit class SamplePlugin(gedit.Plugin): def activate(self, window): print "Sample plugin activated" def deactivate(self, window): print "Sample plugin deactivated" def update_ui(self, window): print "Sample plugin updates ui"
Зберігаємо файли, і перезапускаємо gedit. Заходимо в Edit -> Preferences -> Plugins
і шукаємо в списку наш. Ура!
Якщо перезапускати gedit в терміналі, і потім закрити його, то ми побачимо, що він друкує такі повідомлення:
Sample plugin activated Sample plugin updates ui Sample plugin updates ui Sample plugin updates ui Sample plugin deactivated
Клас плагіна наслідується від базового класу gedit.Plugin
, який описує такі методи (які можна перевантажити):
activate(self, gedit.Window)
deactivate(self, gedit.Window)
update_ui(self, gedit.Window)
Gedit – програма що завжди працює в одному екземплярі. При запуску він перевіряє чи не існує вже запущеного екземпляру програми, і якщо так, то передає контроль йому. Тому створюється тільки один екземпляр плагіна (при запуску основної програми). Але плагіни зазвичай відповідають вікнам. Для цього й створені функції activate
та deactivate
, які викликаються відповідно при створенні та знищенні вікна.
Функція update_ui
викликається коли плагіну варто перевірити, чи не пора обновити стан інтерфейсу.
Зазвичай, при створенні вікна, створюють новий екземпляр плагіну, який прив’язують до цього вікна. Так кожне вікно має свій плагін. Але так казали в офіційній документації, а в Расселла Бітті була краща ідея, яку я і використаю.
Пункт в меню
Тепер давайте зробимо пункт в меню, при натискуванні на який, в вікні з’являється традиційний привітальний напис.
Документація трохи недописана, але є класний плагін – python console, в якому можна інтерактивно виконувати команди. Щоб дізнатись які методи має документ, відкриваємо нову вкладку, консоль, і пишемо:
doc=window.get_active_document() doc.set_text("\n".join(dir(doc)))
В вікні редагування з’являється список методів документа. Це звісно не документація, але вже хоч щось… Не розумію, як в такій класній програмі докстрінги можуть бути відсутніми? Може це тому що вона написана на C?
Так я вияснив наприклад, що щоб взяти увесь текст документа треба зробити так:
text = doc.get_text(doc.get_start_iter(),doc.get_end_iter())
Потім можна з цим текстом попрацювати, і повернути назад, функцією doc.set_text()
Інтерфес gedit, як “щирої” гномської програми написаний на gtk. На жаль, gtk, я все ще не знаю, тому просто використаю готовий скрипт Рассела Бітті [4], трохи його підправивши. Хоча, щоб підправити, треба таки розібратись. При активації програма створює таку собі групу дій (ActionGroup
).
Щоб створити групу дій, використовують конструктор
gtk.ActionGroup(name)
де name
– унікальне ім’я групи.
Потім в цю групу додають дії.
actiongroup.add_actions(entries, user_data=None)
Де entries
– це список кортежів такого формату:
- Ім’я дії. Має бути таке саме як значення атрибута
action
в тезіmenuitem
що знаходиться вmenu_str
(перевірено експериментально). - Ідентифікатор дії. Необов’язковий (може мати значення None), якщо задана мітка.
- Мітка дії. Буде відображатись в меню, як назва. Необов’язкова якщо заданий ідентифікатор.
- Акселератор дії, в форматі який розуміє функція
gtk.accelerator_parse()
. Необов’язковий (можна писати None). - Спливаюча підказка дії. Теж необов’язкова.
- Функція яка запускається, при активації дії. Теж може заміщуватись None, хоча тоді не ясно, а нащо взагалі дію?
В user_data
Рассел передавав об’єкт window
, і мені лінь перевіряти, що буде якщо передати туди щось інше.
Далі група дій передається менеджеру інтерфейсу.
manager = window.get_ui_manager() manager.insert_action_group(self._action_group, -1)
Метод insert_action_group()
додає об’єкт класу gtk.ActionGroup
в список груп. Другий параметр означає позицію в яку додають. Якщо вона від’ємна – додають в кінець. Дії груп що ближче до початку списку приховують дії груп що ближче до кінця, якщо в них однакові імена.
Ну, і нарешті сама програма:
#!coding: utf-8 import gedit import gtk menu_str = """ <ui> <menubar name="MenuBar"> <menu name="EditMenu" action="Edit"> <placeholder name="EditOps_3"> <separator name="SampleSep1"/> <menuitem name="Sample" action="Sample"/> </placeholder> </menu> </menubar> </ui> """ class SamplePlugin(gedit.Plugin): def __init__(self): gedit.Plugin.__init__(self) def hello(self, action, window): doc = window.get_active_document() doc.begin_user_action() doc.insert_at_cursor("Привіт, світе!") doc.end_user_action() def activate(self, window): actions = [ ('Sample', None, 'Привітатись', '<Shift><Control>h', "Додати привітання", self.hello) ] self._action_group = gtk.ActionGroup("SampleActions") self._action_group.add_actions(actions, window) manager = window.get_ui_manager() manager.insert_action_group(self._action_group, -1) self._ui_id = manager.add_ui_from_string(menu_str) def deactivate(self, window): manager = window.get_ui_manager() manager.remove_ui(self._ui_id) manager.remove_action_group(self._action_group) self._action_group = None self._ui_id = None
Тепер є пункт в меню Edit -> Привітатись
, який вставляє в документ фразу “Привіт, світе!”, і відповідна комбінація клавіш Ctrl+Shift+H
. Справа зроблена. Залишилось ще трохи порозбиратись з GTK, і вияснити як додати до плагіна діалогове вікно, і розібратись з модулем subprocess
щоб вияснити, як з коду Python взаємодіяти по трубах з всякими grep
, man
, і іншими програмами, що спілкуються текстом.
Посилання
- Офіційна інструкція на gnome.org
- Расселл Бітті, про те, як він написав плагін що вставляє дату.
- Інструкція PyGTK про
ActionGroups
- Скрипт Рассела Бітті
Понравилось, что ты выяснил всякие фишки)
вспомнил вот это: http://kino-matrix.ru/glava%204/index2.htm (там про эксперименты)
jtimv
Листопад 12, 2010 at 21:53
Ну, виясняти – напевне в цьому і полягає наукова робота 🙂 Так і напишу в своїй курсовій “в даній роботі з’ясовано …”
І дякую за посилання. Цікава книжка.
bunyk
Листопад 12, 2010 at 22:11