悲しいお知らせですが、前エントリは没となりました。
根本的な勘違い
そもそもなぜ巨大なだけのこんなスクリプトが出来上がってしまったのかを考える必要があります。
プロジェクトリーダーの理解
- netrw内のブックマークファイル(
.netrwbook
)はただのvimスクリプトなので、先にロードしておけば、netrwの変数g:netrw_bookmarklist
を使えるかもしれない - ノーマルモードの
gb
が空いていた - ディレクトリ関係を弄るのであればvim導入初期から使っていた
<Leader>v
から始まる設定ファイルへの移動マップもうまく組み込みたい - なんか
:split some/directory/
と:Hexplore some/directory/
の挙動が違う気がする (すごく気になる)
というわけで、この辺の欲を一気にまとめるスクリプトを作ろうという発想に至ったわけです。
得られたサポート
そもそもじゃあこの差はなんなんだ?って話なんだけど…何の成果も得られませんでした。ただ :Hexplore
を使うと既にあるnetrwのバッファ内でディレクトリ移動されて、 :Rexplore
を使うまでウィンドウとして出てこない事があるので「これは何なんだろう」というところまでしかわかりませんでした。
プログラマのコード
…はもう前のエントリで見てもらえばいいとして、どうにもやるべきことに対して労力が見合っていません。この状態から更に捻じ伏せようという気になれなくなったところで根本的に方法が間違っている事に気が付きました。
顧客が本当に必要だったもの
そもそもnetrwはどう使われたいのでしょうか?確かに :Explorer
は現在のバッファの編集状態を見ていい感じにウィンドウを開くダンディなヤツですが、「もっとカジュアルに :e some/directory/
で使ってもいいよ」と言ってくれているんです。じゃあわざわざ長いコマンドを使わずに :e
, :sp
, :vs
でいいじゃないですか。"Small is beautiful" を忘れちゃダメっすよ…
実装された運用
if!exists('g:netrw_bookmarklist')try
execute printf("source %S/%S",g:netrw_home,'.netrwbook')catch/E121/
execute printf("source %S/%S", split(&runtimepath,',')[0],'.netrwbook')endtryendiflets:cmdDict={ \'e':'edit', \'e!':'edit!', \'s':'split', \'v':'vsplit', \'t':'tabe', \'t!':'tabe' \}lets:cmdDict['s!']=&splitbelow ? 'abo split':'bel split'lets:cmdDict['v!']=&splitright ? 'lefta vsplit':'rightb split'function! dirz#open(...) abort
let path =a:1let isBang = exists('a:2') ? a:2:''let drx = exists('a:3') ? tolower(a:3[0]):''if drx ==''if getbufinfo(bufname(''))[0]['changed']let drx = isBang =='!' ? 'v':'s'elselet drx ='e'endiflet isBang =''endif
execute printf("%s %S",s:cmdDict[drx.isBang], path)endfunctionfunction! dirz#netrwBook(...) abort
let index = exists('a:1') ? a:1:0let isBang = exists('a:2') ? a:2:''let drx = exists('a:3') ? a:3:''if index ==0let line =1forbming:netrw_bookmarklist
echo printf('%3d: %s', line,bm)let line +=1endforcall inputsave()let selected = input('番号と<Enter>を入力して下さい (空でキャンセル): ')call inputrestore()elselet selected = index
endifcall dirz#open(g:netrw_bookmarklist[abs(selected)-1], isBang, drx)endfunction
noremap <Plug>(dirz_netrwBookS):<C-u>call dirz#netrwBook(v:count)<CR>
noremap <Plug>(dirz_netrwBookV):<C-u>call dirz#netrwBook(v:count,'!')<CR>
noremap <Plug>(dirz_netrwBookT):<C-u>call dirz#netrwBook(v:count,'','t')<CR>
command!-bang Bookz call dirz#netrwBook('','<bang>','')
command!-bang SBookz call dirz#netrwBook('','<bang>','s')
command!-bang VBookz call dirz#netrwBook('','<bang>','v')
command!-bang TBookz call dirz#netrwBook('','<bang>','t')
…どうしてこんな事になってしまったんだ。
さておき
やっていることは基本的に一緒で、netrwのブックマークをノーマルモードからも使うためのものです。dirz#netrwBook()
関数の方で g:netrw_bookmarklist
からパスを読み込んで、開き方の指定は汎用的に使える dirz#open()
関数に任せています。むしろ本体は dirz#open()
に見えてきます。
dirz#open()
関数
:Explorer
のバッファの編集状況をチェックしていい具合にウィンドウ分割するダンディな部分はぜひ実装したいということで残しました。
モード
dirz#oepn()
の第三引数のモードは大体こんな感じです。
mode | 名称 | bangなし挙動 | bangあり挙動 |
---|---|---|---|
(なし) | ワイズモード | バッファが保存されていなければ :split | バッファが保存されていなければ :vsplit |
s | 垂直分割モード | :split | :split と逆方向 (&splitbelowを参照) |
v | 水平分割モード | :vsplit | :vsplit と逆方向 (&splitrightを参照) |
t | タブモード | :tabe | :tabe |
e | 通常モード | :edit | :edit! |
アナリストのデザイン
とりあえず汎用に使える関数にしてしまったので、netrwに入れるには適してない1ブックマークを別なスクリプトから定義して使ってもいいかなと思ってたんですけど…けど、なんですよ。このスクリプト作成前のvimのコンフィグへのリマップ「群」が「選んで」「開く」という形になっていたのは良くないんじゃないのか?という自問自答が始まってしまいました。一つの動作で一つづつ操作を定義すれば、マトリクスを書くためにすべての状態を書く必要はないわけで…というわけで現在手近にアクセスしたいファイルのパスはコマンドモードの短縮入力にしてみました。とはいえ打鍵数は多いので頑張り過ぎかなとも思っているので…弱ったなまたスクリプトが増えるぞ…?
netrwのブックマークは追加するとリストの最初の要素に入るのでカウントがズレる。 ↩