はじめに
複数端末でAtomの設定やパッケージを共有するためにはどのような方法があるかを模索している。
まだちゃんとしたやり方は定まっていないが、頭の中を整理するためにもメモを残す。
方法1: .atomディレクトリをまるごと移す
調べていて多く見つかったのは、DropBoxに.atomディレクトリを移し、各端末でそのディレクトリにリンクを貼るという方法だった。
一番わずらわしくない方法だが、デメリットが許容できないので見送った。
デメリット
- 各パッケージのファイルまで同期してしまう
- DropBoxならばまだ許容範囲内かもしれないが、どうせなら
gitでバージョン管理したい- 独自パッケージならまだしも、他の方が作成しているパッケージまで
git管理下に置きたくない
- 独自パッケージならまだしも、他の方が作成しているパッケージまで
- DropBoxならばまだ許容範囲内かもしれないが、どうせなら
- パッケージによっては
config.csonにパスが記載されることとなるが、WindowsとLinux/Macでパスの表記方法が異なるため問題が発生すると思われる
方法2: sync-settingsパッケージを利用する
コメント欄にてsync-settingsというパッケージを紹介いただいた。
各種設定をgistにアップロードして同期を行うというもののようだが、いくつかこちらの要件に合わなかったため申し訳ないが見送ることとした。
懸念1: 端末固有としたい設定も同期する
config.cson(sync-settingsではsettings.jsonという名称で保存している模様)にはディレクトリパスが記載されるものがある。
例えばcore.projectHomeがそれに当たるのだが、sync-settingsはこれらも同期を行うようだ。
Linux/Mac間での同期であればあまり問題にならないと思うが、ここにWindowsが同期対象として入ってきた場合、ディレクトリパスを同期してしまうと問題が発生することが懸念される。
また、core.projectHome以外にもパッケージがパスを追記するケースがあるため、単純にcore.projectHomeを設定しなければ回避できる問題という訳ではない。
懸念2: settings-viewのソースを利用している
パッケージのインストールのためにCore Packagesのsettings-viewからpackage-manager.coffeeをコピーして同梱しているようだ。
MITライセンスなので再利用である旨さえ明記しておけばライセンス上は問題ないのだが、Core Packages由来のコードだけあってAPIドキュメントにはないメソッドをいくつも利用している。
非公開のメソッドであるため、特にアナウンスなく挙動が変更となる可能性があるものを数多く利用するのは精神衛生上あまりよろしくない。
(先日非公開のメソッドを利用していたばかりに動作しなくなったremote-editがよい例である)
懸念3: パッケージのアンインストール情報の同期には未対応?
実際に試したわけではないのだが、ソースを読む限り追加のインストールしかしておらず、アンインストールの情報は同期していないようだ。
正確にはパッケージの情報を記載しているpackages.jsonからは消えているのだろうが、リストアをする際に消えたパッケージをチェックしていないため、とある端末では削除したパッケージが別の端末ではインストールされたままという状態になってしまう。
方法3: 個別にがんばる
.atomディレクトリまるごと同期を行わないのであれば、パッケージと各種設定の同期を個別の方法でやる必要がある。
現在は下記の方法を検討している。
パッケージの同期
apm starsを使う
パッケージのバージョンまで合わせる必要がない、常に最新バージョンをインストールしたい場合はapm star及びapm starsで同期が可能となる。
インストール済みのパッケージ全てにスターを付ける
$ apm star --installed
スターを付けたパッケージをインストールする
$ apm stars --install
apm listを使う
パッケージのバージョンまで合わせたい場合、apm listでバージョン付きのパッケージ一覧を作成し、apm installで一覧を読んでインストールする方法を利用する。
参考: インストールされてるpackageをgitで管理したい
インストール済みパッケージ一覧を作成する
$ apm list --installed --bare > atom-packages.txt
パッケージ一覧を読んでインストールする
$ apm install --packages-file atom-packages.txt
起動時にパッケージをインストールする
FIXME: あとでもっと調べる
init.coffeeでchild_processを利用してapmコマンドを操作すればパッケージのインストールは可能となるはずである。
問題はインストールしたパッケージのロードで、atom.packages.loadPackages()を使えばロード自体は出来るのだが、PackageManagerのAPIドキュメントを見てもloadPackages()の記載がないのでこれを利用するのはあまり褒められたやり方ではないのだろう。
(これを用いるとonDidLoadInitialPackagesイベントが呼ばれるため、パッケージのロード時に一度だけ呼ばれる想定の処理が複数回呼ばれる可能性があり、あまりよろしくない)
loadPackages()の処理を模倣するにしても、APIドキュメントに記載のないものをいくつも利用しているため、公開APIだけを利用して模倣するには無理があるようだ。
2015/11/30 Update 机上の空論追記
しばらく調べてみたが、APIドキュメントに記載がある範囲ではうまく実現できそうにないと判断した。
もしAPIドキュメントに記載がある範囲で実現する場合、apmコマンドで更新した後にパッケージの再ロードのためにWindow: Reloadを促すダイアログを表示する必要があるだろう。
sync-settingsパッケージではCore Packagesであるsettings-viewパッケージからpackage-manager.coffeeをコピーして利用しているが、コピーしてくるよりは「他パッケージのモジュールをロードする」という別エントリに書いた方法でsettings-viewパッケージ内のpackage-manager.coffeeを直接読んだほうがこのファイルのメンテナンスの手間がなくなる分だけまだ手間は少ないと思われる。
package-manager.coffeeの内部でもAPIドキュメントに記載がないものが多く使われているが、settings-viewはCore Packagesであることと、設定が最新のものに追随しておらずにエラーを吐くような状況で正式リリースされることはないはずなので、package-manager.coffee内部で使われている分にはこちらは気にする必要はない。
ただし、どの道このpackage-manager.coffee自体そもそも外部から呼び出すことを想定していないはずなので、ファイルパスが変わったり中身がアナウンスなく書き換わったりする可能性は大いにあるため、このファイルの変更を追って追随する必要がある。
各種設定の同期
config.cson
基本的な設定は同期したいが、端末固有のもの(例えばcore.projectHome)は個別に設定したい場合、config.csonをただ共有する方法を取ることが出来ない。
考えられる手段としては端末固有の設定を除いたconfig_global.csonと、端末固有の設定を記述したconfig_local.csonの2種類のファイルを作成し、同期時にこれらを統合してconfig.csonを生成するという方法。
local-settingsというプロジェクト固有の設定を読むためのパッケージがあった(が、長らくメンテされておらずIssueを見る限り今は動かないようだが)のでソースを確認したところ、config.csonとプロジェクト固有の設定をマージさせて設定を反映させる処理が書いてあったため、これを参考にすればinit.coffee内でconfig.csonを生成して再読み込みさせることが出来そうだ。
設定が変更された際のイベントは恐らくatom.config.onDidChangeで拾えるはずなので、このイベントを拾ってconfig_global.csonとconfig_local.csonに追記してやることも出来るはずである。
あくまで机上の空論であるため、後日時間を取って試すことにする。
2015/11/30 Update 「実装してみた」を追記
実装してみた
2015/12/08 Update 別ウィンドウを開いた際に設定ファイルが壊れるバグが見つかったため削除
設定ファイルが吹っ飛んでびっくりしたのだが、config.csonが空になってしまう不具合があった。
幸いgitで管理していた分は復旧できたが、危なっかしいので原因をちゃんと調査修正が出来るまでコードは削除しておくことにする。
.apmrc
これは基本端末固有の設定になるはずなので、そもそも同期の必要がないのではないかと思われる。
その他キーマップや起動スクリプト等
基本的に端末固有のものはないので、そのままgitで管理するなりDropBoxに放り込んで各端末でリンクするなりすればよいと思う。
起動スクリプトに端末固有のものを書きたい場合
例えば.atom内や$HOME(Windowsなら%USERPROFILE%が適切?)以下に.atom_init.coffeeと言った各端末固有のスクリプトを作成し、init.coffee内でそれらをrequireする方法が考えられる。
# 各端末固有の起動処理例: 環境変数PATHにパスを追加
process.env.PATH = ["/path/to/targetdir", process.env.PATH].join(":")
path = require 'path'
fs = require 'fs'
localInitPath = path.join process.env.HOME, ".atom_init.coffee"
require localInitPath if fs.existsSync localInitPath