Pull to refresh

Создание плагина для Intellij Platform (IntelliJ IDEA, RubyMine, WebStorm, PhpStorm, PyCharm and AppCode)

Reading time5 min
Views17K
Привет, Хабр!
В данном топике я расскажу как создать простой плагин для 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, мало пишут о процессе создания плагинов, что не содействует их появлению и развитию. В итоге это похоже на поиск выхода из комнаты без единого источника света. Надеюсь мой пост даст некоторый толчок в данном направлении.

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

Еще немного информации есть здесь.
Исходный код моего проекта.
Tags:
Hubs:
Total votes 38: ↑37 and ↓1+36
Comments8

Articles