Humanity

Edit the world by your favorite way

hatena.vimの不満を解消する

アイスストーム!(訳:Vim Advent Calendar 2012への2回目の投稿です)
アイスストームは3連鎖目の呪文だと突っ込まれました
ぷよぷよよく知りませんがアルルって娘は僕っ娘でかわいいと思います。


初めましてこんばんは。tyruです。
この記事はVim Advent Calendar 35日目*1の記事です。
34日目は@masudaKさんの「Vimの環境を晒してみる(2013) - カイワレの大冒険」でした。


Vimユーザかつはてなダイアリーユーザの方に朗報です。
(残念ながらはてなブログには対応していません)
知っている方もいるかもしれませんが、今回紹介するのはhatena.vimというVimはてなダイアリーが更新できるVimプラグインです。(LinuxでもMacでもWindowsでも使えます)
そのhatena.vimを使いやすくしてみたのでいっちょ便利設定を紹介したいと思います。
便利設定といいつつ最近自分が追加した変数ばっかりです。
すでにあるhatena.vimの記事はどれも古く、自分が追加した変数は書かれてないので、自分が宣伝しないと誰も宣伝してくれないだろうと思ったからです。

やったこと (目次)

  • 不満1:「:w」で記事が投稿されてしまう
    • 「:w」で記事を投稿するか設定できる変数g:hatena_upload_on_writeを追加
    • 「:w!」で記事を投稿するか設定できる変数g:hatena_upload_on_write_bangを追加
  • 不満2: 「he」のマッピングが上書きされてしまう
    • デフォルトのマッピングを作るか設定できる変数g:hatena_no_default_keymappingsを追加
    • すでにマッピングが存在する場合は何もしないよう修正
  • 不満3: (:q!ではなく):qで何の断りもなく書きかけのバッファを捨ててしまう
  • 不満3.5: DropboxのWebインターフェースにアクセスしないとファイルが復元できない
    • 一時ファイルのフルパス名を指定する変数g:hatena_entry_fileを追加
  • 不満4(おまけ): ブラウザで記事を確認できない
    • Vimperatorと連携し、Vimで書いたMarkdownをVimperatorでリアルタイムプレビュー

使い方

この記事で紹介するのはあくまでhatena.vimに対する自分の変更点のみです。
使い方については色んな方が記事を書いてくれているのでそちらを参照してください。

上記記事にも書いてありますが、注意点としてはcurlコマンドがPATHに存在する必要があります。

機能

  1. 新しい記事を投稿できる
  2. 既存の記事を編集できる
  3. はてな記法のsyntax highlightが効く
  4. Vimで編集できる

hatena.vimの機能はこんなところです。
最後2つが自分にとってはポイントです。
Vimの強力なsyntax highlightと編集能力で記事が書けます。
自分はeskk.vimというSKKのような何かをVimで実現するプラグインを使っているので、それを使って日本語入力しています。*2
SKKの機能がほぼ揃っていて安定しているskk.vimもどうぞ。*3
@anyakichiさんのリポジトリではif_python,if_rubyなどを用いてskkservにも対応しているようです。*4

不満1:「:w」で記事が投稿されてしまう

いくらVimスワップファイルを備えているからといって、
無意識に保存する癖を持っている人は多いと思います。
自分のその一人なのですが、保存するとその瞬間記事が投稿されてしまいとても緊張感が楽しめる仕様だったのですが、最近自分によって「g:hatena_upload_on_write」という変数が追加され、.vimrcに次のように書くことで「:w」で記事が投稿しないようにすることができます(投稿するためには「:HatenaUpload」コマンドを実行する必要があります)。

let g:hatena_upload_on_write = 0

互換性重視のため、デフォルトでは以前の挙動のまま(g:hatena_upload_on_write = 1)です。
近いうちにデフォルト値を変えるようhatena.vim作者のmotemenさんにissues&pull req出すかもしれません。


あとまだpull req出していませんが(2013-01-07 20:30 追記:pull req出してmotemenさんのリポジトリに取り込まれました)、「:w!」で記事を投稿するか設定できる変数g:hatena_upload_on_write_bangを追加しました。
イデアid:sasaplus1さんのものです。(参考:機能が強化されたhatena.vimのテスト - 四角革命前夜)
upload-on-write-bangブランチをcheckoutして.vimrcに次のように書けば「:w!」の時にのみ投稿するようになります。

let g:hatena_upload_on_write = 0
let g:hatena_upload_on_write_bang = 1


いろいろ変数を追加したので表を作ってみました。

変数 意味 デフォルト値
g:hatena_upload_on_write :wと:w!で記事を投稿する 1
g:hatena_upload_on_write_bang :w!で記事を投稿する 0

不満2: 「he」のマッピングが上書きされてしまう

hatena.vimheに「:HatenaEdit(はてなダイアリー)」を呼び出すマッピングを作るようです。
マッピングが追加されること自体はいいのですが、.vimrcで作ったマッピングhatena.vimによって上書きされてしまいました。

ここでの問題点は

  • (.vimrcなどでユーザによって作られた)マッピングを上書きしてしまう
  • マッピングを作らないようにする設定がない

の2つですが、
前者に関しては「he」にマッピングが存在するか確認して上書きしないようにしました
後者に関しては「g:hatena_no_default_keymappings」という変数を追加しました。
.vimrcで以下のように設定するとマッピングの有無に関わらずデフォルトのマッピング*5を作りません。

let g:hatena_no_default_keymappings = 1

不満3: (:q!ではなく):qで何の断りもなく書きかけのバッファを捨ててしまう

端末で使ってるならGNOME Terminalなりscreenなりでスクロールバックさせれば端末に表示されたテキストの断片が残っている可能性がありますが(ない場合もありますが)、gVimで書いているとどうしようもありません。
これで今回ちょっと記事が吹っ飛んだので、カッとなって機能追加しました。(というかこの記事にある不満は全てカッなって追加した機能ばかりですが)


やったこととしては、書いてる最中の一時ファイルのディレクトリを指定する変数を追加しました。...が、削除しました。
意図としてはこの変数にDropboxのディレクトリを指定すればDropboxが履歴を保存してくれるので思わぬオペレーションミスの場合も安心...というつもりでした。
イデアはいいと思ったのですが、次の不満で追加した「g:hatena_entry_file」という変数で指定したファイル名(フルパス)で保存できるようにしたので、それで十分かと思い、無用な複雑さを避けるためあえて削除しました。


また、バッファが閉じられる前にプロンプトを出して、本当に閉じるかどうかユーザに尋ねるようにしたいと思ったのですが、Vimの仕様上それは無理でした。
詳しくは以下のページを見てください。

BufLeaveなどでバッファを閉じるか閉じないか制御できる仕組みがほしい · Issue #278 · vim-jp/issues · GitHub

不満3.5: DropboxのWebインターフェースにアクセスしないとファイルが復元できない

さて、不満3で一時ファイルを特定ディレクトリに保存する変数を(一時的に)追加しましたが、万が一削除してしまった場合にDropboxのWebインターフェース経由でしかファイルが復元できないのは少々面倒に感じるかもしれません。
頻繁に起こる事ではないので面倒とは感じないかもしれませんが、とりあえず面倒と感じたことにしておきます。


ここでDropbox APIを叩くVimプラグイン(metarw-dropbox)を作るのはmattnさんに任せておくとして、
Vimには多段undo機能があり、さらに7.3からはファイルにundo情報を書き出して無限undoを実現する機能が追加されました。
この機能が追加されてからというもの、「VimVCSの機能を備えたエディタである」と言い張っているのですが、なぜか反論が返ってきませんでした。周りのVimmer率が高いからでしょうか。おかげで「まぁundoじゃ単位が細かいし、そもそもコミットログないし...」みたいに毎回一人ツッコミしています。
この話は微妙に嘘で上の発言は一回しか言ったことないですが、でも全ての記録が残っているっていうのはすごく心強いですね。「無限」って単語から感じる何かこう...今までにない何か熱い無限感が押し寄せてきています。乗るしかない、このビッグウェーブに!


はい、つまりundo履歴が残るようにすればいいですね。
やるべきことは

  • 無限undoできるようにファイル名を固定化する
  • 無限undoの設定

undofile*6はファイル名(フルパス)と対になっているので、ファイル名が常に同じでなければいけません。
不満3ではディレクトリ名を指定できるようにしましたが、今度はファイル名まで指定できるとよさそうです。
なので「g:hatena_entry_file」を追加しましたただこの記事を書いた時点ではmotemenさんのリポジトリにマージされていないので、使いたい場合は私のリポジトリのentry-fileブランチをcheckoutしてください(2013-01-07 20:30 追記:motemenさんのリポジトリに取り込まれました)。次のように使います。

let g:hatena_entry_file = '~/Dropbox/memo/blogentry.txt'

そして以下が.vimrcに書く無限undoの設定です。
undodirは基本どこでもいいですが、なんとなく「~/.vim」以下に保存したかったので「~/.vim/info/undo」ディレクトリに保存するようにしています。
Windowsだと、Vimのフォルダは(特に変えてなければ)「~/vimfiles」なので「~/vimfiles/info/undo」にする必要があります。

" undo-persistence
if has('persistent_undo')
    " persistent-undo(無限undo)を使う
    set undofile
    " undoファイルを保存するディレクトリの設定
    let &undodir = '~/.vim/info/undo'
    " undodirを作成しておく
    silent! call mkdir(&undodir, 'p')
endif


注意点として、はてなダイアリーの仕様上、「g:hatena_entry_file」のファイルはEUC-JPで保存されています。*7

不満4(おまけ): ブラウザで記事を確認できない

Vim上で書いた記事をブラウザで確認できれば便利ですよね。
はてなダイアリーにログインしてWeb上で書けばいいのですが*8Vim Advent Calendarの記事で確認するのもどうかと思いますが、Vimで書きたいですよね。ね?*9

そこで、id:teramakoさんがVimperator Advent Calendarで公開してくれたvimperator-plugin-httpdjsを使うことでVimperatorがVimと連携できるようになり、リアルタイムでVimのバッファの内容などをVimperatorに表示することができます。
ただし今サポートしているのは

  • Markdown
  • Vimperatorのコマンド
  • JavaScriptの式

だけなので、はてな記法はサポートしていません。
そこで今回id:teramakoさんに機能追加のお願いをしたところ、快くOKしてくれました!id:teramako++


あとはVim側でやることはPOSTでバッファの内容を投げるだけです。
しかしこれもid:teramakoさんがinstant-markdown-vimというVimプラグインも一緒に公開してくれたので、それに少し手を加えるだけで達成できました。
具体的には

  1. vimperator-plugin-httpdjsをインストールして
  2. instant-markdown-vimをインストールして
  3. 以下の設定を.vimrcに追加

すれば目が光りますhatena.vimで編集中の記事の内容をブラウザに表示できます。

autocmd FileType hatena let b:instant_markdown_path = '/html?type=hatena'

以前はテキストが変更される度にcurlコマンドを起動してPOSTリクエストを投げてたので果てしなく重かったのですが、リクエストを投げるタイミングを調整したので随分改善したと思います。多分。

何はともあれ、これではてな記法のミスがぐっと減りますね。

text-hatena.js 自動リンク記法について追記 (2013-01-05 22:50)

id:teramakoさんからコメント欄で補足コメント頂きました。

id:teramako
vimperator-plugin-httpdjsについて少し補足です。
httpd/text-hatenaにsubmoduleとしてtext-hatena.jsが入っています。
今現在、text-hatena.jsには自動リンク機能が入っていませんが、実験的にAutoLinkブランチに完全ではないけど実装中です。このブランチで text-hatena.js の先頭あたりに
var EXPORTED_SYMBOLS = ["TextHatena"];
を加えていただければ、さらに便利になるかも。

text-hatena.jsがさらに便利になってうれしいですね。

おしまい

改めて自分の不満一覧を見てみると、巻き戻し可能でない操作に対する恐怖感が見てとれるようです。
Vimプラグインとかソフトウェアとか関係なく、巻き戻し可能でない操作は怖いので、できるだけ巻き戻し可能であってほしいとか、そういった操作はデフォルトではプロンプト出して警告するようにしてほしいと思ったりします。*10


36日目のVim Advent Calendarは@ShougoMatsuさんの「あるVimmerのブログ: Vim Advent Calendar 36日目:「暗黒美夢王が紹介するエディタアニメ 2012+おまけ」」です...でした。
Vim Advent Calendarが来年まで続くとよいですね。*11

*1:@choplinさんが欠番となったので代わりに49日目の記事をアップロードしています

*2:いつかは...いつかはちゃんとしたものに...

*3:うっ...eskkユーザの方から冷たい視線が...

*4:そろそろマージしたいと思ってるんですが腰が重い...

*5:今のところは「he」だけでした

*6::help undofile()

*7:はてなグループとかはてなブログは当然UTF-8だけどはてなダイアリーEUC-JP(でAPIに送らないといけない and EUC-JPで記事が保存されている?

*8:気分屋なのでたまに使う時はあります

*9:閲覧者の中にEmacsユーザの方はいらっしゃいませんか!いらっしゃったら両手を挙げろ!手を挙げてください!

*10:参考リンク:ちょっとだけでもやるほうがやらないよりもましな作業はどういうものか? - 発声練習

*11:地獄の行軍っぽい