AtomでPackageを作成してみる。


##概要
最近巷ではAtomと言う`Github`製のエディタが流行っているようだ。`Sublime Text`をそこそこ使用していたのだが、基本有償なので、無償で評判の良い`Atom`に乗り換えてみた。

https://atom.io/

バージョン1.0より前のバージョンは起動が結構遅かったが、バージョン1.0になってから結構実用的になったように思える。
とは言え、個人的に慣れるには使い込む必要があった。

前置きはどうであれ、最近は`Atom`のマークダウンが気に入っており、ドキュメント作成に`Atom`と`Markdown`を利用するようになった。そこでちょっとした作業を`Package`として作成できないかなと思ったのといつもの興味で`Package`作成の手順を記述しようと思う。

##ディレクトリ構成
まずはインストールディレクトリを把握しておく。デフォルトでは下記にインストールされているようだ。

###Macの`Atom`インストールディレクトリ

```
/Users/ユーザ名/.atom
```

###`Atom`のプロジェクトディレクトリ

```
/Users/ユーザ名/github
```


![スクリーンショット 2015-08-03 21.15.33.png](https://qiita-image-store.s3.amazonaws.com/0/3184/9137580c-6ce6-cefc-bbbe-9dfd5fb17906.png "スクリーンショット 2015-08-03 21.15.33.png")


##パッケージ雛形の作成

`Atom`のメニューから[Packages]-[Package Generator]-[Generate Atom Package]を選択する。

![スクリーンショット 2015-08-03 21.09.07.png](https://qiita-image-store.s3.amazonaws.com/0/3184/fba39a46-352d-7f67-9e68-e4a6e13b8173.png "スクリーンショット 2015-08-03 21.09.07.png")

するとパッケージを生成する先を聞かれる

![スクリーンショット 2015-08-03 21.09.59.png](https://qiita-image-store.s3.amazonaws.com/0/3184/4d3c3ade-7eb5-75e7-f886-4a1bad4442ce.png "スクリーンショット 2015-08-03 21.09.59.png")


すると指定したディレクトリ内にパッケージの雛形が生成される。

![スクリーンショット 2015-08-03 21.12.38.png](https://qiita-image-store.s3.amazonaws.com/0/3184/25523f2e-172e-4a55-d582-db4e393c80dd.png "スクリーンショット 2015-08-03 21.12.38.png")


##デバッグ
ちなみに、`[command]+[option]+[i]`によって、`Atom`の開発ツールのインスペクタ画面が開くようだ。この画面で`console.log`デバッグできる。

![スクリーンショット 2015-08-03 21.38.27.png](https://qiita-image-store.s3.amazonaws.com/0/3184/2c83c1e9-fc14-217d-a37b-8d6ab98f5673.png "スクリーンショット 2015-08-03 21.38.27.png")


##主なファイル構成

ここからは生成されたファイルの主要なものを説明していく。

基本的に、`CoffeeScript`という`JavaScript`言語のコードに変換される言語で記述されている。

###メニューの変更

まずは簡単なところで、メニューを変更してみる。

```menus/my-package.cson
# See https://atom.io/docs/latest/hacking-atom-package-word-count#menus for more details
'context-menu':
  'atom-text-editor': [
    {
      'label': 'Toggle my-package'
      'command': 'my-package:toggle'
    }
  ]
'menu': [
  {
    'label': 'Packages'
    'submenu': [
      'label': 'こんにちは。'
      'submenu': [
        {
          'label': '私のパッケージ'
          'command': 'my-package:toggle'
        }
      ]
    ]
  }
]
```

`Atom`を再起動すると下記のようなメニューができる。

![スクリーンショット 2015-08-03 21.48.37.png](https://qiita-image-store.s3.amazonaws.com/0/3184/6dde36ec-d509-b270-a2a9-85eda18cd0ed.png "スクリーンショット 2015-08-03 21.48.37.png")



###パッケージの定義ファイル

このファイルでは、パッケージの名前等が定義されているが、重要な部分で言うと、"main": 部分で初期に呼ばれる`CoffeeScript`クラスをしてするようだ。
例えば、この部分を`"./lib/main"` にすることで、`main.coffee`が呼ばれる。

```package.json
{
  "name": "my-package",
  "main": "./lib/my-package",
  "version": "0.0.0",
  "description": "A short description of your package",
  "keywords": [
  ],
  "activationCommands": {
    "atom-workspace": "my-package:toggle"
  },
  "repository": "https://github.com/atom/my-package",
  "license": "MIT",
  "engines": {
    "atom": ">=1.0.0 <2.0.0"
  },
  "dependencies": {
  }
}

```

次に、メッセージ内容を変更してみる。

```lib/my-package-view.coffee
#
module.exports =
class MyPackageView
  #コンストラクタ
  constructor: (serializedState) ->
    #ドキュメントで<div></div>タグを作成する。
    @element = document.createElement('div')

    #class属性を追加する。<div class='my-package'></div>にする。
    @element.classList.add('my-package')

    #こんな感じのタグを作成している。
    #<div class='my-package'>
    #  <div class='message'>こんにちは。たぢさん。</div>
    #</div>
    message = document.createElement('div')
    message.textContent = "こんにちは。たぢさん。"
    message.classList.add('message')
    @element.appendChild(message)

  # Returns an object that can be retrieved when package is activated
  serialize: ->

  # Tear down any state and detach
  destroy: ->
    @element.remove()

  getElement: ->
    @element

```


表示されるメッセージが変わった。

![スクリーンショット 2015-08-03 22.00.29.png](https://qiita-image-store.s3.amazonaws.com/0/3184/3ceba36a-c1d3-89fd-a26d-92eaf1a12119.png "スクリーンショット 2015-08-03 22.00.29.png")




わかりやすくメイン処理のクラスコメント化してみた。
内容があっているかどうかは今後も調査予定。

```lib/mypackage.coffee
#Viewであるmy-package-viewを読み込む。
MyPackageView = require './my-package-view'
{CompositeDisposable} = require 'atom'

#パッケージの初期化処理
module.exports = MyPackage =
  myPackageView: null
  modalPanel: null
  subscriptions: null

  #パッケージがアクティベートされる時に呼ばれる処理
  activate: (state) ->
    @myPackageView = new MyPackageView(state.myPackageViewState)

    #モーダルパネルをmy-package-viewで作成する。
    @modalPanel = atom.workspace.addModalPanel(item: @myPackageView.getElement(), visible: false)

    #イベントを入れる管理してくれる箱のようなもの？
    @subscriptions = new CompositeDisposable

    #コマンドを登録する。下記のtoggleメソッドと'my-package:toggle'を紐付け定義する。
    @subscriptions.add atom.commands.add 'atom-workspace', 'my-package:toggle': => @toggle()

  #破棄処理
  deactivate: ->
    @modalPanel.destroy()
    @subscriptions.dispose()
    @myPackageView.destroy()

  #不明なので後日調査
  serialize: ->
    myPackageViewState: @myPackageView.serialize()

  #実装したいコマンド処理
  toggle: ->
    console.log 'MyPackage was toggled!'

    if @modalPanel.isVisible()
      @modalPanel.hide()
    else
      @modalPanel.show()

```



今回は長くなりそうなので、ここまで。

今後も、これらの`CoffeeScript`ファイルを読み解いて行こうと思う。