ハイパーマッスルエンジニア

Vim、ShellScriptについてよく書く

Vimでカーソル位置下の単語をGoogle検索する

プログラムを書いていると「お、なんだこの関数?」と思いググることってよくあると思う。
そんな時一々単語をコピーし、ブラウザを開き、検索バーに打ち込んで検索している自分に腹が立った。なぜこんな無駄な動きをしているんだ。
プログラムに限らずREADMEなどドキュメントを読んでいるときも多々遭遇する。

息を吸うようにググりたい

私はエディタがVimなので本来ならターミナルから動くことは許されない。
唯一「ググる」という行為は許しているが、それでもブラウザに行くまでの動作は限りなく短いほうがよい。

今までのググるまでの道のりは以下の通り。

  1. 調べたい単語が見つかる
  2. 単語をコピーする
  3. ブラウザに移動する
  4. 検索バーにペーストする

長過ぎる...

理想は「調べたい単語が出てきた時点で既に検索が終了している」状態が望ましい。

関数作った

ということで理想に限りなく近い関数を作った。もちろんVimScriptだ。

f:id:rasukarusan:20190309011318g:plain
息を吸うように検索する

" カーソル下の単語をGoogleで検索する
function! s:search_by_google() 
    let line = line(".")
    let col  = col(".")
    let searchWord = expand("<cword>")
    if searchWord  != ''
        execute 'read !open https://www.google.co.jp/search\?q\=' . searchWord
        execute 'call cursor(' . line . ',' . col . ')'
    endif
endfunction
command! SearchByGoogle call s:search_by_google()
nnoremap <silent> <Space>g :SearchByGoogle<CR>

調べたい単語の上で<SPACE> gをタイプすれば検索された状態のブラウザを開く。 割と理想に近いと思う。

解説

特に難しいこともしていないが一応。
上の関数をシンプルに書くと以下。

" カーソル下の単語をGoogleで検索する
function! Search_by_google() 
    let searchWord = expand("<cword>")
    execute 'read !open https://www.google.co.jp/search\?q\=' . searchWord
endfunction

他の部分はエラー判定やキーバインドの設定なので無視して構わない。
調べたい単語の上で:call Search_by_google()と打てばググることができる。

やっていることは

  1. カーソル下の単語を取得
  2. Vimを開いたままシェルコマンドを実行

のみである。

1. カーソル下の単語を取得

これは

expand("<cword>>")

でゲットできる。他にもファイルパスとか取得できたりするので:help expandで調べてみると楽しいと思う。

2. Vimを開いたままシェルコマンドを実行

execute 'read !open https://www.google.co.jp/search\?q\=' . searchWord

肝はread。これを付けないで!open https://...と実行すると、

press enter or type command to continue

# もしくは

続けるにはENTERを押すかコマンドを入力してください

と出力され、VimからShellに操作を奪われてしまう。

これを回避するためにreadを使う。

readって何?

詳しくは:help readで調べてくれればいいが、ざっくりいえばコマンドの出力をVimにそのまま貼り付けるコマンド。

例えば

:read !ls

" もしくは
:r !ls

と実行すると、lsの結果がVimに出力される。

もしくはreadを使わなくても、Shift+V→:!lsのようにVisualモードに切り替えてから実行しても同じ結果が得られる。
shellコマンドのopenは出力を返すものではないので、Vim上に出力されるものがない=Shellに操作を奪われずVim上で実行したように見える。

ただ、readでコマンドを実行するとカーソル位置が行の最初に移動してしまうため、

let line = line(".")
let col  = col(".")
execute 'call cursor(' . line . ',' . col . ')'

でカーソル位置を実行したときの位置まで戻している。

終わり

:helpで調べてくれればいいが」と何回も言っているが、本当に:helpは有能なので騙されたと思って実行してみてほしい。きっと楽しいから。

でもVimで欲しい情報を得たい時、phpとかをググるより難しいな。欲しい情報が中々出てこない。
今回だったらshellに操作を奪われないためにどうするかに結構悩み、「"press enter or type command to continue" vim」でググっていたがわからなかったので、とりあえずvim.jpを読んでみた。偶然readを見つけることができたからいいが、もうちょっとググり力を上げたい。

まあでも道中で知らないVimのコマンド知ることできたし、こういう遠回りは積極的にしていきたい。