Atom パッケージを作成してみる。

Atom

Atom で UUID を自動生成したくなったのをきっかけに Atom Package を作ってみることにしました。

Atom Package というのは、Atom の機能を拡張できるプラグインです。


Atom で編集しているテキストに UUID を手軽に挿入したくなったのをきっかけに、そのための Atom Package を作成してみることにしました。Atom Package というのは、Atom の機能を拡張できるプラグインです。

Atom Package を作成する

Atom Package の作成は Atom エディター自身が積極的にサポートしてくれる感じで、けっこう簡単に始めることができました。あらかじめ Atom に組み込まれている Package Generator を使って、パッケージを生成します。

パッケージを生成する

Atom のメニューから Packages Package Generator Generate Atom Package と辿ると、パッケージ名を入力するウィンドウが表示されるので、そこに名前を入力します。

大文字は区切りと判断されるみたいで、たとえば今回は uuid-inserter という名前にしていますけど、これを UUIDInserter みたいにすると、場所によっては u-u-i-d-inserter みたいな名前で扱われたりします。

パッケージの構成ファイル

これだけでパッケージを作成する環境が整いました。

ファイルは、次のようになっているようです。

名称 用途
keymaps パッケージのコマンドに割り当てるショートカットキーの設定が格納されています。
lib パッケージの実装が格納されています。
menus パッケージのコマンドを Atom メニューにどう表示させるかを設定したものが格納されています。
spec パッケージのテストコードが記載されています。 P でテストを実行できる様子です。
styles パッケージで表示するウィンドウなどのスタイルを格納しているようです。
package.json パッケージの基本情報を設定するファイルです。

パッケージにコマンドを実装する

パッケージの実装は lib/ ディレクトリーに格納することになるようです。

いちばん最初に指定したパッケージ名がつけられた lib/uuid-inserter.js というファイルがあるので、それを調整することにします。JavaScript でコードを書いていくようでした。

基本的なところ

まず、パッケージとして成り立たせるために必要な基本的なところを記載しておきます。

'use babel';

import { CompositeDisposable } from 'atom';
import { BufferedProcess } from 'atom';

export default {

  subscriptions: null,

  activate(state) {

    this.subscriptions = new CompositeDisposable();

    this.subscriptions.add(atom.commands.add('atom-workspace', {
      'uuid-inserter:insert': () => this.insert()
    }));
  },

  deactivate() {

    this.subscriptions.dispose();
  },
};

アクティブ化

とりあえず activate でパッケージが有効化される時のコードを記載して、deactivate で無効化される時のコードを記載するようです。

この時に CompositeDisposable でコマンドを登録してますけど、試してみた感じ、これをしないと Atom から自作のコマンドを実行できない様子でした。メニューからの実行やショートカットでコマンドが実行されない場合、正しく登録されているか確かめてみるのも良いかもしれません。

モジュールのインポート

冒頭でインポートしている BufferedProcess は UUID を生成するときに uuidgen コマンドを実行するときに BufferedProcess を使うために記載しています。

UUID の生成コードを実装する

それでは、先ほどの lib/uuid-inserter.js 内に『現在行に UUID を挿入するコード』を実装してみます。

コマンドで呼び出す関数の登録

先ほどの activate などと同じところに、Atom からコマンドを実行するときに呼び出す関数を追加します。

今回は insert という名前で登録することにしました。あとでコマンドを Atom のメニューに登録する方法などを紹介しますけど、そのときに指定するコマンドの関数名がこれになります。

insert() {

}

現在行を取得する

Atom で現在行を取得するのはとても簡単でした。atom.workspacegetActiveTextEditorメソッド を実行すると、現在のアクティブなテキストエディターが取得できます。あとは、テキストエディターの insertTextメソッド を呼び出せば、指定したテキストを現在位置に挿入できます。

コードの雰囲気としては次のような感じです。

var editor = atom.workspace.getActiveTextEditor()

editor.insertText(uuid)

UUID を取得する

ざっくり探してみた感じでは JavaScript には UUID を生成する機能が用意されていなそうなので、今回は Mac にインストールされている uuidgen コマンドを使って生成することにしました。

Atom パッケージで外侮コマンドを実行するには https://atom.io/docs/api/v1.13.0/BufferedProcess を使うことになるようです。これに、実行したいコマンドとオプション、標準出力に出されたテキストを受け取る関数などを指定します。

insert() {

  var command = 'uuidgen';
  var arguments = [];
  var stdout = function(output) {

    var editor = atom.workspace.getActiveTextEditor();
    var uuid = output.replace(/\n+$/g, '');

    editor.insertText(uuid);
  };

  var process = new BufferedProcess({ command, arguments, stdout });
},

uuidgen コマンドを実行すると UUID テキストが、末尾に改行付きで出力されるので、それを BufferedProcess を使って取得したら、末尾の空白を空文字に置換して、それを現在位置に挿入します。

これで、UUID を生成して、現在位置に挿入する insert コマンドが出来上がりました。

パッケージの情報や、実行経路を登録する

Atom パッケージは、パッケージの概要や、どのコマンドをどこからよびだせるかを簡単に設定できるようになっていました。

パッケージの基本情報

まずは package.json を編集して、パッケージの基本情報を登録しておきます。

注目するところとしては namedescription で、パッケージの名前と概要を設定するところでしょうか。

{
  "name": "uuid-inserter",
  "main": "./lib/uuid-inserter",
  "version": "0.0.0",
  "description": "Generate an UUID and Insert the UUID to current line.",
  "keywords": [
  ],
  "activationCommands": {
    "atom-workspace": "uuid-inserter:insert"
  },
  "repository": "https://github.com/es-kumagai/atom-uuid-inserter",
  "license": "MIT",
  "engines": {
    "atom": ">=1.0.0 <2.0.0"
  },
  "dependencies": {
  }
}

それと repository で、このパッケージを公開する Git リポジトリーの情報を添えることができます。

また、activationCommands というのがあって、詳しくはわからないのですが、ここで指定したコマンドを実行するときに初めてこのパッケージをロードするみたいなことになるらしいです。複数のコマンドがる時は、配列で指定すれば良いとかどうとか、とりあえず、このあたりはまた必要になったら調べてみることにします。今は、このパッケージに実装する唯一のコマンド insert を実行したときにアクティベートするようにします。

ショートカットキーの登録

ショートカットキーを使って UUID を挿入できるように、keymaps/uuid-inserter.json を編集します。ファイルは JSON 形式で、ここに『どのショートカットキーを押したときにどのコマンドを実行するか』という風に指定します。

{
  "atom-workspace": {
    "ctrl-alt-u": "uuid-inserter:insert"
  }
}

メニューの設定

Atom の Packages メニューに表示する項目名や実行するコマンドは menus/uuid-inserter.json で設定します。

設定は JSON 形式で、menu 以下の submenu で、項目のラベル名と実行コマンドを指定します。また context-menu では、Atom エディター上で右クリックしたときに表示されるポップアップメニューに表示する項目名とコマンドを登録できます。

{
  "context-menu": {
    "atom-text-editor": [
      {
        "label": "Insert UUID",
        "command": "uuid-inserter:insert"
      }
    ]
  },
  "menu": [
    {
      "label": "Packages",
      "submenu": [
        {
          "label": "UUID Inserter",
          "submenu": [
            {
              "label": "Insert UUID",
              "command": "uuid-inserter:insert"
            }
          ]
        }
      ]
    }
  ]
}

不要なファイルを削除

今回、自動的に作られたファイルの中で不要だった、次のファイルを削除しておきました。

Atom Package を有効化する

パッケージは、Atom のウィンドウをリロードすることで有効化できます。メニューから Packages Command Palette Toggle でコマンドラインを使って Window: Reload を実行するか、ショートカットキー L でリロードします。

こうすることで Packages の中に、自分で設定したメニューが表示され、そこから実行できます。もちろん、ショートカットキーを登録していれば、それを使っても実行できます。

実行に失敗すると…?

コードに誤りなどがあって実行できなかった場合は、即座に丁寧なエラーメッセージを表示してくれます。どのファイルのどこでエラーが出たかなどが記載されているので、修正しやすい印象でした。

おわりに

uuid-inserter

今回作成した Atom パッケージは es-kumagai/atom-uuid-inserter: Generate an UUID and Insert the UUID to current line. に公開してみました。

インストールするには apm コマンドを使って、次のようにします。そうするとリポジトリーからパッケージがダウンロードされて ~/.atom/packages にインストールされる様子でした。インストールが終わったら、既存のウィンドウを L でリロードすると使える状態になります。

apm install https://github.com/es-kumagai/atom-uuid-inserter

Atom Package の標準機能

Atom Package の開発で使える機能については https://atom.io/docs/api/v1.13.0/AtomEnvironment にまとめられていました。まだ少ししかみてないですけど、例えば https://atom.io/docs/api/v1.13.0/TextEditor とか眺めてみると、どんなことができそうかが窺えて楽しい感じです。