vimの外部grepでagを使う

ackというperl製のgrepがいいという情報を聞いたのもつかの間(過去記事参照)、ackの3-5倍高速かつ、コマンド名が33%も短い(笑)agというgrepがいいという情報を聞いたのでvimの外部grepで使えるようにしてみた。

設定は前回と同じく自力でやる。
高機能で安定したもの(たぶん)を求めたい方は専用のプラギンが用意されていますのでそちらをどうぞ。

" grep設定
" ag -> ack -> grep の順に優先して使用
if executable('ag')
    set grepprg=ag\ --nogroup\ -iS
    set grepformat=%f:%l:%m
elseif executable('ack')
    set grepprg=ack\ --nogroup
    set grepformat=%f:%l:%m
else
    set grepprg=grep\ -Hnd\ skip\ -r
    set grepformat=%f:%l:%m,%f:%l%m,%f\ \ %l%m
endif

" 拡張子指定grep
command! -bang -nargs=+ -complete=file Grep call s:Grep(<bang>0, <f-args>)
function! s:Grep(bang, pattern, directory, ...)
    let grepcmd = []
    call add(grepcmd, 'grep' . (a:bang ? '!' : ''))
    if executable('ag')
        if a:0 && a:1 != ''
            call add(grepcmd, '-G "\.' . a:1 . '$"')
        else
            call add(grepcmd, '-a')
        endif
    elseif executable('ack')
        if a:0 && a:1 != ''
            call add(grepcmd, '--' . a:1)
        else
            call add(grepcmd, '--all')
        endif
    else
        if a:0 && a:1 != ''
            call add(grepcmd, '--include="*.' . a:1 . '"')
        endif
    endif
    call add(grepcmd, a:pattern)
    call add(grepcmd, a:directory)
    execute join(grepcmd, ' ')
endfunction

なんと驚きの3段構え!!
agコマンドのオプションは適当に設定したので使ってみてから調整しようと思います。
会社のサーバにもagをこっそり入れようか。

ターミナルのvimを手動コピペし易くする

ターミナルのvimで表示している内容をそのままコピペしたい時には普通マウスでチョイチョイっと選択すると思います。
ちょっとした文字列なら問題ありませんが、欲しい内容が複数行の場合だと行番号や余計なスペースまでクリップボードに入ってしまいます(もちろんそういう設定にしていなけば問題ありませんが)。

そんな時は:set nonumberや:set foldcolumn=0などを実行する必要があり、これが大変面倒くさいです。
更に用がすんだら設定を元に戻さないといけません。

このままでは発狂してしまうので、少しでも心の傷を柔げるための簡単なスクリプトを作りました。

nnoremap <silent><F8> :<C-u>call <SID>CopipeTerm()<CR>
function! s:CopipeTerm()
    if !exists('b:copipe_term_save')
        " 値が保存されていなければ保存後に各オプションをコピペ用に設定
        let b:copipe_term_save = {
        \     'number': &l:number,
        \     'relativenumber': &relativenumber,
        \     'foldcolumn': &foldcolumn,
        \     'wrap': &wrap,
        \     'list': &list,
        \     'showbreak': &showbreak
        \ }
        setlocal foldcolumn=0     " 折りたたみ情報表示幅
        setlocal nonumber         " 行番号
        setlocal norelativenumber " 相対行番号
        setlocal wrap             " 折り返し
        setlocal nolist           " 行末やタブ文字の可視化
        set showbreak=            " 折り返し行の先頭に表示されるマーク(こいつだけグローバル設定しかない)
    else
        " 保存されている場合は復元
        let &l:foldcolumn = b:copipe_term_save['foldcolumn']
        let &l:number = b:copipe_term_save['number']
        let &l:relativenumber = b:copipe_term_save['relativenumber']
        let &l:wrap = b:copipe_term_save['wrap']
        let &l:list = b:copipe_term_save['list']
        let &showbreak = b:copipe_term_save['showbreak']
        " 削除
        unlet b:copipe_term_save
    endif
endfunction

コピペ時に邪魔になりそうなオプションを思いつく限りならべてみました。
これでF8を押す度に表示がコピペ用の設定に切り替わったり、元に戻ったりします。
同じキーで2度おいしい動作なので、これでなんとか耐えられるでしょう。

vimのビルド時に+iconvでつまづいた話(初級編)

先に言うと原因はかなりしょうもない。

vimに限らずソースからのビルドに不慣れな自分。
普段はyumやらhomebrewやらで済ませてしまうゆとり世代が、意を決してvimのビルドを実行してみたもののすんげーつまづいてしまった。

mercurialからvimの最新版を落としてきてビルドを実行するところまでは何の問題も無くすんなり行けたので余裕余裕と思っていたのですが、ふと:versionを確認してみると+iconvが付いていない・・!!

f:id:saihoooooooo:20130627110149p:plain

おおおおお。。。
急いでlibiconvをインストールするが何度やっても

checking for iconv.h... (cached) no

と表示され+iconvが付かない。

lingrvim部屋で色々聞いてる内に解決方法が判明。
初回のビルド時にはlibiconvは入ってなかったのでその情報がキャッシュされていたというだけでした。チーン。
ていうか思いっきりcachedて書いてるっていう。

という訳でキャッシュの場所を教えてもらい削除。

rm src/auto/config.cache

おかげ様で今ではiconv()使いたい放題の毎日です。

cygwin上のvimからxamppのphpを実行

$ ln -s /cygdrive/c/xampp/php/php.exe /usr/local/bin/php

とした場合、zshから

$ php /cygdrive/c/Users/hoge/unko.php

を実行しても問題無いが、vim(quickrun)からphpを動かしたい場合に「Could not open input file: /cygdrive/c/Users/hoge/unko.php」と言われ失敗する。

cygwinunix)形式のパスがwindows版のphpで読めていない模様。
なのでcygpathでパスを変換してphpを実行するダミーのシェルスクリプトを用意する(超簡易版)。

$ rm /usr/loca/bin/php(既にシンボリックリンクが貼られてる場合)
$ vim /usr/local/bin/php
$ cat /usr/local/bin/php
#!/bin/sh
function args {
    while [ "$1" != "" ]
    do
        # オプション以外をcygpathする
        case $1 in
            -*)
                echo "$1"
                ;;
            *)
                echo `cygpath -m "$1"`
                ;;
        esac
        shift
    done
}
/cygdrive/c/xampp/php/php.exe `args $@`

cygpath便利。

hubotで部屋名を取得する

部屋名を指定して発言したいけど部屋名がわからない!
そんな時には以下のコマンドをhubotに投げましょう。

hubot fake event debug

hubot-skypeでいうとこういう出力。

fake event 'debug' triggered
{ user: 
   { id: '1369030403127',
     name: 'hogeuser',
     room: '#hogeuser/$0123456789abcdef',
     roles: [] } }

部屋名がわかったらあとはsendするだけです。

// curl -d "message=テスト" http://localhost:9999/hubot/say
robot.router.post "/#{robot.name}/say", (req, res) ->
  user = {room: '#hogeuser/$0123456789abcdef'}
  robot.send user, req.body.message

  res.writeHead 200, {'Content-Type': 'text/plain'}
  res.end 'OK'

以上。