Vimからはてなハイクに投稿する

vimスクリプトに興味があったので、試しにhatena.vimはてなハイク対応に改造してみました。

以下のコードを plugin/hatena.vim に追加すると、はてなハイクに投稿可能になります。

" はてなにログインし、ハイクを編集する
" Usage:
"   :HaikuEdit [<keyword>]
command! -nargs=? HaikuEdit            call <SID>HaikuEdit('<args>')

" :HaikuEdit で開いたバッファの内容をはてなに送信し、ハイクを投稿する
" Usage:
"   :HaikuPost
"command! -nargs=? HaikuPost            call <SID>HaikuPost(<args>)

function! s:HaikuEdit(...) " 編集する

    " ログイン
    if !exists('b:hatena_login_info')
        let hatena_login_info = s:HatenaLogin()
        if !len(hatena_login_info)
            return
        endif
    else
        let hatena_login_info = b:hatena_login_info
    endif

    let [base_url, user, cookie_file] = hatena_login_info
    let base_url = "http://h.hatena.ne.jp"


    "  キーワードを取得
    if a:0 > 0
        let word = a:1
    else
        let word = input('Keyword: ')
    endif

    if !strlen(word)
        echoerr 'キーワードを入力してください'
        return
    endif

    " セッション(編集バッファ)を作成
    let tmpfile = tempname()
    execute g:hatena_edit_command tmpfile
    setlocal noswapfile
    let &fileencoding = 'utf-8'

    let content = system(s:curl_cmd . ' "' . base_url . '" -b "' . cookie_file . '"')
    let b:rkm = matchstr(content, 'name="rkm"\s*value="\zs[^"]*\ze"')

    if !strlen(b:rkm)
        echoerr 'ログインできませんでした'
        if exists('s:user')
            unlet s:user
        endif
        return
    endif

    let b:word = word

    autocmd BufWritePost <buffer> call s:HaikuPost() | autocmd! BufWritePost <buffer>
    autocmd WinLeave <buffer> let &titlestring = b:prev_titlestring
    autocmd WinEnter <buffer> let &titlestring = 'Haiku!: ' . b:word . ' [' . b:hatena_login_info[1] . ']'

endfunction

function! s:HaikuPost(...) " 投稿する

    if !exists('b:word') || !exists('b:rkm')
        echoerr ':HaikuEdit してから :HaikuPost して下さい'
        return
    endif

    " ログイン
    if !exists('b:hatena_login_info')
        let hatena_login_info = s:HatenaLogin()
        if !len(hatena_login_info)
            return
        endif
    else
        let hatena_login_info = b:hatena_login_info
    endif

    let [base_url, user, cookie_file] = hatena_login_info
    let base_url = "http://h.hatena.ne.jp"

    if &modified
        write
    endif
    let body_file = expand('%')

    let post_data = ' -F rkm=' . b:rkm . ' -F "word=' . b:word
                    \ . '" -F "location=/' . user . '/" -F "body=<'
                    \ . body_file . '"'

    " ポスト
    let result = system(s:curl_cmd . ' ' . base_url . '/entry -b "' . cookie_file . '"' . post_data . ' -D -')

    if v:shell_error
        echo '投稿に失敗しました'
    else
        echo '投稿しました'
    endif

endfunction

まあ、ほぼ日記投稿部分からのコピぺだったりしますが。

それでも、バッファ変数(b:*)の有効範囲を理解してなかったので、b:wordを定義する位置がおかしくてしばらくハマりました。

あと、

:HaikuEdit キーワード

という使い方が出来るようにしようと思ったんですが、キーワードが日本語だとエラーになるので、引数を無効にしてプロンプトからの入力のみにしてます。一応ダブルクォーテーションで囲っておくとうまく行くのは分かってますが、いちいちそうするのも面倒なので。

追記

Vimからはてなフォトライフに画像を投稿するvimスクリプトを書いているときに、HaikuEditの引数がうまく動作しなかった原因に気付いたので、本文のスクリプトを修正しておきました。command登録時に引数をシングルクォーテーションで囲っておくと引数が文字列として渡されるようです。