Пользователь
0,0
рейтинг
3 августа 2012 в 17:01

Разработка → Создание плагина для Intellij Platform (IntelliJ IDEA, RubyMine, WebStorm, PhpStorm, PyCharm and AppCode) из песочницы

Привет, Хабр!
В данном топике я расскажу как создать простой плагин для IntelliJ IDEA и PyCharm. Так как все IDE содержат одинаковый интерфейс для работы с плагинами, то модификация его для других систем не требует значительных усилий (подробнее), в отличии от процесса непосредственной разработки.

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

Плагины пишутся на Java, UI создается на SWING. Документация для разработки плагинов состоит всего лишь из нескольких страниц и горстки примеров. На просторах интернета данная тематика не отражена совсем. Единственное, что слегка помогает это наличие исходных кодов у некоторых уже созданных плагинов.

Изначально я хотел создать окно в котором можно быстро и удобно выбрать описание стандартной библиотеки питона, но получилось плохо. Добавить ещё можно многое, хотя бы поиск и подсветку документации питона. Доделывать желания нет, пока проще по старинке использовать браузер.



Тогда начнем:

1) Подготовка среды


Плагины для IDE пишутся в IDE. Их придется установить и настроить.

Установка инструментов:

Нам потребуются:
— Java ( разработчики рекомендуют 1.6);
— IntelliJ IDEA Community Edition или Ultimate.(Я использовал первую, так как она бесплатная. Скачать можно здесь)

Настройка инструментов:

Необходимо настроить Java SDK и IntelliJ IDEA Plugin SDK:
— запускаем IntelliJ IDEA
— открываем пункт меню File | Project Structure
— выбираем вкладку SDKs, жмем на плюсик и выбираем путь к Java

— выбираем вкладку Project
— нажимаем на new, далее IntelliJ IDEA Plugin SDK и в открывшемся меню — выбираем путь к IntelliJ IDEA



Теперь можно создавать проекты плагинов.

2) Создание плагина


Плагин является обычной java программой, которая использует специальный открытый интерфейс для взаимодействия с IDE (это он только называется открытым, лучше бы closeapi назвали). Существует несколько основных видов плагинов: действие пользователя(AnAction), сервис(Service), расширения для других плагинов(Extension) и просто компоненты. Подробнее в документации. И хотя я не расширил ни одного плагина, в файле конфигурации я регистрировал именно его.

Создадим проект плагина

File | new project: Вводим имя, выбираем тип Plugin Module, выбираем SDK настроенный в шаге 1, создаем проект.




Далее в зависимости от разрабатываемого плагина действия будут индивидуальными. Я буду описывать как создавал свой плагин. За основу я взял пример плагина из документации — Tool Window. Чтобы получить его исходный код и код других примеров, необходимо скачать исходный код IDE.

Редактируем plugin.xml

После создания проекта появилась структура плагина и основной файл конфигурации — plugin.xml.



В нем мы будем регистрировать наши классы и производить их настройку. Подробнее об этом файле можно прочитать в документации.
Код файла:
<idea-plugin version="2">
  <name>DocPy</name>
  <description>Python standard documentation</description>
  <version>1.0</version>
  <vendor>YourCompany</vendor>
  <!-- please see http://confluence.jetbrains.net/display/IDEADEV/Build+Number+Ranges for description -->
  <idea-version since-build="107.105"/>
  <application-components>
    <!-- Add your application components here -->
  </application-components>
  <project-components>
    <!-- Add your project components here -->
  </project-components>
  <actions>
    <!-- Add your actions here -->
  </actions>
  <extensions defaultExtensionNs="com.intellij">
    <!-- Add your extensions here -->
  </extensions>
</idea-plugin>


Для своего плагина я добавил две строчки:

в секции idea-plugin:
com.intellij.modules.lang — для того чтобы данный плагин работал в PyCharme, если не указывать ни одной зависимости плагин будет работать только в IntelliJ IDEA. В этой секции также можно указывать необходимые зависимости для работы плагина.

в секции extensions:
— для запуска класса при старте IDE и его начальное расположение: anchor — положение окна, factoryClass — наш класс

В итоге:
<idea-plugin version="2">
  <name>DocPy</name>
  <description>Python standard documentation</description>
  <version>1.0</version>
  <vendor>YourCompany</vendor>
  <idea-version since-build="107.105"/>
  <depends>com.intellij.modules.lang</depends>
  <application-components>
  </application-components>
  <project-components>
  </project-components>
  <actions>
  </actions>
  <extensions defaultExtensionNs="com.intellij">
      <toolWindow id="PythonDoc"   secondary="true" anchor="right" factoryClass="MainPanel"   >
  </extensions>
</idea-plugin>

Cоздаем класс и графический интерфейс

Так как у меня простое графическое окно, то я создаю класс из шаблона Gui Form, что позволит мне воспользоваться удобным графическим редактором для создания интерфейса. Добавляю необходимые элементы:


Получился вот такой класс:
public class MainPanel {
    private JPanel panel1;
    private JTabbedPane tabbedPane1;
    private JTextArea MainText;
    private JList FileList;
    private JPanel FilesTab;
    private JPanel TextTab;
    private JScrollPane TextPane;
}

Тут у нас панель с двумя вкладками, на первой список файлов, на второй текст из этого файла.
Расширяем данный класс интерфейсом ToolWindowFactory. При помощи него можно мой класс сделать частью IDE и добавить стандартные средства управления(иконки, возможность расположения в произвольном месте, масштабирование и тд)

Как я узнал о данном интерфейсе? — спросите вы.
Скопировал из примера, какие ещё бывают неизвестно и нигде не написано, один из путей — искать в исходниках других плагинов.

Реализуем требуемый метод данного интерфейса — createToolWindowContent, который вызывается при создании нашего окна. Интересные в нем только последние три строчки.

@Override
    public void createToolWindowContent(Project project, ToolWindow toolWindow) {
        final String[] FilesMas = getFileList("python-3.2.3-docs-text\library\");
        FileList.setListData(FilesMas);
        //Обработчик события выбора элемента
        FileList.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                MainText.setText(readFileToStr("python-3.2.3-docs-text\library\" +
                FilesMas[FileList.getSelectedIndex()]));
                //Устанавливаем курсор в верхнюю позицию
                MainText.setSelectionStart(0);
                MainText.setSelectionEnd(0);
                //Прокручиваем в начало текста
                TextPane.getVerticalScrollBar().setValue(0);
                //Переключамся на вторую вкладку
                tabbedPane1.setSelectedIndex(1);
 
            }
        });
        MainText.setText(readFileToStr("A:\downloads\python-3.2.3-docs-text\library\sqlite3.txt"));
        //Создаем фабрику контента
        ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
        //Создаем контент(окно) с нашим GUI
        Content content = contentFactory.createContent(panel1, "", false);
        //Добавляем в IDE
        toolWindow.getContentManager().addContent(content);
    }


После добавления ещё двух функций( получение списка файлов и чтение из файла) плагин готов для следующего этапа.

3) Сборка плагина


Для использования плагина необходимо его определенным образом собрать:
Build | Prepare Plugin Module PyDoc for Deployment

Получаем в директории проекта jar файл с именем нашего проекта.

4) Устанавливаем плагин в IDE


Через настройки->Плагины->Загрузить с диска(выбираем jar полученный на предыдущем шаге) или jar файл копируем в папку plugins.

Выводы


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

Так как почти все приходилось делать вслепую, возможно я где-то допустил ошибки. Буду благодарен если поправите в комментах или через личку.

Еще немного информации есть здесь.
Исходный код моего проекта.
@overmes
карма
56,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (8)

  • 0
    overmes, большое спасибо за статью! Я недавно заинтересовался разработкой плагинов для Идеи. Поэтому для меня это очень актуально.

    > Документация для разработки плагинов состоит всего лишь из нескольких страниц и горстки примеров.

    В Eclipse все горздо хуже, кстати. Тут хоть удосужились все основные этапы кратко изложить. По паре доков создается картина что и как там работает хотя бы.

    У меня, кстати, такой вопрос есть. Насчет разработки языковых плагинов. Допустим, у меня есть компилятор, который уже сам умеет инкрементально парсить файл, строить синтаксическое дерево(есть API для получения). Но формат сильно расходится с PSI. Есть ли возможность имлпементировать все эти идеевские код-камплишены минуя PSI, на более низком уровне?
    • 0
      я не писал языковых плагинов, но думаю можно миновать PSI. Не знаю, есть ли уже созданные методы для этого или придется его переписывать для себя читая исходники оригинала(у нас ведь есть код IDE). В последнем случае мы потеряем большую часть уже созданных плюшек и это займет много времени.
  • 0
    Привет. Я еще не прочитал статью, на будущее возьмусь.

    Планировал плагин написать, эдакий хитрый. У меня есть сервис, куда можно заливать исходник скрипта, там его компилировать. Можно ли такой плагин написать? Возможно ли и не слишком ли сложно?

    Надо по первости, чтобы была панелька с кнопочками типа слить с сервера, залить, скомпилировать.
    Вторая хотелка — это языковая поддержка. Можно ли там напихать некоторых исключений для джаваскрипты, чтобы оно не подчеркивало некоторые расширения языка, как ошибки. АПИ внешний подсоеденить бы как-нить.
    Третья хотелка- панелька сбоку, типа как набор файлов в папках, только это дерево скриптов панелька с сервера загружает.

    Вот, что из этого можно сделать, а что — нет, насколько это сложно? Скажите, пожалуйста.
    • 0
      Мне кажется, что второе сделать, скорее всего, можно только грязными хаками, свой хайлайтинг запустить после джаваскриптового и удалить в нужных местах ненужный красный код (звучит просто, а на самом деле не так, скорее всего, если такой возможности таки нет, лучше обратиться к разработчикам, чтобы они добавили подобное API).
      Первое и третье сделать можно, причем, я полагаю, что малой кровью (но по первости, скорее всего, какое-то время это отнимет).
      Другой разговор, что если затронуть не openapi (особенно с грязными хаками), то вероятность, что надо будет постоянно, что-то чинить от версии IDEA к версии, довольно высока.
      • 0
        Согласен. Возможно что-то уже есть в плагинах, тогда можно взять или модифицировать.
        Первое скорее всего совсем просто. В плагине соединяться с сервером и отображать результат.
        Второе я не совсем понял, но думаю многое можно настроить через стандартные настройки.
        Третье в PyCharme есть, называется Remoute Server, можно подключаться к серверу по ssh и синхронизироваться с локальным проектом, причем если настроить, то изменения в локальном проекте будут автоматически передаваться на сервер.
    • 0
      Насчёт первого — можно попробовать написать скрипт на любом языке, а потом вызывать через CommandLine tools, либо по событиям after build и т.д.

      Насчёт второго, можно поиграться с настройками инспекций. Причём инспекции можно отключать как глобально для проекта, так и локально для какой-либо строки\выражения.
      Писать плагин для такой цели кажется нецелесообразным и очень трудозатратным.
  • 0
    Статья здоровская, но скажите, у вас глаза не ломаются при работе с такими шрифтами?
    • 0
      если вы про качество изображений, то они выглядят хуже чем есть на самом деле
      на мониторе все выглядит значительно лучше
      image

      а если вы именно про шрифт, то я от них не сильно завишу
      этот меня устраивает, хотя другие вроде и не пробовал

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