この記事では、Vim / neovim でプラグインを使わずにファイル内でジャンプする「マーク」の使い方について、ご紹介します。
[解答]
マークの一覧を参照する
(ノーマルモード) :marks
マークした場所の一覧を表示することができます。また、指定したマークだけ表示する場合はこちらです。
(ノーマルモード)
:marks {マーク文字}
マーク文字は複数つなげて指定することができます。
マークを作る
Exコマンドだと、次のように作ります。
:mark {マーク文字}
{マーク文字}は英文字の大文字小文字のいずれかを指定します。
キー操作でコマンドを実行する場合は、次のように実行します。
(ノーマルモード) m{マーク文字}
同じく、{マーク文字}は英文字の大文字小文字のいずれかを指定します。
キー操作で実行する方が簡単ですね。
マークへ移動する(ジャンプ)
`{マーク文字}
{マーク文字}は英文字の大文字小文字のいずれかを指定します。
ちなみに、指定したマークの行頭へ移動するなら次のように実行します。
'{マーク文字}
マークを削除する
:delmarks {マーク文字}
{マーク文字}は英文字の大文字小文字のいずれかを指定します。
また、これまでマークした内容をすべて削除する場合は次のコマンドを実行します。
:delmarks!
せっかくマークした内容が全部消えてしまうので注意が必要です。
大抵の場合は、上書きするだけで問題無いはずですから、そちらを使った方が危険が少ないでしょう。
特殊なマークへ移動する(ジャンプ)
Vimでは、あらかじめ次のようなマークが設定されています。
コマンド | 実行内容 |
---|---|
`. | 最後の編集箇所へジャンプ |
`^ | 最後の挿入箇所へジャンプ |
`0 | 最後にVimを終了したときの位置へジャンプ |
`” | 現在のファイルを最後に閉じたときの位置へジャンプ |
“ | 直前のマークへジャンプ |
Ctrl-o | 古いマークへジャンプ |
Ctrl-i | 新しいマークへジャンプ |
こちらは暗記して、いつでも使えるようになるとスムーズにジャンプできますね。
オペレータ+マーク
マークはモーションとしても活用できます。
コマンド | 実行内容 |
---|---|
d`{マーク文字} | マークまで削除する |
y`{マーク文字} | マークまでコピー(ヤンク)する |
c`{マーク文字} | マークまで置換する |
gU`{マーク文字} | マークまで大文字にする |
gu’{マーク文字} | マークまで小文字にする |
正直、ビジュアルモードとどちらが良いのかは悩ましいところですが、使い方としてはありうるということで。
なんてことを書いていたら、次のようにコメントいただいて合点がいきました。なるほどー!という感じですね。
このVimコマンドの補足情報
- 利用頻度
- 便利さ
- 覚え易さ
関連するVimヘルプ
Vim のヘルプでは下記のように解説されています。
7. マーク mark-motions E20 E78
マークへジャンプするには2つの方法があります:
1. ` (バッククォート)で : カーソルは指定された位置に置かれます。exclusive
2. ‘ (シングルクォート)で: カーソルは指定された位置の行の最初の非空白文字に置
かれ移動は行単位です。m mark Mark
m{a-zA-Z} カーソル位置を{a-zA-Z}にマークします(これは移動コマン
ドではありません。ですのでカーソルは動きません)。m’ m`
m’ or m` 直前位置マークをセットします。””” もしくは ““” コマ
ンドでこの位置に移動できます。(移動コマンドではありま
せん。ですのでカーソルは動きません)。m[ m]
m[ or m] マーク ‘[ or ‘] をセットします。オペレータコマンド
が複数のコマンドでシミュレートされるときに便利です。
(移動コマンドではありません。ですのでカーソルは動きま
せん)。m< ‘< or gv コマンドで選
択される範囲を変更するのに便利です。 (移動コマンドでは
ありません。ですのでカーソルは動きません)。
Note ビジュアルモードは設定できません。開始と終了の位
置のみ設定できます。:ma :mark E191
:[range]ma[rk] {a-zA-Z’}
[range]の範囲の最後の行番号の0桁目を{a-zA-Z}にマーク
します。デフォルトはカーソル行です。:k
:[range]k{a-zA-Z’} :mark コマンドと同じですが、マーク名の前のスペースは挿
入しなくてもよいです。‘‘a` `a
‘{a-z} `{a-z} カレントバッファのマーク {a-z} へジャンプ。‘A‘0`A`0
‘{A-Z0-9} `{A-Z0-9} マーク {A-Z0-9} を含むファイル・位置へジャンプ。
(別のファイルにある場合は移動コマンドにはなりません)。g’g’ag`g`a
g'{mark} g`{mark}
{mark} へジャンプするが、カレントバッファ内で移動する
場合にはジャンプリストを変更しない。例:
g`”
これはファイル内の最後の記憶している位置にジャンプする。
$VIMRUNTIME/vimrc_example.vim を参照。:keepjumpsも参照。:marks
:marks 現在のマークを全てリストします(移動コマンドではありません)。
‘(, ‘), ‘{ と ‘} マークはリストされません。
1桁目は桁番号0となります。E283
:marks {arg} {arg} で指定されるマークをリストします(移動コマンドで
はありません)。例:
:marks aB
マーク ‘a’ と ‘B’ をリストします。:delm :delmarks
:delm[arks] {marks} 指定されたマークを削除します。削除できるマークはA-Zと
0-9などです。マーク’は削除できません。それらはダッシュ
で区切られたマーク名のリストを与えることで指定できます。
スペースは無視されます。例:
:delmarks a マークaを削除する
:delmarks a b 1 マークa, b, 1を削除する
:delmarks Aa マークA, aを削除する
:delmarks p-z pからzまでのマークを削除する
:delmarks ^.[] マーク^ . [ ]を削除する
:delmarks \” マーク”を削除する
:delm[arks]! A-Z, 0-9を除くカレントバッファのすべてのマークを削除します。マークはどのようにしても見えません。マークは単に覚えておかれるファイル中の位置
に過ぎません。マークと名前付きレジスタを混同しないようにしてください、まったく
別のものです。‘a – ‘z 小文字のマークです。1つのファイル中で有効です。
‘A – ‘Z 大文字のマークで、ファイルマークとも呼ばれます。ファイル間でも
有効です。
‘0 – ‘9 番号マークです。.viminfo ファイルによってセットされます。小文字のマーク ‘a から ‘z まではマークのあるファイルがバッファリストに存在する
限り覚えておかれます。もしファイルをバッファリストから削除するとそのファイルに
関するマークは全て失われます。またマークを含んでいる行を削除するとそのマークは
消されます。小文字のマークはオペレータコマンドとともに使うことができます。例: “d’t” は現在
のカーソル位置からマーク ‘t’ までの行を削除します。アイデア: マーク ‘t’ をTop
位置に設定したり、’b’ を Bottom 位置に設定したりします。小文字のマークはアン
ドゥとリドゥによって復元することができます。大文字のマーク ‘A から ‘Z はファイル名を含んでいます。ファイルからファイルに移
動するのに使うことができます。大文字のマークをオペレータコマンドとともに使うに
はマークは現在のファイルになければなりません。また大文字のマークの場合は行を挿
入/削除したり一時的に他のファイルを編集したりしてもマークのある行番号は覚えて
おかれます。‘viminfo’ オプションの値が空でなければ大文字のマークは .viminfo
ファイルに保持されます。参照: viminfo-file-marks番号マーク ‘0 から ‘9 まではこれらとはまったく異なります。直接セットすることは
できず、viminfo ファイル viminfo-file を使っている場合にのみ存在します。基本
的に ‘0 は最後に Vim を終了したときのカーソル位置であり、’1 は最後から1個前の
位置、などなどです。特定のファイルを番号マークに保存しないようにするには
‘viminfo’ の “r” フラグを使ってください。参照: viminfo-file-marks‘[`[
‘[ `[ 直前に変更またはヤンクされたテキストの最初の文字へ移動します。‘]`]
‘] `] 直前に変更またはヤンクされたテキストの最後の文字へ移動します。なんらかのオペレータコマンドを実行した後は、カーソルはオペレータを施したテキス
トの初めに置かれます。プットコマンド(“p” もしくは “P”)の後は、カーソルは挿入さ
れた最初の行に位置する場合と最後に挿入された文字に位置する場合があります。上の
4つのコマンドはカーソルをどちらかの端に位置させます。例: 10行ヤンクした後、そ
の行の内の最後の行に移動したい場合は: “10Y’]”。数行を “p” コマンドで挿入した
後、1番下に挿入された行に移動したい場合は: “p’]”。これはすでに挿入済みのテキス
トに関しても動作させることができます。Note: 矩形ビジュアルモードを使っているのでない限り、テキストの削除の後は始めと
終わりの位置は同じです。これらのコマンドは、現在のファイルに対してまだ変更がさ
れていない場合は動作しません。‘<`<
‘< `< 現在のバッファで最後に選択されたビジュアルエリアの最初
の行(‘<)または最初の文字(`<)に移動します。ブロックモー
ドでは最初の行の最後の文字になる場合もあります(選択の
開始位置による)。‘selection’ が適用され、位置はビジュアルエリアの直後に
開始位置による)。”“
” “ カーソルがジャンプする直前にいた、もしくは最後の “m'”
か “m`” コマンドが行われた位置に移動します。
:keepjumps コマンドモディファイヤが使われた場合には
セットされません。
restore-position も参照。‘quote`quote
‘” `” 現在のバッファを最後に終了した時のカーソル位置に移動し
ます。デフォルトで最初の行の最初の文字に移動します。そ
れぞれの開いたファイルでこれをどのようにして使うかにつ
いては last-position-jump をご覧下さい。
ウィンドウごとに1つではなく、バッファに対して1つの位
置が記憶されます。バッファがあるウィンドウに表示されて
いる間はその位置は変わりません。‘^`^
‘^ `^ 最後に挿入モードが終了したときのカーソル位置に移動しま
す。これは gi コマンドで使われます。
:keepjumps コマンドモディファイヤが使われたときは
セットされません。‘.`.
‘. `. 最後に変更された場所に移動します。変更が始まった場所か
その近くです。1つのコマンドが複数の変更をすることもあ
ります。その場合は、変更の最後の近くになります。例え
ば、単語を入力をしたときは、最後の文字の上になります。
さらに古い変更へジャンプするには g; が使えます。
{Vi にはありません}‘(`(
‘( `( ( コマンドのように、現在の文の最初に移動します。‘)`)
‘) `) ) コマンドのように、現在の文の最後に移動します。‘{`{
‘{ `{ { コマンドのように、現在の段落の最初に移動します。‘}`}
‘} `} } コマンドのように、現在の段落の最後に移動します。これらのコマンドは、それ自身はマークではなく、マークへジャンプします:
]’
]’ カーソルがある行から [count] 個先の小文字のマークがあ
る行の最初の非空白文字へ移動します。]`
]` カーソル位置以降の [count] 個先の小文字のマークへ移動
します。
[‘
[‘ カーソルがある行から [count] 個前の小文字のマークがあ
る行の最初の非空白文字へ移動します。[`
[` カーソル位置より [count] 個前の小文字のマークへ移動し
ます。:loc[kmarks] {command} :loc:lock:lockmarks
マークを調整することなく {command} を実行します。
{訳注: 普通にコマンドを実行したときはマーク位置が調整
される}
これは、完了したときの行数が実行前と変わらないような変
更をするときに便利です。
警告:行数が変わった場合には、変更箇所以降のマークは以
前の行番号を持ち続けるので、別の行に移動することになり
ます。
以下のものが行の削除・挿入後に調整されません:
– 小文字のマーク ‘a – ‘z
– 大文字のマーク ‘A – ‘Z
– 番号マーク ‘0 – ‘9
– 最後の挿入箇所 ‘^
– 最後の変更箇所 ‘.
– 最後に影響を受けたテキスト領域 ‘[ および ‘]
– ビジュアルエリア ‘< と ‘>
– 目印が設置された行の番号
– quickfix 箇所の行番号
– jumplist 内の位置
– tagstack 内の位置
以下のものは調整されます:
– 直前の文脈マーク ”
– カーソル位置
– バッファに対するウィンドウの表示
– 折り畳み
– 差分表示:kee[pmarks] {command} :kee:keep:keepmarks
現在のところ、フィルターコマンド :range! にだけ効果
があります:
– フィルタリングの後の行数が実行前以上の場合、全ての
マークは同じ行番号を持ち続けます。
– 行数が減る場合、削除された行中のマークは削除されま
す。
どちらの場合にも、フィルタされたテキスト以降のマークは
通常通りテキストに一致するよう調整されます。
‘cpoptions’ オプション中に ‘R’ フラグがない場合、これ
は “:keepmarks” を使うのと同じ効果があります。:keepj:keepjumps
:keepj[umps] {command}
{command}の実行中の移動でマーク ”, ‘., ‘^ と
jumplist や changelistを変更しないようにします。
自動的に変更やテキストの挿入を行い、ユーザーがその位置
に行きたくないという場合に便利です。例:タイムスタンプ
“Last change” を更新するとき::let lnum = line(“.”)
motion – Vim日本語ドキュメント
:keepjumps normal gg
:call SetLastChange()
:keepjumps exe “normal ” . lnum . “G”
Note “:keepjumps” はコマンドごとに使わねばなりません。
関数を呼び出すとその関数の中のコマンドはジャンプリスト
を変えてしまいます。また、”:keepjumps exe ‘command ‘”
とすると、この “command” はジャンプリストを変えてしま
います。そうでなくて “:exe ‘keepjumps command'” として
ください。
こちらは、Vim上では下記のコマンドでヘルプを確認できます。
:help mark-motion
ヘルプで検索するときは、通常は大文字小文字は識別されませんので、どちらでも構いません。
参考書籍
こちらの書籍が参考になります。
Vim/neovim関連の書籍で、もっとも評判が良くてバイブルと呼んでる人もいる一冊です。Vim/neovimのバージョンに依存しない沢山のTips形式で、その表題通りに「思考のスピードで編集」できるようになるノウハウが詰まっています。その高い評価は Amazon のレビューからも分かる通りです。Vimmer なら必ず一度は読んでおいて間違いありません。
こちらもVim関連の書籍で評価が高い書籍の一冊です。vim-jpで見かける上級Vimmer(Vimサポーターズ)の皆様による、Vimを実践で使ったノウハウからプラグイン関連の情報が詰まっています。日本の Vim界隈を知る上でも是非一読しておきたい一冊です。
Vim/neovim の設定ファイルやプラグインなど、Vim script に関するノウハウがいくつも詰まった一冊です。日本で Vim Script をここまで深く解説している唯一の書籍と言えます。Vim力を伸ばしたいと考えるなら、絶対に避けては通れない書籍でしょう。