『実践Vim』学習メモ

Todo

エスケープ不要なので消す。

RTFM

  • Vimのデフォルト設定とは、組み込みプラグインを有効化し、vi互換モードを無効化するもの。essential.vim

Ch01 Vimのやり方

TIP01 .コマンド

  • 直前の変更とは
  • >G
  • マイクロマクロとしての.

TIP02 DRY

  • $a → A
  • ノーマルモードから挿入モードに切り替わるための複合コマンドがいくつかある

TIP03 一歩下がって、3歩進む

  • ; : カーソルを次の変更対象まで移動 ← , : 1つ戻る

TIP04 戻る

  • リバースコマンド一覧

TIP05 手作業での検索と置換

  • * : カーソル位置にある単語を検索
  • /{単語} : 単語を検索
  • 全置換なら「:%s/target/replacement/g」

TIP06 ドットの公式

  • 「カーソル移動用のキー入力1つ + 何かを実行するキー入力1つ」を変更の単位とする

Part1 mode

Ch02 normal mode

ノーマルモードは、オペレータコマンドとモーションを組み合わせることで強力になる

TIP08 undo

  • undoできる単位でESCする。挿入モードでの行の挿入も\ではなく\oでやる
  • 挿入モードでカーソルを使うと変更がリセット

TIP09 変更を繰り返し可能なものにする

  • Vim Golf
  • daw : delete a word

TIP10 回数指定で簡単な計算

  • \<C-a>と\<C-x>は数値の加減算 → 10\<C-a>でプラス10
  • 0が前置されている数字は8進数として解釈 → .vimrcに set nrformats=とすることで10進数として解釈してくれる

TIP11 繰り返しで済むなら回数を指定しない

  • 回数が重要なときのみ回数を使う。e.g. a couple of

TIP12 統合して統治

  • オペレータ + モーション = アクション
  • オペレータコマンド一覧
  • 組み合わせでできることが増える
  • オペレータコマンドを連続 → 現在の行に適用
  • カスタムオペレータ
  • カスタムモーション
  • オペレータ待機モード

Ch03 insert mode

TIP13 挿入モードでの修正

  • \<C-w> : 直前の1単語を削除
  • \<C-u> : 行頭まで削除

TIP14 ノーマルモードへの復帰

  • \<C-o> : 挿入ノーマルモードに切り替え
  • zz : 画面を再描画してカーソル行を中央に置く

TIP15 挿入モードのままレジスタから貼り付け

  • \<C-r>0 : 挿入モードで貼り付け。0は{register}

TIP16 簡単な計算をその場で実行

  • \<C-r>= : Expressionレジスタを呼び出す。VSCodeVimでは対応していない?

TIP17 文字コード特殊文字を入力

TIP18 ダイグラフによる特殊文字の挿入

TIP19 置換モードで既存のテキストを上書き

  • R : 置換モードに入る。gRで仮想置換モード。gRが良い
  • gR{char} : 1文字だけ置換してノーマルモード継続

Ch04 visual mode

TIP20 visual modeとは

  • ノーマルモードのオペレータコマンドとは制御が逆(選択範囲を指定してからオペレート)になる
  • 選択モードというものがあるがほとんど使わない

TIP21 visualな選択範囲の定義

  • 3種類のvisual mode
    • 文字指向 : v
    • 行指向 : V
    • ブロック指向 : \<C-v>
  • 直前のvisualな範囲選択を再度選択
  • 各コマンドはトグル(オンオフを切り替えるもの)
  • oで始点と終点を入れ替える

TIP22 行指向のvisual modeの繰り返し

  • set shiftwidth = 4 softtabstop = 4 expandtab
  • >でインデント

TIP23 オペレータコマンドを優先

  • vit : visually select inside the tag
  • gU{motion}

TIP24-26 ブロック指向

  • r{replace} : {replace}に置換
  • yyp : コピーして貼り付け
  • i,aキーの役割

Ch05 commandline mode

  • ed,ex,vi,vimの歴史

TIP27-

  • \でcommandline modeを抜けられる
  • commandline modeで実行するコマンドをExコマンドと呼ぶ
  • Ctrlを押すことでコマンドを実行できる : w,u,v,k,r
  • 一度に多くの行に作用できるのがExコマンド
  • :$で最終行に移動。数字だけだとアドレス指定できる
  • :2,5も可能
  • :.,$ : 現在行から末尾
  • % : ファイル全体 %sの%はこれ
  • visual modeでの範囲選択も可能
  • パターンでの行範囲指定も可能、加減も可能
  • copy,co,t(copy To)
  • move,m
  • @:で繰り返し
  • normal .などでノーマルコマンドが可能 → ノーマルコマンドの高い記述性とExコマンドの長射程の組み合わせ
  • \<C-d> で候補を表示。Tabで補完
  • wildmodeオプションで自動補完の動作の変更ができる
  • \<C-r>\<C-w>でカーソル位置の単語をコマンドラインにコピーできる
  • *でカーソル位置の単語を全て検索
  • set history=200 で履歴を多く保持する
  • :,/は履歴をたどれる
  • cnoremap <C-p> <Up> cnoremap <C-n> <Down>
  • q:でコマンドラインウィンドウを開ける
  • \<C-f>でコマンドラインモードからコマンドラインウィンドウに切り替え
  • !で外部プログラムを実行
  • % : コマンドラインモードでは編集中のファイル名を表す
  • :shellでインタラクティブなシェルセッションを始める exitで終わる → \<C-z>とfgの方が早い
  • :read でstdoutをバッファに送れる。:writeはstdinにバッファを使う
  • 外部コマンドでバッファの内容のフィルタリングもできる → :2,$!sort -t',' -k2
  • 範囲指定は!{motion}でも可能

Part2 file

Ch06 複数ファイルの管理

TIP36-

  • ファイルのインメモリ表現 : バッファ
  • % : カレントバッファ。#は代替ファイル。\<C-^>で切り替え
  • bn,bp,bfirst,blast,buffer {bufname}
  • nnoremap <silent> [b :bprevious<CR> nnoremap <silent> ]b :bnext<CR> nnoremap <silent> [B :bfirst<CR> nnoremap <silent> ]B :blast<CR>
  • bdelete,bd
  • args : 元はエディタ起動時の引数リストだが、変更可能
  • globでのファイル指定。*とディレクトリも含む
  • バッククォート展開でも引数リストを設定できる
  • next,prevで引数リストにあるファイルを移動
  • ls → a : active, h : hidden
  • edit!でディスクから読み直し
  • qall!,wallも可能
  • hiddenを有効にしてargdo,bufdo
  • (v)sp(lit)で分割した新しいウィンドウに表示
  • \<C-w>とw,h,j,k,lでウィンドウ切り替え
  • close : アクティブなウィンドウを閉じる。only : 非アクティブのウィンドウをすべて閉じる
  • :h window-resizeでサイズ変更と位置変更について見ることができる
  • タブページ : ウィンドウのコレクションを保持するコンテナ
  • lcd {path}で作業ディレクトリを現在のウィンドウごとにローカルに設定する。local cdということ
  • tabedit, \<C-w>T,close,tabclose,tabonly
  • {N}gt,tabmove [N]

Ch07 ファイルのオープンとディスクへの保存

  • pwd,edit,edit %:h\
  • cnoremap \ %% getcmdtype() == ':' ? expand('%: h').'/' : '%%'
  • set path+=app/** → find
  • netrw : Vimのネイティブなエクスプローラ。edit {dir}で開ける。edit %:hでカレントディレクトリを開く
  • Explorer,Eはアクティブなバッファのディレクトリでファイルエクスプローラを開く
  • ファイル/ディレクトリを扱うモードがそれぞれあることで、Vimの分割ウィンドウIFと連動する
  • netrwでディレクトリ操作が可能
  • \<C-g> : 現在のファイルの名前と状態をエコー
  • 新規ファイル作成時は、外部コマンド!mkdirを呼び出し

Part3 speedup

Ch08 モーションによるファイル内の移動

  • 論理行と表示行を区別する
  • j,gj
  • w : 次の単語の先頭に前進。b : 現在もしくは前の単語の先頭に後退
  • e : 現在もしくは次の単語の末尾に前進。ge : 前の単語の末尾に後退 → eaなどとして使うことが多い
  • word : 英文字・数字・アンダースコアが連続したもの、もしくはその他の非空白文字が連続したもの
  • WORD : 非空白文字が連続したもの
  • f{char},;
  • t,TはTill。dやcと組み合わせる
  • 出現率の低い文字を移動先とする
  • 検索コマンド/を使って移動する
  • d/{phrase}\で排他的なモーションとして検索コマンドを使える
  • i},a",i>,it,at,a] : テキストオブジェクト
  • i : inside, a : around
  • d,c,y{motion}でテキストオブジェクトを使える
  • 飛び蹴りとシザースキックの絵面白い
  • i,aとw,W,s,p
  • m{a-zA-Z}でカーソル位置に指定した文字でマーク。',{mark}で移動 → mmとm
  • 'と',.,^,[,],<,>で自動マークに移動
  • %で対になるカッコにジャンプ
  • set nocompatible filetype plugin on runtime macros/matchit.vim
  • surround.vim

Ch09 ジャンプによるファイル間の移動

  • :jumps
  • \<C-o>,\<C-i>
  • \<C-i>と\は同一
  • u\<C-r>でカーソルを移動
  • :changes
  • g;とg,
  • gi
  • gf : go to file
  • :set suffixesadd+=.rb
  • path
  • m{letter}のletterが大文字だとグローバルマークになる

Part4 register

Ch10 copy & paste

  • レジスタの扱い
  • xpで文字を入れ替え
  • "_d{motion}でコピーしないで削除
  • "{register}でレジスタを指定。Exコマンドでは引数に指定できる
  • "" : 無名レジスタ
  • "0 ヤンクレジスタ
  • :reg
  • 大文字でアドレスを指定してレジスタに追記
  • "+ : system clipboard
  • "* : primary, マウスの中ボタン。WindowsMacでは+と同じ
  • "= : Expression
  • その他のレジスタ : %,#,.,:,/
  • e : endのモーション
  • レジスタでビジュアルな選択範囲の置換ができる。置き換えた文字はレジスタに移る
  • gPで貼り付けられた行の末尾にカーソルを移す
  • set pastetoggle=\

Ch11 macro

  • q{register}で始め、qで終わる
  • :reg {register}で調べられる
  • @{register}で実行。@@は直前に実行したマクロ
  • 繰り返し可能なコマンドのみマクロに記録する
  • w,b,e,geを使う。0eなど。検索とテキストオブジェクトを使う
  • 10@aのように使える。できる限りやった後は勝手に止まってくれる
  • s : カーソル位置の文字を削除して挿入モード
  • r{char}でcharに置き換え
  • ~ : カーソル位置の文字の大小をトグル
  • ビジュアル選択し、normal @aとすることで並列にマクロを実行できる
  • q{REGISTER}でマクロに追記できる
  • :argdo normal @aで各ファイルにマクロを実行。マクロの記録後は:edit!
  • Expressionレジスタによる変数の使用
  • :put a で確実に下の行に貼り付けられる
  • "aでレジスタを指定して、y$など文字単位でヤンクする
  • substituteなどでもレジスタに記録したマクロを編集できる
  • let @a=substitute(@a, '\~', 'vU', 'g')

Part5 Pattern

Ch12 パターンとリテラルのマッチ

  • smartcaseで大文字小文字の区別を制御
  • \v でvery magic検索
  • \Vでno magic
  • (),\1の組み合わせて部分マッチのキャプチャを使える
  • <> : 単語境界デリミタ
  • %()でキャプチャしない
  • \zs,\zeでマッチ境界を指定する
  • escape({string},{char})を\<C-r>=で呼び出す
  • 検索フィールドの終端文字があることで、フラグを使える

Ch13 検索

  • n,N,/\,?\で検索を繰り返せる
  • :nohlsearch
  • nnoremap \ \<C-l> :\<C-u>nohlsearch\\<C-l>
  • \<C-r>\<C-w>で検索候補を自動補完
  • incsearch
  • :%s///gnで、マッチ件数を表示
  • //eでマッチの末尾にカーソル
  • Kana Natsunoのtextbj-lastpatプラグインでマッチ全体に対してドットで処理する
  • 検索履歴を繰り返して複雑なパターンを作る。q/
  • 直前の検索フィールドを流用できる
  • "+pでautoindentの影響を受けずに貼り付け。\でpasteオプションのトグル
  • ``` " ビジュアルモードで選択範囲を検索 xnoremap * :<C-u>call VSetSearch()/<C-R>=@/ xnoremap # :<C-u>call VSetSearch()?<C-R>=@/

    function! s:VSetSearch() let temp = @s norm! gv"sy let @/ = '\V' . substitute(escape(@s, '/\'), '\n', '\n', 'g') let @s = temp endfunction ```

Ch14 置換

  • [range]s[ubstitute]/{pattern}/{string}/[flags]
  • flags
    • g : globally(現在行について)
    • c : confirm
    • n : number
    • e : not disp error
    • & : 直前と同じフラグ
  • 置換文字列での特殊文字
    • \r : \
    • \t : \
    • \\ : \
  • cフラグへの答え方
  • 置換フィールドに\=@{register}で、参照渡し(特殊文字の影響を受けない)
  • :let @/='{string}' :let @a='{string}' :%s//\=@a/g
  • :&& : 新しい範囲に対して置換コマンドを繰り返す
  • nnoremap & :&&<CR> xnoremap & :&&<CR>
  • csvフィールドを入れ替える例
  • submatch(0)で現在のマッチを取得
  • 2つ以上の単語の入れ替え : key:valueペアを設定する
  • Abolishによる置換
  • 検索 + vimgrepと\<C-r>/
  • command! -nargs=0 -bar Qargs execute 'args' QuickfixFilenames() function! QuickfixFilenames() let buffer_numbers = {} for quickfix_item in getqflist() let buffer_numbers[quickfix_item['bufnr']] = bufname(quickfix_item['bufnr']) endfor return join(map(values(buffer_numbers), 'fnameescape(v:val)')) endfunction
  • vimでの|はシェルの;と同じ

Ch15 Global Command

  • :glabalはドットやマクロに並んで繰り返しを効率化する
  • :[range] global[!] /{pattern}/ [cmd]
  • :vglobal vはinvertのv。:global!と同じ
  • grep : :g/re/p
  • :g/re/dでマッチする行を削除する
  • :v/re/dでマッチする行を残す
  • qaqでaレジスタを削除
  • :g/{pattern}/yank Aでaレジスタに結果を保存
  • :g/{pattern}/t$でファイルの末尾にコピー
  • vi{で{}内を選択
  • :g/{/ .+1,/}/-1 sort
    • .はグローバルでは指定したpatternにマッチした行
    • +1,-1は単に{}の行を除いている
    • /{/と.+1/}/は別物。前者はglobalのpattern、後者はsortのrange
  • :g/{start}/ .,{finish}[cmd]

Part6 Tool

Ch16 ctags

  • ctagsの扱い方
  • コミット時にインデックスを再作成がよい
  • \<C-]>,g\<C-]>
  • \<C-t>
  • :tselectでタグマッチリストを再表示
  • :tnext,tprev,tfirst,tlast
  • :tag {keyword},:tjump {keyword}
  • :tag /{pattern}も可能

Ch17 quickfix

  • :cから始まるナビゲーションコマンド
  • quickfixリストを作るコマンドの頭にlをつけると、ロケーションリストを作成できる
  • quickfixリストはVimについてグローバル
  • cnfile,cpfile
  • colder,cnewer
  • makeprgでmake実行時のプログラムを指定
  • errorformatを設定することで、makeの出力のパースができる
  • :compilerでmakeprg,errorformatを設定

Ch18 grep/vimgrep

  • grepprg,grepformatでgrepをカスタマイズ
  • ackの使用
  • :vim[grep][!] /{pattern}/[g][j] {file} ...
  • ## : 引数リストの各ファイル名を展開

Ch19 自動補完

  • infercaseで大文字候補を小文字に変える
  • \<C-p>,\<C-n>で自動補完 in insert mode
  • \<C-x>\<C-{char}>で自動補完のバリエーション
  • ポップアップメニューの操作
  • \<C-n>\<C-p>が便利
  • \<C-x>\<C-i>のためのinclude設定←サポートされた言語は自動で認識
  • completeの設定で自動補完をカスタマイズ
  • \<C-x>\<C-k> : 辞書を使って自動補完→:set spellまたはdictionaryオプション
  • \<C-x>\<C-l>で行を自動補完
  • \<C-x>\<C-f>でファイル名を自動補完。Working Directoryが対象
  • \<C-x>\<C-o> : オムニ補完。インテリセンス

Ch20 スペルチェッカ

  • [s,]sでフラグのついた単語に移動
  • z=で修正候補を表示
  • spelllangの設定
  • http://ftp.vim.org/vim/runtime/spell/
  • [n]zg,zw,zug,spellfileオプション
  • \<C-x>\<C-s>で挿入モードでスペルの自動補完

付録

  • Vimの設定をオンザフライで変更する方法
  • edit $MYVIMRC
  • FileTypeによる判別はftpluginディレクトリに保存する