категории | RSS

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

Итак, начнем.
|
---- Предварительные..., гм, приготовления
|

1.) Для написания любого плагина Вам понадобится в первую очередь иметь перед глазами и под рукой исходный код редактора в удобном для чтения и копирования виде.
Я использую для этого отличный текстовый редактор Dedit Юрия Бакунина aka jbak.
Почему я не использую для этого сам Kaapython, спросят зловредные злопыхатели?
По кочану и по кочерыжке.
На данный момент главный скрипт -- kaapython.py -- имеет размер около 140 кб.
Экземпляры appuifw.Text не могут вместить столько текста!
Извините, это был вопль души.
Разбить kaapython.py на несколько связанных модулей? Вариант, но и тут подводных камней хватает, поверьте мне на слово. Или можете не верить, но тогда... просто сделайте это сами и подарите мне результат ваших бескорыстных трудов.

2.) Теперь небольшая справка.
Каждый плагин по сути это подпакет (я буду так называть пакет, вложенный в другой, "родительский", пакет) в пакете "plugins", размещенном в папке программы.
При старте редактора, упрощено говоря, происходит импорт всех этих подпакетов, то есть (для тех, кто не в курсе, как работает импорт модулей) файлов __init__.py, размещенных в папках подпакетов.
|
---- И, начали! Документация
|

Напишем, вернее создадим, простой плагин "Hello, World!".
Как и полагается плагину с таким названием, он будет делать ровно ничего.
Сначала создадим в папке plugins папку hello_world.
Добавим к нашему плагину документацию (да, именно так, солидно и серьезно): для этого храброго дела создадим подпапку help для встроенной в Kaapython утилиты для просмотра документации.
В этой папке должны быть размещены текстовые файлы с именами English, Russian, Deutsch etc.
Таким образом, в них размещается справочная информация по плагину и, в зависимости от установленного в редакторе языка, откроется соответствующий файл помощи.
Как вы понимаете, если у вас нет олбанской локализации для всего редактора, то нет смысла и для плагина создавать файл помощи "Olbanian".
Я рекомендую создавать файл English. Английский язык используется в редакторе дефолтно. И справочную информацию рекомендую предоставлять на английском.
Но в данном случае мы создадим файл Russian.
Пропишем в хелпе назначение плагина, способ использования и наш копирайт smile -- стандартная сборная солянка:
|
Простой плагин для вывода информационного сообщения с текстом "Hello, World!". Чтобы использовать плагин, назначьте функцию "Hello, World!" на какой-либо шорткат, используя диалог Установок.

Copyright (c) 2010, %username%
Distributed under the new BSD license.
|
---- Продолжаем. Локализация
|
Теперь добавим локализацию для нашего плагина, то бишь русификатор в моем конкретном случае.
Создаем подпапку lang в папке hello_world (директория нашего плагина, если вы помните), в ней файл Russian.
В нём будет одна пара ключ-значение:
'Hello, World!': 'Привет, Мир!'.decode('utf-8')
Как уже неоднократно говорилось, в зависимости от текущего языка редактора (English по умолчанию) будут использоваться соответствующие строки.
|
---- Ага! Объявляем манифест.
|
Далее заполняем манифест.
Что прописывается в манифесте?:
Kaapython-Version-Max: 1.0.0
Version: 1.00.0
Kaapython-Version-Min: 0.00.0
Name: Hello, World!
Package: hello_world
Имя и версия будут отображаться в списке установленных плагинов. Максимальная/минимальная версии Kaapython'а покажут под какими версиями редактора плагин будет работать корректно.
Лучше всего указывать в качестве максимальной текущую версию.
Так как я не гарантирую, что даже минорные релизы не повлекут за собой кардинальные изменения и не сломают работу плагинов smile.
Пункт Сверток предназначен для установки плагина из зип-архива. Это имя домашней папки плагина.
При его установке через стандартный инсталлятор редактора (Инструменты -> Плагины -> Установить...) будет создана папка с таким именем, и в ней будут размещены все файлы плагина.

|
---- Пишем код
|

Так, теперь, разобравшись с рутиной, вернемся к собственно плагину.
Создаем новый файл __init__.py (впоследствие, как и любой другой модуль, можно его скомпилировать для экономии времени загрузки редактора) в папке плагина.
#
Первыми строками укажем
import kaapython
import ui
Так или иначе, работа любого плагина состоит либо в изменении стандартной функциональности редактора, либо в дополнении оной.
Поэтому мы подключаем весь доступный функционал редактора.
Модуль ui содержит классы, функции и константы для работы с интерфейсом и представляет из себя по сути минифреймворк, который можно использовать отдельно.
Модуль kaapython представляет сам редактор со всем его функционалом.
#
Итак, код плагина. Пояснения ниже.

def get_shortcuts(cls):
menu = old_get_shortcuts()
menu.append(ui.MenuItem(_('Hello, World!'), target=hello_world))
return menu
def hello_world():
note(_('Hello, World!'))
_ = kaapython.get_plugin_translator(__file__)
old_get_shortcuts = kaapython.repattr(kaapython.PythonFileWindow, 'get_shortcuts', classmethod(get_shortcuts))

|
---- Что к чему
|

Начнем с этой строчки
...
_ = kaapython.get_plugin_translator(__file__)
...
В Ped/Kaapython переменная "_" обычно является транслятором-переводчиком дефолтных ascii-строк в Юникод, для решения проблемы национальной локализации редактора.
Транслятор принимает на вход обычную строку (ключ в словарных файлах типа ".../lang/Russian"), и возвращает, грубо говоря, её "перевод".
В __file__ содержится путь к файлу плагина, так как он импортируется как модуль.

Таким образом, в строке кода, приведенной выше, мы получаем языковой транслятор для нашего плагина. Он будет оперировать ключами и значениями, определенными в подготовленном нами файле plugins/hello_world/lang/Russian (естественно, если текущий язык редактора - русский). Там всего один ключ "Hello, World!", и соответствующее ему значение "Привет, Мир!". Но нам для наших нужд больше и не потребуется smile.

##############

...
def get_shortcuts(cls):
menu = old_get_shortcuts()
menu.append(ui.MenuItem(_('Hello, World!'), target=hello_world))
return menu
...

и

...
old_get_shortcuts = kaapython.repattr(kaapython.PythonFileWindow, 'get_shortcuts', classmethod(get_shortcuts))
...
Утилитная функция repattr устанавливает новое значение атрибута некоторого объекта, ссылку на который в неё передают, в данном случае это метод PythonFileWindow.get_shortcuts, и возвращает старое.
В get_shortcuts мы вызываем старый, дефолтный, метод для получения списка шорткатов и добавляем в этот список наш новый шорткат.

Класс kaapython.PythonFileWindow представляет собой основу для каждого скрипта, редактируемого в редакторе. Отличный пример тавтологии, кстати winked.
Если вы создаете или открываете Python скрипт, то он будет представлен внутри редактора экземпляром этого класса.
Небольшое большое отступление: внутри редактора выстроена целая иерархия классов. Так, например, PythonFileWindow наследует от TextFileWindow, TextFileWindow от TextWindow, TextWindow от Window, Window от ui.Window.
Это даёт гибкость, которую, думаю, оценят понимающие толк в ООП, которой к сожалению, никак не удается воспользоваться в полной мере :( по причине нехватки свободного времени.
Отсюда же становится понятным для чего в Установках Kaapython есть несколько разделов с установкой шорткатов.
Метод get_shortcuts возвращает список шорткатов. Понятное дело не для каждого экземпляра класса, а для класса как класса данных. Для текстовых файлов, являющихся экземплярами класса TextFileWindow вернется один список шорткатов, для скриптов (PythonFileWindow) этот же список, но дополненный Python-специфичными фичами.
Соответственно, если вам придет в голову добавить новый класс для работы, например, с вебстраницами (*.html), то лучше всего наследовать этот класс WebPageFileWindow от класса TextFileWindow.
Ещё немного "химии" и вы получите автоматом простой вебредактор.
Возвращаясь к теме шорткатов, можно добавить, что если есть шорткаты, которыми вы привыкли пользоваться везде и всюду, то помещайте их ближе к корню наследования: если возможно, установите их в глобальных шорткатах, или текстовых шорткатах, чтобы не дублировать их в нескольких наборах.

##############

Итак, плагин написан.Теперь остается только перезапустить редактор, и испытать наш хелловорлд в действии.

Если упаковать папку плагина в зип-архив (в X-plore для этого достаточно выделить Карандашом папку и нажать клавишу вызова, на 9-ках без Карандаша нужно зажать Решетку и нажать клавишу вызова), то его можно распространять для установки непосредственно из самого редактора.

##############

Кстати говоря, в процессе испытания плагина я обнаружил и устранил (благодаря счастливой случайности smile) очень неприятный баг, который, судя по всему достался в наследство от Ped'а.
Вот такой он старый и замшелый. Неприятен он был тем, что был непонятен. Потому что написав несколько строк кода, которые понятны насквозь, трудно найти причины возникающей ошибки, которая ни на первый, ни на второй взгляд никак не связана с добавочным кодом.

################

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

Virtuos86
2010-09-21T22:12:59Z

Здесь находятся
всего 0. За сутки здесь было 0 человек

Комментарии 7

#7   Virtuos86    

Не забудь исправить ошибку (^). И в добрый путь. В принципе, в kaapython.py в методе __init__ класса Application можно посмотреть как кошерно добавлять пункты в app.menu и настройки редактора.


0 ответить

#7   Zaterehniy    

smile неплохо описан сам процесс и все что с ним связано. Спасибо, надо будет попробовать.


0 ответить

#7   Virtuos86    

dimy44, не такая уж и объемая статья-то.
Немного оффтоп. Хотя блог мой, какого фига. Вот правил недавно (и продолжаю править сейчас) довольно большой проект (>100к). Если бы не последнее моё новшество: расширенное автодополнение - я не знаю как набирал бы имена типа GenerateRandomMagicItem, которыми код проекта изобилует.


0 ответить

#7   dimy44    

я поражаюсь. Чего стоит даже такую огромную статью на телефоне набрать! Я б наверно на полтекста максимум психанул нафиг. У меня тоже нет компа:(


0 ответить

#7   Virtuos86    

FanatGD, да, весь добавочный по сравнению с Ped'ом код написан на смарте. Это примерно 3-я часть от всего кода.
#################
Я забыл добавить для тех, кто всё-таки попробует воспроизвести мои действия, где нужно поправить kaapython.py, чтобы убрать ту пресловутую ошибку.
Заходим в папку src в папке программы, открываем для редактирования kaapython.py.
Ищем метод get_plugin_translator, а именно следующие строки в нём:
...
trans = ui.Translator()
translator.try_to_load(path)
return trans
...
Вот и она, ошибка-опечатка: вместо translator должен быть trans, который создается строкой выше. translator же, это ещё одно имя для "_". То есть возвращается пустой словарь.
Если у кого есть исходники Ped, можете глянуть, там эта опечатка присутствует.


0 ответить

#7   Besplotnyi    

FanatGD, насколько мне известно, компа у него нет. Соответственно и вариантов тоже


0 ответить

#7   FanatGD    

Virtuos, неужели весь Kaapython написан исключительно на телефоне?


0 ответить

Яндекс.Метрика