はじめに
Atomアドベントカレンダー21日目の記事(飛び入り参加)です。
Atomを使用している方であれば、普段から$ apm install {パッケージ名}
というコマンドを叩いたり、Settings > Install
から検索したりして、様々な便利なパッケージをインストールしているかと思います。
そんなAtomのパッケージですが、最近こちらの記事を見て、実は思っていた以上にお手軽に自作できてしまうということを今更ながら知りました!
この記事では、Atomパッケージ自作の入門として「コマンド実行後、一定時間が経過したらIt's Time!
というメッセージを表示する」という簡単なパッケージを作成する手順を紹介していきます。
なお、開発環境は以下の通りです。
-
OS
:macOS Sierra 10.12.6
-
Atom
:1.22.1
パッケージの雛形を生成
まずはパッケージの雛形を生成します。
コマンドパレットを表示(Macの場合:cmd-shift-p
)してPackage Generator: Generate Package
を実行すると、生成するパッケージのパスの入力(デフォルトでは~/github/my-package
)を求められます。
※本来であれば適切な名前をつけるべきですが、ここではデフォルトの~/github/my-package
のままパッケージを生成したものとします。
パッケージのパスを入力すると、~/github/my-package
以下に下記のようなファイルやディレクトリが生成され、同時に~/.atom/packages
以下に生成したパッケージ(~/github/my-package
)へのシンボリックリンクが貼られます。
余談ですが、自作パッケージをアンインストールすると~/.atom/packages
以下のシンボリックリンクは削除されますが、生成したパッケージのディレクトリ自体は削除されないようです。
.
├── keymaps
│ └── my-package.json
├── lib
│ ├── my-package-view.js
│ └── my-package.js
├── menus
│ └── my-package.json
├── package.json
├── spec
│ ├── my-package-spec.js
│ └── my-package-view-spec.js
└── styles
└── my-package.less
...
my-package -> /PATH/TO/~/github/my-package
...
雛形の状態ではmy-package:toggle
というコマンドが定義されていて、このコマンドを実行すると以下のようなモーダルが表示されます。
主要なファイルについては、ざっくりと説明すると以下の通りです。
-
package.json
: パッケージの説明や依存ライブラリなどを定義する -
lib/my-package.js
: パッケージのエントリポイント -
keymaps/my-package.json
: パッケージのショートカットキーを定義する -
menus/my-package.json
: メニューバーやコンテキストメニュー(右クリックで表示するメニュー)の表示内容を定義する
各ファイルの内容はそれぞれ以下のようになっています。
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": {
}
}
-
main
: エントリポイントへのパスの指定 -
activationCommands
: パッケージを有効化するためのコマンドの指定-
my-package:toggle
コマンドを実行するまでパッケージの読み込み(有効化)を遅延させるように定義されている
-
activationCommands
については、定義自体を削除するとAtomの起動と同時にパッケージが有効化されるようになります。
ただし、起動と同時にパッケージを有効化しようとするとその分起動時の動作が重くなってしまうので、コマンド実行型のパッケージであればactivationCommands
を定義しておいた方がよさそうです。
lib/my-package.js
'use babel';
import MyPackageView from './my-package-view';
import { CompositeDisposable } from 'atom';
export default {
myPackageView: null,
modalPanel: null,
subscriptions: null,
activate(state) {
this.myPackageView = new MyPackageView(state.myPackageViewState);
this.modalPanel = atom.workspace.addModalPanel({
item: this.myPackageView.getElement(),
visible: false
});
// Events subscribed to in atom's system can be easily cleaned up with a CompositeDisposable
this.subscriptions = new CompositeDisposable();
// Register command that toggles this view
this.subscriptions.add(atom.commands.add('atom-workspace', {
'my-package:toggle': () => this.toggle()
}));
},
deactivate() {
this.modalPanel.destroy();
this.subscriptions.dispose();
this.myPackageView.destroy();
},
serialize() {
return {
myPackageViewState: this.myPackageView.serialize()
};
},
toggle() {
console.log('MyPackage was toggled!');
return (
this.modalPanel.isVisible() ?
this.modalPanel.hide() :
this.modalPanel.show()
);
}
};
-
activate(state)
: パッケージ起動時(パッケージが有効化された際)の処理-
this.subscriptions.add(atom.commands.add(...))
:my-package:toggle
コマンドを実行した際にtoggle()
メソッドを呼び出すように定義されている
-
-
deactivate()
: パッケージ終了時の処理
keymaps/my-package.json
{
"atom-workspace": {
"ctrl-alt-o": "my-package:toggle"
}
}
-
atom-workspace
領域内でctrl-alt-o
を押下することでmy-package:toggle
コマンドを実行するように定義されている
menus/my-package.json
{
"context-menu": {
"atom-text-editor": [
{
"label": "Toggle my-package",
"command": "my-package:toggle"
}
]
},
"menu": [
{
"label": "Packages",
"submenu": [
{
"label": "my-package",
"submenu": [
{
"label": "Toggle",
"command": "my-package:toggle"
}
]
}
]
}
]
}
-
context-menu
:atom-text-editor
領域でのコンテキストメニューにToggle my-package
というラベルでmy-package:toggle
コマンドの実行処理を定義されている -
menu
: メニューバー >Packages
>my-package
>Toggle
というラベルでmy-package:toggle
コマンドの実行処理を定義されている
機能実装
ここからは、今回作成するパッケージの機能を実装していきます。
1. メッセージを表示する
まずはコマンド実行時にIt's Time!
というメッセージを表示させます。現時点では、とりあえずメッセージの表示にはwindow.alert()
を使用します。
toggle() {
- console.log('MyPackage was toggled!');
- return (
- this.modalPanel.isVisible() ?
- this.modalPanel.hide() :
- this.modalPanel.show()
- );
+ window.alert("It's Time!");
}
ソースコードの修正後、変更内容を反映させるにはAtomを再起動する必要があります。
メニューからView
> Developer
> Reload Window
を選択することで再起動できますが、キーボードショートカット(Macの場合:ctrl-alt-cmd-l
)を覚えておくと便利です。
再起動後、my-package:toggle
コマンドを実行すると以下のような形式でメッセージが表示されます。
2. 一定時間が経過したらメッセージを表示する
次に、コマンド実行してから一定時間が経過してからメッセージを表示するように修正します。setTimeout()
を使用して5秒後にメッセージを表示させます。
toggle() {
- window.alert("It's Time!");
+ setTimeout(() => {
+ window.alert("It's Time!");
+ }, 5000);
}
また、メソッド名やコマンドの名称、メニューのラベルをtoggle
からcountdown
に変更しておきます。
"activationCommands": {
- "atom-workspace": "my-package:toggle"
+ "atom-workspace": "my-package:countdown"
},
this.subscriptions.add(atom.commands.add('atom-workspace', {
- 'my-package:toggle': () => this.toggle()
+ 'my-package:countdown': () => this.countdown()
}));
...
- toggle() {
+ countdown() {
"atom-workspace": {
- "ctrl-alt-o": "my-package:toggle"
+ "ctrl-alt-o": "my-package:countdown"
}
"context-menu": {
"atom-text-editor": [
{
- "label": "Toggle my-package",
- "command": "my-package:toggle"
+ "label": "Countdown",
+ "command": "my-package:countdown"
}
]
},
...
"submenu": [
{
- "label": "Toggle",
- "command": "my-package:toggle"
+ "label": "Countdown",
+ "command": "my-package:countdown"
}
]
3. カウントダウンの秒数をユーザが設定できるようにする
これまでの修正によりコマンド実行の5秒後にメッセージが表示されるようになりましたが、この秒数をユーザが設定できるようにします。
エントリポイントに設定しているメインのスクリプト(lib/my-package.js
)にconfig
を定義することで、ユーザ設定が有効になります。
export default {
-
+ config: {
+ "countdownSeconds": {
+ "type": "integer",
+ "default": 5
+ }
+ },
myPackageView: null,
上記の定義を追加することで、パッケージ設定画面にユーザ設定の項目(Countdown Seconds
)が追加されます。
atom.configを参照してユーザ設定の値を取得し、任意の秒数が経過したらメッセージを表示するように修正します。atom.config.get()
の第一引数は{パッケージ名}.{configのキー名}
の形式で指定します。
countdown() {
+ const countdown_seconds = atom.config.get('my-package.countdownSeconds');
setTimeout(() => {
window.alert("It's Time!");
- }, 5000);
+ }, countdown_seconds * 1000);
}
これで「コマンド実行後、一定時間が経過したらIt's Time!
というメッセージを表示する」という機能を持ったパッケージが自作できました!
4. おまけ:メッセージの表示形式を変更
これで必要な機能は実現できましたが、せっかくなのでwindow.alert()
の代わりにAtomに用意されているメッセージ通知機能を利用してみます。
atom.notificationsを使用することでメッセージ通知が実現できます。
今回はatom.notifications.addInfo()を使用してみます。
setTimeout(() => {
- window.alert("It's Time!");
+ atom.notifications.addInfo("It's Time!");
}, countdown_seconds * 1000);
また、オプションとしてdismissable: true
を指定することでユーザが任意のタイミングで通知メッセージを閉じることができるようになります。
setTimeout(() => {
- atom.notifications.addInfo("It's Time!");
+ atom.notifications.addInfo("It's Time!", {dismissable: true});
}, countdown_seconds * 1000);
これらの修正を加えることで、以下のような形式で通知メッセージが表示されるようになります。
完成したソースコード
機能実装後の最終的なソースコードは以下の通りです。
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:countdown"
},
"repository": "https://github.com/atom/my-package",
"license": "MIT",
"engines": {
"atom": ">=1.0.0 <2.0.0"
},
"dependencies": {
}
}
lib/my-package.js
※これまでの機能実装の部分では特に取り上げていませんでしたが、不要なコードは削除しています。
'use babel';
import { CompositeDisposable } from 'atom';
export default {
config: {
"countdownSeconds": {
"type": "integer",
"default": 5
}
},
subscriptions: null,
activate(state) {
this.subscriptions = new CompositeDisposable();
this.subscriptions.add(atom.commands.add('atom-workspace', {
'my-package:countdown': () => this.countdown()
}));
},
deactivate() {
this.subscriptions.dispose();
},
countdown() {
const countdown_seconds = atom.config.get('my-package.countdownSeconds');
setTimeout(() => {
atom.notifications.addInfo("It's Time!", {dismissable: true});
}, countdown_seconds * 1000);
}
};
keymaps/my-package.json
{
"atom-workspace": {
"ctrl-alt-o": "my-package:countdown"
}
}
menus/my-package.json
{
"context-menu": {
"atom-text-editor": [
{
"label": "Countdown",
"command": "my-package:countdown"
}
]
},
"menu": [
{
"label": "Packages",
"submenu": [
{
"label": "my-package",
"submenu": [
{
"label": "Countdown",
"command": "my-package:countdown"
}
]
}
]
}
]
}
おわりに
簡単な実装例を取り入れつつ、Atomのパッケージを自作する手順について紹介しました。表題通り10分で学べる程度のボリュームに上手くまとまっているかは微妙なところですが、この記事を通して「Atomパッケージの自作は意外と簡単にできてしまう」ということが伝わっていれば幸いです!
時間があれば、いずれ今回作ったパッケージを実際に公開してみようと思います。