ハトネコエ Web がくしゅうちょう

プログラミングやサーバー・Web制作、チームマネジメントなど得た技術のまとめ

エレガントなコードを書くための ATOMパッケージを作りました!

最近、ブログ記事のカテゴリーがやたら増えてきたので、1記事しか無いものはカテゴリー消そう。という決意を固めつつあるハトネコエです。

今日は、近頃大人気のテキストエディタ ATOM のパッケージ(プラグイン)を自作してみたのでその話です。

1. テキストエディタ戦争

以前は Emacs を使っていましたが、設定ファイルをいちいち自分で書くのがめんどくさく感じてきて、ATOM に浮気してます。
Web のコード書くなら、ATOM はもう、テキストエディタというより IDE統合開発環境)と言えてしまうレベルです……。

EmacsVim も、自分の好きなパッケージ(プラグイン)を入れてカスタマイズできるからと一世を風靡したのですが、
そのプラグインを読み込むのに一行で済むならまだしも、
さらに細かい設定がないと呼び出せない場合とかけっこうあって、
新しいプログラミング言語を学ぶときに、その設定にまず多くの時間をとられるとかよくありました。

しかも、起動が軽いのが売りなそういったテキストエディタも、
あまりにもいろいろプラグインを入れると起動に時間がかかるようになっちゃいますし……。

ATOM はその点、パッケージを入れるのも、不要なものを停止させるのも削除するのも簡単ですからいいですね。
apm コマンドでも ATOM 内の画面からでもインストール&アンインストール出来るので、初心者にも上級者にも優しい仕組みです。

……さて、いろんなパッケージの恩恵を受けていると、今度は自分でも作ってみたくなるものです。
やってみましょう。

2. 参考URL

順番がおかしいですが、今回大変参考になったページを先にご紹介です。

これは最後のパッケージ公開についてです。

3. つくってみよう : 準備編

まず、出来上がったものがこちらです。

今回作ろうとしたのは、コードにエレガントさを足すために、
Element という言葉を Elegant という言葉に直して、(気分的に)コードを美しくしてくれるパッケージです。

これで JavaScript のコードが動かなくなる可能性はありますが、
エレガントなコードを書くための小さな犠牲ですし、jQuery を使えばおおむね大丈夫ですね!

3-1. Generate ATOM Package

ATOM のメニューバーをご覧ください。
『Packages』→『Package Generator』→『Generate ATOM Package』と進み、
パッケージ名を入力するよう促されますので、作りたいパッケージ名を入力しEnterキーを押してください。

今回は「pack-age」という名前で作ってみることにします。
ATOM のパッケージ名は、小文字をハイフンでつなぐのが慣例です。アンダーバーを使わないようにしましょう)

すると、

/keymaps
/lib
/menus
/spec
/styles
.gitignore
CHANGELOG.md
LICENSE.md
package.json
README.md

が生成されます。

では、カンタンなところからいじっていきましょう。

3-2. LICENSE.md

一行目が

Copyright (c) 2015 <Your name here>

となっているかと思います。去年の数字になってますし、MIT ライセンスということがわかりづらいので、

The MIT License (MIT)

Copyright (c) 2016 ハトネコエ

のように例えば直しておくといいと思います。

もちろん、MIT 以外のライセンスを望む場合は、ここ全体を別の文章にする必要がありますね。
参考 : ライセンスの選択を恐れる必要はありません

3-3. package.json

初期状態ではこうなっています。

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

name, main, engines については変える必要がありませんが、他はなかなかに大事です。
まず、"repository"。ここのURLをこのパッケージの開発に使う、GitHubのリモートリポジトリのURLに必ずしておきましょう。
これを忘れてしまうと、あなたが公開したパッケージに興味を持って使い方を見ようとした人が、
404ページに飛ばされてしまうというなかなか悲しいことが起こります。
f:id:nekonenene:20160224044507p:plain
GitHubのリモートリポジトリはすぐに作って、ここのURLをしっかり直しておきましょう。

それから、"description" と "keywords" も、公開ページで使われる、
短い説明文と、タグに、それぞれなりますのでとても大事です。
f:id:nekonenene:20160224045727j:plain

そしてもう1つ大事なものが、
"activationCommands" です。
デフォルトでは "atom-workspace": "pack-age:toggle" の一行だけですが、
これから別のメソッドを作っていき、……例えば pack-age:add-package という機能を作ったなら、

"activationCommands": {
    "atom-workspace": "pack-age:toggle"
    "atom-workspace": "pack-age:add-package"
},

と直しておかないと、仮に pack-age:add-package に正しくショートカットを振っていても反応してくれません。
これは気付きにくいところでしたので、お気をつけ下さい。

dependencies は npm のパッケージ管理の部分です。
npm については以前書いたこの辺りをご覧ください。まあ、今回は使いませんので、気にしないで飛ばしてもOKです。


4. つくってみよう : 実装編

実装編では、パッケージの変更を更新するため、たびたびATOMを開き直す必要があります。
開き直すと言っても、終了させる必要はなく、
メニューバーの『View』→『Developer』→『Reload Window』からおこなえます。

また、開発中は『View』→『Developer』→『Toggle Developer Tools』で開発者ツールを開いておきましょう。
コンソール出力が見られたほうがデバッグが捗りますものね。

4-1. keymaps/pack-age.cson

さて、
一番簡単なところです。手始めに、ここのショートカットを変えてみましょう。
ctrl-alt-o がデフォルトですが、必ずこれ以外のものにしておきましょう。
なぜなら、このデフォルトのままパッケージを公開している人が大勢いるためです……。
デフォルトのままにしておいたら、絶対にショートカットは動いてくれないと思っておきましょう……。

Mac の コマンドキーを使いたい場合は、cmd です。
なお、TABキー単独など、ATOMの規定上、上書きできないショートカットキーがいくらかあります。

4-2. menus/pack-age.cson

ここは、メニューバーと、右クリックメニューについての拡張です。
デフォルトですでに規定されていますので、特に今は変更する必要がありませんね。
context-menu が右クリックメニューの意味だということだけ覚えておきましょう。

4-3. lib/pack-age.coffee

さて、ここからが本番です。
実を言うと、今回のパッケージを実装するにはこのファイルだけで充分です。

現在、17行目は

@subscriptions.add atom.commands.add 'atom-workspace', 'pack-age:toggle': => @toggle()

となっています。
27行目には toggle: -> と書いてあり、 @toggle() の実際の挙動が規定されています。
(なお、modalPanel が見えていれば隠す、見えてなければ出現させる、という単純なコードですね。
この modalPanel の姿は、同じディレクトリにある pack-age-view.coffee で規定されています)

例えばこの17行目を

@subscriptions.add atom.commands.add 'atom-workspace',
  'pack-age:toggle': =>
    console.log 'とぐるんるん'
    @toggle()
  'pack-age:akari': ->
    console.log 'あっかりーん'

と直したとしましょう。

また、3-3. で書いたように "activationCommands" には pack-age:akari を追加し、
4-2. で見た menus/pack-age.cson の14行目以降は

      'submenu': [
        {
          'label': 'Toggle'
          'command': 'pack-age:toggle'
        },
        {
          'label': 'Akkari-n'
          'command': 'pack-age:akari'
        }
      ]

と直し、メニューバーに表示されるようにしたうえで、
『View』→『Developer』→『Reload Window』で ATOM を開き直します。

完了ののち、Akkari-n を実行すると、
『View』→『Developer』→『Toggle Developer Tools』でひらいていたコンソール画面に
「あっかりーん」と表示されるのが確認できると思います。

4-4. 中途半端ですが実装編はここまで

ここまで説明すれば、あとは JavaScript を書ける人であれば思い思いの実装がおこなえることでしょう。
すこし突き放した感じになってしまいますが、
おおまかな枠組みが理解できればあとは大丈夫だと思いますので、執筆労力を減らすためにここで閉じます。

私の最新のコミットは不要なファイルを削ぎ落とした状態になっているので、
今までに説明した状態に近いリビジョンであるこちらをご覧いただくのがわかりやすいかと思います。

公開されている人気パッケージはもちろん私のなんかより、より良いコードですので、
複雑ではありますが、以下から自分の作りたいものに構造が似ているものを見つけてレポジトリにアクセスし、
先輩たちのコードを読み解くのがとてもとても作る助けになります。

https://atom.io/packages


5. さあ、公開しよう

あまりに役に立たないパッケージを作ったので、公開するかはけっこう迷ったのですが、
海外の人はジョークに寛容だろう…ということで公開してみました。
そうすると、なかなか気付いたことがありましたので、いくつか気をつけるべき点を書きます。

5-1. 画像のURLは相対パスでなく絶対パス

どういうパッケージなのかわかりやすいようにスクリーンショットをREADMEに載せたいことがあるかと思います。
docs ディレクトリを作って screenshot.jpg を入れたとします。

GitHubから見るぶんには、READMEには

![Package Screenshot](./docs/screenshot.jpg)

相対パスで記述して何も問題は起こらないのですが、
このREADMEが ATOM のパッケージ紹介ページ (例えば https://atom.io/packages/pack-age というURL)にそのまま載る都合上、
その画像リンクは動作しなくなってしまいます。

ですので、 https://raw.githubusercontent.com/nekonenene/jk-elegant/master/docs/elegantify_ss.gif のような、
リモートレポジトリのスクリーンショット画像への絶対パスであるURLを、READMEでは記載するようにしておくべきです。

5-2. リリース前のバージョンは 1 より小さく

当たり前といえば当たり前の話ではありますね(笑)

パッケージの公開はコマンドラインからおこなうのですが、私は大きな失敗をしてしまいました。
「さあ、リリースするぞ」と思い、そののちファイルの整理をおこない、
package.json のバージョンを v1.1.0 と記載し、
git tag -a v1.1.0 と git タグも作りました。

そののち、説明で読んだ通り apm publish minor を実行しました。
すると、このようになってしまいました。

f:id:nekonenene:20160224062253p:plain

v1.2.0 として公開されたのです。

どうにも、apm publish の際、package.json のバージョンを読み取り、
気を利かせて、それに1足した値をバージョンとして設定するようなのです。
また、その際に「v1.2.0」の git tag も自動的に作られます。

ですから、自分でわざわざ package.json のバージョン番号を変更したり git tag を付けるべきではなく、
package.json に記載するバージョン番号は 1.0.0 より必ず小さくしておいて、
リリース時に apm publish major とコマンドすることで v1.0.0 がリリースされ、
apm publish patch で更新、というのが想定されている流れのようです。

apm publish major
apm publish minor
apm publish patch

の三種類ありますので、1.0.0 から 1.0.1 に上げるような更新を行ったときは apm publish patch

1.0.0 から 1.1.0 へは apm publish minor というふうにコマンドすればいいようです。

ちなみに、

apm publish --tag v2.5.0 minor

とコマンドすると、v2.5.0 でリリースされるかと思いきや v2.6.0 でリリースされますので、この点も注意が必要です。
なんでもプラス1されるようですね。

5-3. しめのあいさつ

以上で公開まででした。
あ、ちなみに apm publish での公開の際に、atom.io のアカウントにログインしてユーザートークンをゲットし入力するよう指示されますが、
atom.io のアカウントを今まで作っていなくとも、atom.io のアカウント = GitHub アカウントですので、
特に時間かけずにすぐにパッケージの公開がおこなえるかと思います。

f:id:nekonenene:20160224064510p:plain

atom.io

非常にいい加減なものを作りましたが、
公開されると、そこはかとなく嬉しかったです。

ぜひともこの記事をご参考にパッケージをひとつ作成してくださると
うれしく思います!(あ、でも私のよりはまともなパッケージ作ってくださいね!!!)