Пишем Visual Studio Code extension для VirtualBox
VS Code достаточно мощный текстовый редактор, куда с помощью различных расширений интегрирована куча всевозможных инструментов. Мне всегда невероятно больно, когда нужно покидать его, потому что я сразу начинаю путаться в окнах и забываю, что я вообще хотел сделать. Я думаю, каждый хоть раз терялся в трех соснах во всех открытых им окнах, поэтому предположу, что вам это знакомо. У меня установлено несколько виртуальных машин, и меня невероятно раздражает, что для их запуска нужно открыть VirtualBox просто чтобы нажать кнопку Run. Собственно говоря, сегодня я расскажу, как избавился от своей боли.
Это статья проведет вас через весь путь создания VirtualBox extension - от генерации базового шаблона, до управления виртуалками из VS Code.
Прежде чем бежать сломя голову и начинать что-то писать, нужно посмотреть, возможно уже есть что-то готовое. Поэтому отправляемся в VSCode Marketplace и убеждаемся, что, к сожалению, ничего готового нет, и всё придется делать самим. Но ещё не все потеряно, и мы отправляемся на просторы github, чтобы найти хоть что-то и находим npm пакет node-virtualbox, который мы и будем использовать для управления виртуалками.
Если вы читаете эту статью, то наверняка у вас установлены Node.js и Git, поэтому просто установите Yeoman и VS Code Extension Generator.
После чего необходимо сгенерировать, собственно, сам темплейт. Запустите следующую комманду и заполните несколько полей
Подробнее о структуре сгенерированного расширения вы можете узнать в официальной документации.
Если вы уже некоторое время пользуетесь VSCode и различными расширениями, то наверняка могли заметить, что все они выглядят достаточно стандартизированно. Несмотря на то, что VSCode написан на Electron, это не означает, что вы можете использовать все его API и верстать все что вам захочется. Ну на самом деле, есть одно место, где вам всё дозволено… ну почти всё … В остальном же, весь редактор разбит на определенные секции, которые вы можете расширять с помощью определенных компонентов, одним из которых является TreeView, который мы и будем использовать.
К сожалению, API предоставляемый пакетом virtualbox работает на колбэках, а сама библиотека написана на JavaScript, поэтому нам необходимо провести некоторую подготовительную работу.
typings
в корень проекта и создадим в ней файл virtualbox.d.ts
со всеми тайпингами, которые нам понадобятся. Таким образом мы добавляем типизация для библиотеки, которая написана на JS и не содержит готовых тайпингов.Как я уже говорил ранее, VS Code разбит на определенные секции и предоставляет возможность расширять встроенную функциональность с помощью JSON деклараций, называемых Contribution Points. В данном случае нас интересует два вида деклараций: viewsContainers и views. Теперь нам необходимо открыть package.json
в папке с расширением и найдем поле contribution
, и заменим его содержимое на следующее:
Теперь давайте разберемся, что здесь происходит. Мы объявляем viewContainer с идентификатором virtual-box-explorer и указываем, что он будет находится в activitybar, это хорошо известная нам боковая панель, в которой находятся такие viewsContainers как Explorer, Search, Git, Debugger и т.д. Далее мы объявляем view с идентификатором vb-machines и указываем, что оно будет находится внутри viewContainer с идентификатором virtual-box-explorer.
Вы наверняка заметили, что я объявил контейнер с иконкой resources/virtualbox.svg
. Размер и цвет иконок VS Code также стандартизированы, поэтому я заранее её подготовил, а вы просто скачайте её из репозитория.
Также стоит остановиться на ещё одном очень важном аспекте. Ваше расширение будет активировано только после запуска активирующего события, которые перечислены в поле actionvationEvents
в package.json
, это сделано для увеличения производительности, чтобы все расширения не загружались одновременно и не просаживали производительность. Нам необходимо чтобы расширение запускалось при открытии view, для этого заменим его содержимое на следующее:
Теперь можем приступить к самой интересной части …
Теперь, когда всё готово, приступим к выводу списка виртуальных машин (убедитесь, что у вас установлен VirtualBox). Если вы ещё не забыли, то для отображения списка виртуальных машин мы будем использовать дерево (TreeView
), где каждая виртуальная машина будет корневым узлом. Для этого нам необходимо создать класс, который реализует интерфейс TreeDataProvider
, с помощью которого TreeView
будет понимать, какие данные необходимо отобразить. Ну что ж, создадим два файла в папке src
:
vmsProvider.ts
- содержит реализацию TreeDataProvider
;vmTreeitem.ts
- содержит реализацию узла дерева, который будем отображать виртуальную машину.И теперь нам необходимо зарегистрировать созданный VirtualMachinesProvider
. Для этого в файле extension.ts
заменим метод activate
на следующий:
Давайте наконец-то запустим наш extension:
Отлично! Идём дальше! 🎉🎉🎉
Мы сделали первый шаг, но расширение всё ещё совершенно бесполезное, поэтому давайте заставим его приносить хоть какую-то пользу. Запуск любых действий в VS Code производится с помощью команд. Команды добавляются с помощью уже хорошо нам знакомых Contribution Points. Давайте добавим две команды в узлы дерева с нашими виртуальными машинами:
virtualbox-extension.runVM
virtualbox-extension.saveStateVM
для этого нужно добавить поля commands
и menus
в секцию contributes
:
Давайте разберемся, что здесь происходит.
Все команды, необходимые для расширения помещаются в секцию commands
, поэтому именно сюда мы добавляем наши команды и указываем для них category
, title
и icon
. Для того, чтобы поместить команду в виде кнопки в наше дерево, необходимо добавить секцию menus
, содержащей секцию view/item/context
. Здесь необходимо обратить внимание на поле when
с помощью которого можно регулировать видимость команды внутри узла дерева. Здесь нам и пригодится contextValue
, которое мы объявили в VirtualMachineTreeItem
, чтобы показывать кнопку запуска для выключенной виртуалки и кнопку выключения для запущенной. Подробнее обо всём этом можно почитать в официальной документации для TreeView. Ну и для простоты мы скроем наши команды из Command Palette (панель которая показывается при нажатии CTRL/CMD+P
) с помощью menus.commandPalette
.
Теперь нам необходимо зарегистрировать обработчики для объявленных команд. Добавим следующий код в метод activate
в файле extension.ts
:
Здесь нам и пригодились утилитные методы, объявленные в файле utils.ts
.
Конечный вариант файла extension.ts
вы можете найти в репозитории:
Теперь, когда всё готово, давайте запустим наш extension:
Теперь, когда наше приложение готово, мы можем его опубликовать. Подробнее с процессом публикации вы можете познакомиться в официальной документации. А я расскажу об этом вкратце.
Устанавливаем vsce (Visual Studio Code Extension Manager)
Получаем Personal Access Token. Не забудьте скопировать PAT сразу после создания, иначе он будет утерян, так как Microsoft не хранит PAT.
Убеждаемся, что в package.json
заполнены следующие поля (Но значения нужно указать ваши, а не мои 😜).
Особое внимание необходимо обратить на поле publisher
, оно нам пригодится в следующем шаге.
Создаем publisher
с тем же именем, которое указано, в package.json
. Как только, вы получили Personal Access Token, вы можете создать publisher
используя vsce
:
Публикуем расширение с помощью следующей команды:
Всё готово. На этом наш путь завершен!
Давайте ненадолго остановимся и подведем итог. Мы разобрались:
TreeDataProvider
;Также рекомендую почитать официальную документацию VS Code Extension API. И репозиторий с примерами расширений, где достаточно наглядно продемонстрированы все их возможности.