Edit with Emacs（Chrome版It's All Text!的な）を使ってtextareaをVimで編集する

Edit with EmacsというChrome拡張とローカルに立てたサーバを使って、textareaをエディタで編集できるようにする。

MacとVimを使った設定方法を書いていくが、Windowsと他のエディタでもできるはず。


まず[Edit with Emacs - Chrome ウェブストア](https://chrome.google.com/webstore/detail/edit-with-emacs/ljobjlafonikaiipfkggjbhkghgicgoh)にある拡張をインストールする。
次に、pythonで書かれたedit-serverを`git clone`する

* [timbertson/edit-server: an edit server compatible with TextAid and "Edit with Emacs" chrome extensions](https://github.com/timbertson/edit-server)

しかし、これだと日本語を適切に扱ってくれないので、修正した

* [tmsanrinsha/edit-server: an edit server compatible with TextAid and "Edit with Emacs" chrome extensions](https://github.com/tmsanrinsha/edit-server)

を使うか、

* https://github.com/tmsanrinsha/edit-server/commit/7dd6dc24b5a4281aea7a70b2f665b911ab2e8e3a

のように修正する。

edit-serverはデフォルトでエディタは`gvim -f`を使い、ポート番号は9292を使う。このままでいいなら

```
$ /path/to/edit-server
```

で起動する。ここで`edit-server`はディレクトリではなくリポジトリに入っているファイル。起動時に

```
WARNING: env_importer not loaded - filters disabled
```

がでるが、これは気にしなくていい。

起動したら、textareaの右下にあるeditボタンを押せば、gvimが立ち上がり編集可能となり、保存すると内容がtextareaに反映される。fileencodingがutf-8でないと気はutf-8に変更しよう。

```
set fileencoding=utf-8
```

gvim以外を使いたい場合は環境変数`EDIT_SERVER_EDITOR`を変更する。PATHに入っているか、絶対PATHで設定する必要あり。

`--port`でポート番号を変更することもできる。ポート番号を変更する場合はEdit with EmacsのオプションのConfigurationのポート番号も合わせて変更する。

エディタをemacsclient、ポート番号9293を使う例。

```
$ EDIT_SERVER_EDITOR='emacsclient' /path/to/edit-server --port 9293
```

ここでemacsを例にあげたが、emacsの場合はelispで設定できるのでedit-serverは必要ない（[EmacsWiki: Edit with Emacs](https://www.emacswiki.org/emacs/Edit_with_Emacs)）。

また、エディタの立ち上げ方法はEdit with Emacsのオプションで幾つか設定できる。

## PC起動時に有効にする

毎回コマンドラインからedit-serverを立ち上げるのは面倒なので、LaunchAgentsを設定をする。

```xml:~/Library/LaunchAgents/edit-server.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
   <dict>
        <key>Label</key>
        <string>edit-server</string>
        <key>ProgramArguments</key>
        <array>
            <string>sh</string>
            <string>-c</string>
            <string>
                export EDIT_SERVER_EDITOR="/Applications/MacVim.app/Contents/MacOS/gvim -f";
                python
                $HOME/src/github.com/tmsanrinsha/edit-server/edit-server
            </string>
        </array>
        <key>OnDemand</key>
        <false/>
        <!-- <key>StandardOutPath</key> -->
        <!-- <string>/Users/tmsanrinsha/logs/edit&#45;server.log</string> -->
        <!-- <key>StandardErrorPath</key> -->
        <!-- <string>/Users/tmsanrinsha/logs/edit&#45;server&#45;err.log</string> -->
    </dict>
</plist>
```

環境変数を設定するために`sh -c`で囲んでいる。以下のコマンドを実行しているのと同じ。

```bash
$ sh -c "export EDIT_SERVER_EDITOR=\"/Applications/MacVim.app/Contents/MacOS/gvim -f\"; python $HOME/src/github.com/tmsanrinsha/edit-server/edit-server"
```

gvimがPATHに入ってないようなので、絶対パスで指定している。`$HOME`は使えるようだ。
StandardOutPath, StandardErrorPathはデバッグ用。うまくいかない時はここのコメントを外す。ファイルパスの部分は自分の環境に合わせる。ここでは$HOMEなどの環境変数は使えない。

```bash
$ launchctl load ~/Library/LaunchAgents/edit-server.plist
```

で設定を読み込む。editボタンでgvimが立ち上がるかを確かめる。成功している場合は次回からはPC起動時にedit-serverが立ち上がる。

立ち上がらない場合はedit-serverのプロセスの確認や、ログの確認などを行う。

プロセスがない場合は起動時に失敗している可能性がある。`sh -c ...`のコマンドを直接実行して失敗しないか、xmlの書き方が間違ってないかを確かめる。xmlのチェックは

```bash
$ plutil -lint  ~/Library/LaunchAgents/edit-server.plist
```

でできる。xmlの変更を行った場合はunloadしてからloadする。

```bash
$ launchctl unload ~/Library/LaunchAgents/edit-server.plist
$ launchctl load ~/Library/LaunchAgents/edit-server.plist
```

## 補足

### pythonのエンコード

元々のコードだと

```
UnicodeDecodeError: 'ascii' codec can't decode
```

がでた。

```python
self.wfile.write(contents.encode('utf-8'))
```

という箇所で失敗している。

`.encode('utf-8')`はunicode文字列をutf-8でエンコードしたstr文字列に変換するメソッドだが、contentsがstr文字列なため（これは`type(contents)`で確認した）pythonが良きに計らって、unicode文字列型に変換しようとし、デフォルトのasciiでデコードしようとして失敗しているようである。contentsは元々utf-8でエンコードされたstr文字列なのでこの変換はいらず、

```python
self.wfile.write(contents)
```

でうまくいく。

以下を参考にした。

* [Python2で文字列を処理する際の心掛け - Qiita](http://qiita.com/FGtatsuro/items/cf178bc44ce7b068d233)
* [Python2のstr/unicodeとencode/decode - Qiita](http://qiita.com/yubessy/items/9e13af05a295bbb59c25)

### .pyc

修正する仮定で.pycというキャッシュファイルができて、うまく反映できなかった。[.pycファイルを作成させない方法メモ - かせきのうさぎさん](http://d.hatena.ne.jp/itasuke/20111215/pyc_file)によると`-B`オプションを使うと、.pycを作らなくなるので、つけて修正していた。

```bash
$ python -B /path/to/edit-server
```
[[python] 細かすぎて伝わりにくい、Pythonの本当の落とし穴10選 | 私の小岩ホッチキス](http://kwatch.houkagoteatime.net/blog/2014/08/24/python-pitfalls/)によるとタイムスタンプが.pyのタイムスタンプが更新されていたら、再度.pycを作り直すらしいが……。

### LaunchAgentsでの環境変数の設定

LaunchAgentsの環境変数の設定は[HowTo: Set an Environment Variable in Mac OS X - launchd.plist - Dowd and Associates](http://www.dowdandassociates.com/blog/content/howto-set-an-environment-variable-in-mac-os-x-launchd-plist/)に書いてある方法で設定が可能で、`$ launchctl load`した後はうまくいったが、PCを再起動するとうまくいかなくなった。plistの読み込み順に問題があるのかも。