Создаем package для Atom

от автора


Ниже я приведу пример написания своего package для Atom.
Мы будем создавать package для генерирования marionettejs файлов на основе библиотеки о которой я писал ранее.
Для создания package я предлагаю использовать package-generator (должен быть установлен как package в вашем Atom)

  • Идем в пункт меню Packages->Package Generator->Generate Atom Package
  • Вводим имя. В моем случае atom-marionettejs-cli
  • Enter

Открываем наш package для редактирования.
Preferences->Packages -> находим свой package, открываем его, View Code
Отлично.
Теперь отредактируем меню.
Идем в ./menus/package-generator.cson, смотрим в документацию и подгоняем под себя.

Мой package-generator.cson

'context-menu':   'atom-text-editor': [     {       'label': 'Generate marionettejs application'       'command': 'atom-marionettejs-cli:generate-app'     }   ] 'menu': [   {     'label': 'Packages'     'submenu': [       'label': 'MarionetteJS CLI'       'submenu': [         {           'label': 'Generate marionettejs application'           'command': 'atom-marionettejs-cli:generate-app'         }         {           'label': 'Generate marionettejs file'           'command': 'atom-marionettejs-cli:generate-file'         }         {           'label': 'Set type'           'command': 'atom-marionettejs-cli:set-type'         }       ]     ]   } ]

И так, мы хотим чтобы юзер имел возможность выбрать файл, который он хочет сгенерировать, из списка. Для этого используем SelectListView

Код самой view

{SelectListView} = require 'atom-space-pen-views' items =   'type': [     {       label: 'ES6'       command: 'es6'     },     {       label: 'CommonJS'       command: 'cjs'     },     {       label: 'RequireJS'       command: 'rjs'     }   ],   'file': [     {       label: 'Layout'       command: '--layout'     },     {       label: 'Collection'       command: '--collection'     },     {       label: 'Model'       command: '--model'     },     {       label: 'Router'       command: '--router'     },     {       label: 'Object'       command: '--object'     },     {       label: 'Item View'       command: '--itemView'     },     {       label: 'Collection View'       command: '--collectionView'     },     {       label: 'Composite View'       command: '--compositeView'     },     {       label: 'Behavior'       command: '--behavior'     },   ]  module.exports =   class AtomMarionettejsCliView extends SelectListView     mode: null      viewForItem: (item) ->       "<li data-command='#{item.command}'>#{item.label}</li>"      showModalPanel: (@mode) ->       @panel ?= atom.workspace.addModalPanel(item: this, visible: false)       @addClass('overlay from-top')       @setItems(items[@mode])       @panel.show()       @focusFilterEditor()      cancelled: ->       @panel.hide()      getCommand: ->       selectedItem = this.getSelectedItemView();       return selectedItem.data().command;

Вот так выглядит живая view

Теперь рассмотрим наш главный файл (./lib/atom-marionettejs-cli)
Кстати, если хотите, чтобы все работало, а главный файл лежал в другом месте или содержал другое имя, просто измените строчку в вашем package.json
"main": "./lib/atom-marionettejs-cli"
Во время активации package создадим наше view и навешаем подписки на события которые будут тригериться при клике на пункт меню

... {   'label': 'Generate marionettejs application'   'command': 'atom-marionettejs-cli:generate-app' } ...

activate: () ->     @modalPanel = new AtomMarionettejsCliView()     @subscriptions = new CompositeDisposable     @subscriptions = atom.commands.add 'atom-workspace',       'atom-marionettejs-cli:generate-app': => @attach('app')       'atom-marionettejs-cli:generate-file': => @attach('file')       'atom-marionettejs-cli:set-type': => @attach('type')

Теперь нужно как-то обрабатывать событие на клик в нашем листе.

@modalPanel.confirmed = ->       path = getPath()       command = @getCommand();       if @mode is 'file'         fileName = filePrefix + command         args = ['g', command, fileName, path]       else         args = ['s', command];        cli.run(args);       @panel.hide()

Метод confirmed — это метод нашей SelectListView. Он вынесен сюда, чтобы не разносить вызов CLI (cli.run()) по разным файлам.

Код главного файла

AtomMarionettejsCliView = require './atom-marionettejs-cli-view' {CompositeDisposable, BufferedNodeProcess} = require 'atom' filePrefix = 'marionette-' cli = require 'marionette-cli/lib/cli'  getPath = ->   editor = atom.workspace.getActivePaneItem()   file = editor?.buffer.file   projectPath = atom.project.getPaths()[0]    # if opened file or project doesn't exist   if !file && !projectPath     throw new Error ('Create project or open some file')    # get path of opened file   path = editor?.buffer.file.path   # if no opened tabs   if !path     return projectPath    regexp = /(.*\/).*/g   # get path to file   regexp.exec(path)[1]  module.exports =   modalPanel: null   mode: null   subscriptions: null    activate: () ->     @modalPanel = new AtomMarionettejsCliView()     @subscriptions = new CompositeDisposable     @subscriptions = atom.commands.add 'atom-workspace',       'atom-marionettejs-cli:generate-app': => @attach('app')       'atom-marionettejs-cli:generate-file': => @attach('file')       'atom-marionettejs-cli:set-type': => @attach('type')      @modalPanel.confirmed = ->       path = getPath()       command = @getCommand();       if @mode is 'file'         fileName = filePrefix + command         args = ['g', command, fileName, path]       else         args = ['s', command];        cli.run(args);       @panel.hide()    deactivate: ->     @modalPanel.destroy()     @subscriptions.dispose()    attach: (@mode) ->     switch @mode       when 'app'         @generateApp()       when 'file', 'type'         @modalPanel.showModalPanel(@mode)    generateApp: ->     appPath = getPath() + '/app'     cli.run(['new', appPath]); 

Несколько небольших советов

  • для отладки используйте консоль (View->Developer->Toggle Developer Tools)
  • после внесенных изменений в файлы делайте перезагрузку окна (View->Developer->Reload Window), потом проверяйте работоспособность кода
  • при использовании сторонних библиотек возможна ошибка типа Refused to evaluate a string as JavaScript because 'unsafe-eval'.... Для борьбы с ней можно использовать loophole

Пишем документацию, приводим в порядок package.json и можно релизить.

git commit -am 'first release' apm publish --tag v0.1.0 minor

Репозиторий на Github
Package на atom.io

Спасибо за внимание.
P.S. Не судите строго, это был мой первый опыт с coffeescript)

Используете ли Вы Atom

Никто ещё не голосовал. Воздержавшихся нет.

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

ссылка на оригинал статьи https://habrahabr.ru/post/280057/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *