cafegale(LeafCage備忘録)

LeafCage備忘録(はてなダイアリー)と統一しました。

些末なるVim scriptのTips

実際に使った、役に立ったもの

あるechoの表示で一時停止させてユーザに確認を促したい

echo の直後で call getchar() する

インプットメソッドを強制的にオフにしたい

'imdisable'で一時的にIMをオフにする。

let save_imd = &imd
set imdisable
let &imd = save_imd

まだ役に立つかどうか未知数

マルチバイト文字にマッチするパターン

>マルチバイト文字にマッチするようなパターン
ものすごーくざっくりやるとすると、
[^\x00-\x7f]
かなぁ
うまくいかないパターンもあるかも

http://lingr.com/room/vim/archives/2013/12/10#message-17781111

undobreak

undobreak1

haya14busa:
undojoin案件、その後のundobreak的なコマンド抜けてて困ったことあったから、vim-overのソースみてみたらちゃんとそこも対応してた。さすがだ

t9md:
undobreak とは。どういうケースで必要になるんですか。僕も undojoin は使ってるので知りたい。
Plugin 内で undojoin した後 u するよカーソルがあらぬ方向にいっちゃうの何とか出来るのか知りたい。

http://lingr.com/room/vim/archives/2013/12/10#message-17781824

undobreakとは

:undojoinはあるけど:undobreakはない。

しかし:undobreak相当のことは次のコマンドでできるようだ。 :execute 'normal!' "i\u\"
すなおに:undobreakよういしてください

http://lingr.com/room/vim/archives/2009/09/08#message-3450

haya14busa:
undobreakこれです。 > t9mdさん

まさに、プラグイン内でundojoinしてそのあと履歴を区切らないと、uしたときに前の部分まで戻ってカーソル動いちゃうと思います。

http://lingr.com/room/vim/archives/2013/12/10#message-17784905

undobreak2

thinca:
command! Undobreak let &undolevels = &undolevels

http://lingr.com/room/vim/archives/2013/12/10#message-17785046

haya14busa:
undobreak相当のこと、thincaさんがおっしゃってる let &undolevels = &undolevelsでもできるんですね
どっちがいいんだろう

thinca:
現在のモードに依存しないので undolevels いじった方がいいと思っている

http://lingr.com/room/vim/archives/2013/12/10#message-17786194

lastmess.vimで表示されるメッセージのハイライトをいろいろ定義できるようにした。

メッセージの開始と、メッセージの中身の色を定義できるようにした

g:lastmess_highlight_errstartg:lastmess_highlight_errcontentsを指定することで、
エラーの開始点と内容が色分けされてこのようにエラーメッセージが見やすくなります。
(デフォルトでエラーの中身は"PreProc"のハイライトを使うように変更されました。)

f:id:leafcage:20131205005439p:plain

(あっ比較のために更新前の画像もキャプっとけばよかった。このE716:とかE15:という行は今までならエラー開始点と同じく、"ErrorMsg"でハイライトされていたのですよ。それを"PreProc"にしたことで1つのエラーのメッセージがどこまで続いているのかが視覚的に判別しやすくなったわけです。)

ユーザが指定したパターンにマッチしたメッセージの色に指定したハイライトを使うようにした

g:lastmess_special_highlightを使います。
これは[{hilight-group-name}, {pattern}]というリストを収めたリスト(つまりリストが入れ子になったリスト)です。
次のように使います。

let g:lastmess_special_highlight = [['MoreMsg', '^sourced:']]

これで'^sourced:'にマッチするメッセージにMoreMsgのハイライトが利用されます。

蛇足、便利な設定

あと、次のように無視したいメッセージパターンを登録しておくと、ノイズがなくなって便利です。

let g:lastmess_ignore_pattern = 'スキャン中\|検索したので\|箇所変更しました;\|行 削除しました;\|行 追加しました\|\d\+L, \d\+C$\|行 --\d\+%--$\|--バッファに行がありません--$\|既に一番新しい変更です\|^\s*\d\+:\s\%(\~\|\u:\)/'

また、次のように、メッセージクリアコマンドを使えるようにしておくと捗ります。

command! MessageClear for n in range(200) | echom "" | endfor| ec 'Cleared Message'
nnoremap mc :<C-u>MessageClear<CR>

Vimにパッチが当てられるまでの間、Windowsでとりあえず外部grepを使えるようにする

mattn

jvgrepの問題、vimを直すしか方法ない
vimがCreateProcessWを使えば解決
たしかパッチは出してあってtodoに入ってたと思う

http://lingr.com/room/vim/archives/2013/12/05#message-17742024

とのことなので、それまでは我慢と工夫で乗り切るしかないのだ。

仕方ないので、Grepというコマンドを作った。ついでにターゲット無指定の時には現在バッファ周辺を検索対象にすることにして利便性を高めた。

function! s:grep_for_cmdprompt(cmd, argstr) "{{{
  let args = split(a:argstr, '\%(\\\@<!\s\)\+')
  let i = 0
  while match(args, '^-', i)!=-1
    let i+=1
  endwhile
  let dflbase = expand('%:p:h')
  let dflbase = dflbase==?expand('$HOME') ? expand('%') : dflbase.'/**/*'
  let opts = i==0 ? '' : join(args[:i-1])
  let pat = has('win32') ? iconv(escape(args[i], '#%'), 'utf-8', 'cp932') : escape(args[i], '#%')
  let target = i+1>=len(args) ? dflbase : join(args[(i+1):])
  let g:greped = a:cmd. ' '. opts. ' -8 '. pat. ' '. target
  silent exe g:greped
endfunction
"}}}
command! -nargs=+ -complete=file   Grep    call s:grep_for_cmdprompt('grep', '<args>')

しかし外部grepだと、% # といった特殊文字が展開されてしまうのでエスケープしないといけないのが辛いところ。
vimgrepだとエスケープの必要がない。差別である。
どうにか利用時にエスケープしなくても済むようにしようとしたけれど無駄だった。


関連エントリ:最新版のjvgrepをコンパイルするにはgo言語とMercurialが必要だった - LeafCage備忘録

最新版のjvgrepをコンパイルするにはgo言語とMercurialが必要だった

# go get github.com/mattn/jvgrep

というコマンドを実行するにはThe Go Programming Languageが必要だった。
しかも$GOROOT $GOPATHという意味不明な環境変数を設定しなければいけなかった。

さらに、それに使われているmahonia - Mahonia—a character-set conversion library for Go - Google Project Hostingを得るためには水銀の元素記号hgでおなじみ、もう一つのバージョン管理システムであるJapaneseMercurial - Mercurialが必要だった。

インストーラでインストールするのが嫌だったのでMercurial Cmd Portable 1.5.1 Development test 1 | PortableApps.com - Portable software for USB, portable and cloud drivesを適当なディレクトリに展開した上で、Mercurialにパスを通すことで対応した。

悲しいお知らせ

ここまで苦労して導入しても、Vimの'encoding'オプションを'utf-8'にしている場合、Windowsではなすすべもなく使えないらしい。

set grepprg=jvgrepにして:grepしたいのですが、日本語が通りません。

Vim側がutf-8で吐いた文字をコマンドプロンプトがcp932として呼んでしまうからですが、解消する方法を知りませんか?

http://lingr.com/room/vim/archives/2013/12/05#message-17739621

絶望

つまり現状ではコマンドプロンプトを使うのをやめるか、qfixgrepを使うしか解決策がないわけですね。
qfixgrepは余計なことを色々しているから好きにはなれないのですが。

http://lingr.com/room/vim/archives/2013/12/05#message-17740433

光明

qfixgrepの中身を見てみたが、つまり最悪、外部コマンドに渡すときにiconv()でエンコードを変換してやれば何とか出来るっぽい。

http://lingr.com/room/vim/archives/2013/12/05#message-17740591

おし。
exe 'grep '. iconv('ファイル', 'utf-8', 'cp932'). ' %'だと正常機能した。
つまり渡すときエンコードしてくれるラッパーコマンドを定義してそれを使えば当面は解決できる問題になった。

http://lingr.com/room/vim/archives/2013/12/05#message-17740802

コマンドラインで :b を実行するときにバッファリストを表示する

Vim - hjklマスターに薦める意外と便利な機能 - Qiita [キータ]
バッファを選択する際に、同時にリストを表示する

nnoremap B :ls<CR>:b 

という設定を見て閃いた。

cnoreabb <expr>b getcmdtype()==':' && getcmdline()=='b' ? 'ls<CR>:b' : 'b'

こうすればコマンドラインで:bを打ってから<Space>キーを打つと勝手に:lsが表示されるようになる。