(後半)少なくとも一つは知らないvimのトリック

Hillel Wayne    
フォーマルメソッド、ソフトウェア歴史家、『実践TLA+』の著者。
この記事は、著者の許可を得て配信しています。
https://hillelwayne.com/post/intermediate-vim/

関連記事:(前半)少なくとも一つは知らないvimのトリック

Exobrain Vim

これらは永続的なストレージを必要としたり、Vim セッションを変更したりする必要があるものです。仮定の話ですが、これらを入力することで本格的に使うことができますが、これらの中には本格的なユーザーの精神に反するような重大な変更もあります。

私はここでは一般的ではないものを入れているだけです。多くの人がHを^にマッピングしているように、私もそれについて話す必要はないと思います。また、vim-sensible や vim-surround についても言及する必要はないと思っています。より一般的ではないプラグインだけを含めました。

常に vimrc を微調整しているという人がいるのであれば、ぜひそのためのコマンドを追加してみてください。

command! Vimrc :vs $MYVIMRC

設定

私はすべての設定、マップ、機能を1つのvimrcファイルに入れています。多くのファイルに分割すると、探し出すのが難しくなるからです。

ほとんどの設定は Vim の「トリック」ではありません。最善の策は vim-sensible を参照することです: そこにあるほとんどすべての設定はvimrc に適しています。

set lazyredraw

マクロの途中で画面を再描画しないでください。その方が早く完了します。

set smartcase/ignorecase

両方をオンにすると、大文字を含まない検索は大文字小文字を区別しませんが、大文字を含む検索は大文字小文字を区別します。

set undofile

Vimを閉じても開きなおしても、永続的なundo化が可能です。undotree プラグインと組み合わせると非常に便利です。

set foldcolumn={n}

サイドバーが折畳表示になります。nが高いほど、折り目が視覚的に表示され、少ないほど数字で表示されます。

set suffixesadd={str}

gf は通常 "カーソルの下にあるファイルを goto する" のですが、文字列の中にファイルの識別子が付いている必要があります。suffixesadd もまた、その識別子が付いているファイルをチェックします。suffixesadd=.md としている場合、文字列 "foo" の上で gf を押すと、foo と foo.md のファイルを探します。

set inccommand=nosplit

これはNeovimのみです。 inccommandは、exコマンドがどのような変更を加えるべきかをリアルタイムで表示します。現在は s のみに対応していますが、それだけでも信じられないくらい便利です。s/regex と入力すると、正規表現 にマッチするものをハイライトします。次に /change と入力すると、すべてのマッチしたものを change で置き換えたものを表示します。これは、バックリファレンスやグループを含むすべての正規表現プロパティで動作します。

set statusline (:h statusline)

各ウィンドウの下部にあるバーに表示されるものを指定します。ここでの書式設定は他の設定に比べて非常に複雑で細かいので、説明にはとても時間がかかります。簡単なトリックとしては、いくつかできることがあります。まず、Vim のデフォルトのステータス行は

:set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P

ここで最も簡単に置き換えられるのは、ファイルを通過した割合を示す %P です。ステータス行のフォーマットは、%{exp()}をexp()の結果を書いているように読み取ります。ですから、マークダウン・ファイルの場合は、次のようなことができます。

:set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %{wordcount()[\"words\"]}

パーセンテージをドキュメントの単語数カウントに置き換えます。

タブラインを設定することもできます。タブを使わない場合は、これをハックして「グローバルステータス行」にすることができます。以下のようにすることができます。

set tabline=%{strftime('%c')}

常に日付を上に表示します。

マップ

マップはたくさんあります。

Vim の主要な不動産の多くは cruft で占められています。s を使うと、cl だけを実行するよりもキーストロークを 1 回分少なくなります。新しい変更としてundoを行う点を除けば、U は u と同じですが、機能的には意味がありません。Q は gQ と同じで、落とし穴になっています。ZはZZとZQにしか使われていません。Vim のマニュアルでは _ や , のようなものをカスタムマップにリバインドすることを推奨していますが、つまりは「おそらくそれらを絶対使うことはない」ということです。私は数回のキーストロークを保存するよりも、キーボードに全く新しいタスクを追加したいと思っています。私が持っているマップのいくつかをお見せします。

nnoremap Q @@

EXモードで間違うのではなく、最後に使用したマクロを繰り返します。

nnoremap s "_d

s (ss と S に対応するマップと一緒に) を d のように動作させるのですが、カットされたテキストはレジスタに保存されません。名前のないレジスタのデータを破損せずに何かを削除したいときに役立ちます。

nnoremap <c-j> <c-w>j

下のウィンドウに移動します。h,k,lに対応するマッピングです。ウィンドウがより簡単に使えるようになります。

nnoremap <leader>e :exe getline(line('.'))<cr>

現在の行をコマンドのように実行する。実験をするときは q: よりも便利なことが多いです。

特別な実引数 (:h map-arguments)

map <buffer> lhs rhs を書くと、そのバッファに対してのみマッピングが行われるようになります。これはオートコマンドと組み合わせて、短期的なショートカットとして、あるいは関数を使ってマップを設定する場合に便利です。バッファマップはグローバルマップよりも優先されます。つまり、一般的なコマンドをより具体的に有用なもので上書きすることができるということです。

すべての使用マップ <expr> {lhs} において expr}は{expr}を評価し、その戻り値をエンドマッピングとして使用します。簡単なユースケースとしては 条件付きマップがあります。以下をご覧ください。

nnoremap <expr> k (v:count == 0 ? 'gk' : 'k')
nnoremap <expr> j (v:count == 0 ? 'gj' : 'j')

カウントがない限り、jとkを折り返し線で移動させますが、その場合は正常に動作します。これで、10jなどを壊すことなく、長い段落の散文をナビゲートすることができるようになりました。

<silent> は、マッピングに ex コマンドを起動させている場合には適しています。

inoremaps

inoremapで、挿入モードでマップを作成することができます。マップは挿入モードで始まるので、inoremap ;aaaaは';a'の代わりに'aaa'と入力します。通常のモードで何かをしたい場合は、<c-O>を使います。

inoremap ;1 <c-o>ma

とすると、;1 は入力中のポイントに 'a マークを設定します。

私はimapsのリーダーキーとしてセミコロンをよく使います。というのも、スペースや改行以外の何かで ; の後に続くことがないからです。

autocmd

オートコマンドはコンフィギュレーションには最適です。通常は、次のフォームでコンフィギュアします。

augroup {name}
  autocmd! " Prevents duplicate autocommands
  au {events} {file regex} {command}
augroup END

そして、{file regex}にマッチするファイル内で{event}が発生すると、{command}が起動します。イベントは :h イベントの下に表示されます。例えば、

augroup every
  autocmd!
  au InsertEnter * set norelativenumber
  au InsertLeave * set relativenumber
augroup END

そうするとVimは挿入モードの時だけrelativenumberをOFFにします。

au {event} <buffer> {ex}を書くと、自分が使用中のバッファにのみオートコマンドを適用します。特定のファイルに短期的なイベントハンドラを追加するためにこれを使っています。

BufNewFile,BufRead

BufNewFile は新規ファイルを作成した時に起動し、BufRead はバッファを初めて開いた時に起動します。これらは、ファイルタイプ固有の設定やマッピングを追加するためによく使われます。私が持っているものは次のものです。

augroup md
  autocmd!
  au BufNewFile,BufRead *.md syntax keyword todo TODO
  au BufNewFile,BufRead *.md inoremap <buffer> ;` ```<cr><cr>```<Up><Up>
augroup END

これは、マークダウンファイルに対してのみですが、文字列TODOがハイライトされ、挿入モードで ;` と入力するとコードフェンスが追加されることを意味します。

オートコマンドを使うと、より複雑なことができるようになります。例えば、BufWriteCmdにauを追加すると、標準の保存を上書きし、カスタムロジックを入れることができます。これは「Vim のトリック」の領域を超えて、「黒魔術」の領域へと移行しているということです。

プラグイン

vim-surroundやNERDtreeなどの人気プラグインは知らない人がいないほど有名です。私が非常に便利だと思う、あまり知られていないプラグインをいくつかリストアップしたものです。

Undotree

ほとんどのテキストエディタにはリニアundo機能を持っています。A という変更を行った後、元に戻して(undo)から B の変更を行うと、A は永遠に失われます。一方、Vim は、undo tree全体を保存します。 u は現在のブランチの前の状態のみ元に戻し(undo)ます。g- は、以前のコードの時系列バージョンに移動します。undo リーフのリストは :undolist で見ることができます。

しかし、この形式は読みにくいので、実際のtreeを見た方がいいでしょう。Undotreeは、簡単なナビゲーションのために、Undotreeの美しいアスキー表現をポップアップで開くことができます。

vim.swap

引数を入れ替えるコマンドを与えてくれるので、数回のキーストロークで(a, f(b, c))を(f(b, c), a)に置き換えることができます。私は定期的にそのような編集をしなければならないので、これがあると本当に便利です。

Neoterm

neo/vim の組み込み端末の周りに高レベルの API を配置します。例えば :T {text} は {text} をターミナルに送信します。素敵な REPL を作ることができます。

" TODO {{{

関数の書き方やシンタックスシステムなどに関しては、内容が濃すぎたり、説明が長くなったりするので、今回の記事では触れていません。もちろん私がまだ知らないこともたくさんあります。ここでは、次に学ぶ予定のものをいくつか紹介します。

プレビュー、Quickfix、リスト ウィンドウ

これらを使うツールはたまに使うけれど、自分ではどうやって操作すればいいのか分かっていません。TLA+プラグインにquickfixエラーを追加したいとも思っています。また、プレビューウィンドウに補助情報やコールバックコマンドを入れるというアイデアも気に入っています。IDEで再現するのは難しいという可能性がいくつかあるということが分かりました。

Neovim API

Neovimには、外部プログラムとVimを連携させるためのAPIが充実しています。つまり、PythonスクリプトからNeovimインスタンスにコマンドを送ったり、サーバーを通してコントロールしたりすることができます。これを使ったカッコいいコンセプトのデモをいくつか見たことがあります。このデモでは、ブラウザの内容をベースにしてオートコンプリートします。これはとても楽しそうですよね!

テキストオブジェクト

まだ自分で設定したことがありません。

ともかく、これでちょっと曖昧なVimの機能についての説明を終わります。今回の記事で、みなさんも一つでも便利な機能を新しく身に付けることができたのであれば嬉しいです。


コメントを読む

新着ピック  






















新着ニュース

米ファンドのSilver Lakeがインド大手通信Reliance Jio Platformsに約660億円追加出資 | TechCrunch Japan

完成しているからこそあえて変えない新ThinkPad X1 Carbon、第10世代搭載の順当進化だが発熱は高め | TechCrunch Japan

React + API Gateway + Lambda + DynamoDB で動画の再生回数を取得する仕組みを作ってみた | Developers.IO

React + API Gateway + Lambd...

DevelopersIO / 3時間前


Reddit創業者アレクシス・オハニアン氏が役員を退任、後任に黒人の指名を要望 | TechCrunch Japan

「iPhone SE(第2世代)」を分解して分かった“4年分の進化” iPhone 8と共通の部品も

[Amazon Connect] 留守番電話を設置した場合に必要なKinesis Video StreamsとS3のデータサイズについて | Developers.IO

BitriseでGitHub OrganizationのRepositoryを連携してみた | Developers.IO

BitriseでGitHub Organization...

DevelopersIO / 16時間前


Cloudflare のスマホアプリを利用した2要素認証(MFA)を試してみた | Developers.IO

モトローラは2020年も低価格スマホ中心の戦略をとる | TechCrunch Japan

Aukeyの非常にコンパクトなGaN採用の100W充電器、サイズはアップル純正の半分 | TechCrunch Japan

シリコンバレーは黒人所有企業を支援して構造的人種差別と戦うべきだ | TechCrunch Japan

プレゼン資料作りにMindMapツールを利用してみた | Developers.IO

SlackとAWSが提携してTeams+Azureコンビを焦らせる | TechCrunch Japan

[備忘録] boto3.dynamodb.conditons.Keyとboto3.dynamodb.conditions.Attrについて | Developers.IO

[備忘録] boto3.dynamodb.condit...

DevelopersIO / 21時間前


ジョージ・フロイド事件と新型コロナでTwitterのインストール記録が更新 | TechCrunch Japan

Apple WatchのECG(心電図)機能、日本でも使えるように?

食品の生産者や卸をD2C化するPortobelが大繁盛、利用者が3倍に | TechCrunch Japan

Instacartがショッパーの不満を受けてチップに関するポリシーを変更 | TechCrunch Japan

「1〜3万円で買えるスチームオーブンレンジ」おすすめ3選 水蒸気の力で脱油! 減塩!【2020年最新版】

ロックダウン解除後も米国のコネクテッドTV視聴は新型コロナ前より高水準 | TechCrunch Japan

もっと見る
記事をPICKする
会員登録
Register
記事をPICKする

会員登録すると、もっと便利に利用できます。