やりたいこと
ブラウザの入力エリアはとても貧弱で, とくに普段からEmacsのような高機能エディタを使っていたり, Emacsのような高機能エディタのviエミュレーションモードを使っていたりするような変態さんにとって, これは耐え難い苦痛.
JavaScriptを頑張って書いて入力エリアそのものを強化することも考えられるけれど, コストが大きい. なにか簡単な方法で, 外部のエディタとブラウザの間でやりとりさせられるならその方が楽. それを実現してみた, というお話.
具体的には, ある決められたファイルに何か書き込むと, それがブラウザのアクティブな入力エリアに書き込まれる, ということを実現する.
やり方
まずは雰囲気をつかむためにデモ動画を見てみよう.
Windowsの人
動画の通りにするだけで使える.
- FirefoxとGreasemonkeyをインストール
- Windows用のインストーラをダウンロードしてインストール
- Greasemonkey用のユーザスクリプトをインストール
- デスクトップの「テキストを編集」ショートカットを好きなエディタで開く
Windows以外(Linuxとか)の人
詳細はGitHubのリポジトリを参照.
インストール
git clone git://github.com/tarao/textserver.git cd textserver git submodule update --init mkdir some-dir echo ':dir: absolute-path-to-some-dir' > textserver.yml
でリポジトリのコピーと必要なモジュールが入る.
Debian系の人はここで
sudo aptitude install libinotify-ruby
しておくと少し幸せになる(これがないと100ミリ秒ごとにファイルの更新確認をするので非効率的, 詳細は技術的な話を参照).
起動
ruby textserver.rb -c textserver.yml
とするとデーモンが起動. あとはFirefoxにGreasemonkey用のユーザスクリプトをインストールすれば使えるようになる. 具体的には, some-dir/text というファイル(デーモンを動かすと勝手にできるはず)を編集して保存するとブラウザの入力エリアに書き込まれるようになる.
停止
デーモンを止めるときは
ruby textserver.rb -c textserver.yml --stop
とする.
高度な設定
.ymlに設定可能な項目とデフォルト値は以下の通り.
:dir: /tmp/textserver :text: text :reset: reset :lock: lock :pid: /tmp/textserver/textserver.pid :logfile: /dev/stdout :loglevel: 0 :server: :BindAddress: 127.0.0.1 :Port: 18080
別のホストでブラウザを動かす場合は:BindAddressを0.0.0.0にして, デーモンの動いているホストの名前hostnameを, Firefoxのプロファイルディレクトリにあるprefs.jsに
user_pref("greasemonkey.scriptvals.http://orezdnu.org//retrieve-remote-text.TextServer:host", "hostname");
と書き加えて設定する.
デフォルト以外(たとえば3000)の値を:Portに設定したときも, prefs.jsに
user_pref("greasemonkey.scriptvals.http://orezdnu.org//retrieve-remote-text.TextServer:textPort", 3000);
と書き加えて設定する. 実はデフォルト設定の場合も18080番と18081番の2つを使っているので, 2つ連続で空いているポートを指定すること.
Emacsとの連携
Emacs用のパッケージをload-pathのどこかに置いて, .emacsに
(require 'textarea) (setq textarea:dir "absolute-path-to-some-dir")
と書いておくと, M-x textarea
でsome-dir/textを*textarea*バッファとして開くことができる. このバッファは数秒で自動保存される. さらに, M-x revert-buffer
でブラウザの入力エリアの内容をバッファに逆流させることができる. これはすごい!
技術的な話
基本的な仕組み
デーモンはテキストファイルを監視していて, ファイルに変更があったらブラウザ側にその内容を通知するというだけ.
HTTP long polling
仕組みの上ではブラウザがサーバで, ファイルに書き込んだ側がクライアントになるけれど, 実装上はファイルの変更を監視しているデーモンがサーバで, そのデーモンに対してXMLHttpRequestするブラウザ側がクライアントになる. そこで, ファイルに変更がない間はデーモン側がレスポンスを返さないようにすることで, デーモン側の都合でデータの流れるタイミングを制御している. いわゆるHTTP long polling.
追記
It's All Text!との違い
textserverでできてIt's All Text!でできないこと:
- キーボードだけで編集する
- 既に起動しているエディタで編集する
- 入力エリアで発生した変更を任意のタイミングでエディタに逆流する
- ブラウザとは別のホストで動いているエディタで編集する
2013-01-20T16:50+0000
- Emacs用のパッケージを書き直したので設定方法を修正