Man On a Mission

システム運用屋が、日々のあれこれや情報処理技術者試験の攻略を記録していくITブログ…というのも昔の話。今や歴史メインでたまに軍事。別に詳しくないので過大な期待は禁物。

Vim備忘録 コピペとレジスタ

先日、Linuxにおけるクリップボード機能についての記事を書きました。

oplern.hatenablog.com

上記記事中、少しVimのコピペ機能におけるクリップボード連携に触れています。

一般的なテキストエディタ、例えばWindowsのメモ帳やLinuxのgedit、LeafpadなどではOSなどの機能を使ってコピペが実現されています。
WindowsではOSのクリップボード機能、Linuxでは、X Window SystemのXセレクション。)
それに対して、Vimでのコピペは、Vim独自方式で行われます。Vimでコピー(yank)や削除したテキストは、レジスタと呼ばれる領域に格納されます。
ペーストの際は、レジスタに格納された内容を読み出すわけです。

Vimのコピペは割と多機能であり、それゆえにとっつきにくい体系になっています。今回は、このとっつきにくさを多少なり緩和するための、各レジスタ解説記事です。

 レジスタの入門知識

Vimレジスタは、クリップボードと違って複数の領域があります。
何も気にせずにヤンク、例えば「yy」で一行ヤンクしたテキストは「無名レジスタ」というレジスタに格納されますが、「"ayy」というコマンドでヤンクすると、「名前付きレジスタ」であるレジスタaに格納されます。レジスタaに格納されたテキストを貼り付けるには、「"ap」のようにします。

無名レジスタへの一行ヤンクと、レジスタaへの一行ヤンクのコマンドの違いは、「yy」の前に「"a」があるか否かです。
「"a」は、「"」が「明示的にレジスタを指定する」ことを、「a」が指定するレジスタを表しています。
名前付きレジスタはaからzまでの26個ありますが、例えば「"byy」でレジスタbへ一行ヤンク、「"zdd」とすると削除したテキストはレジスタzに格納されます。

ちなみに、無名レジスタは「"」で表されます。なので、無名レジスタを明示的に指定するには「""yy」のようにします(意味は無いですが…)。

レジスタに格納した内容は、「:registers」コマンドで確認できます。
実行してみると、上記で説明した無名レジスタや名前付きレジスタ以外にも、「"0」だの「":」だのよくわからないレジスタが表示されると思います。詳細は次節以降で。

10種類のレジスタ

レジスタは、前述した無名レジスタ、名前付きレジスタ以外にも存在し、全部で10種類ものレジスタがあります。
以下、各種レジスタについて、順に述べます。
(実は、Vimにて「:h registers」で調べられるのですが、ちょっとわかりにくいです。今回記事は、「備忘録」というタイトルになってますが、どちらかというと、このやたらと多いレジスタの整理を目的としたものです。)

1. 無名レジスタ ""

前節で述べた通り、使用レジスタを指定しなかった場合に格納先となるレジスタです…が、実はこの記述だけでは正確な表現ではありません。

無名レジスタは、コマンド「d」、「c」、「x」などによる削除や、「y」などでヤンクしたテキストが無差別に格納されます。
レジスタを指定していようがなんだろうが”原則”関係ありません。そのため、名前付きレジスタを指定してヤンクした場合、指定した名前付きレジスタだけでなく、無名レジスタにも同じ内容が格納されます。
ただし、この挙動は”原則”であり、一つだけ例外があります。レジスタ指定において、「"_」を指定した場合は、無名レジスタには格納されません。
この「"_」は、消去専用レジスタ、通称ブラックホールレジスタと呼ばれるものです。(詳細は後述します。)

2. 番号付きレジスタ "0 から "9

番号付きレジスタは、0から9まで10個あります。
ただし、0と1〜9までのレジスタでは役割が異なります。

レジスタ0

レジスタ0には、直近にヤンクしたテキストが格納されます。
ただし、ヤンクの際、「"ay」などの様に、レジスタを指定した場合は、格納されません。

レジスタ1〜9

1〜9までのレジスタには、直近に削除・変更したテキストが格納されます。一番最近に削除したテキストはレジスト1に格納され、その前に削除したテキストは順次、レジスト2、3、4…という風に格納されます。
(要は、新たな削除・変更テキストはいったん1に格納され、テキストの削除・変更が発生するたびに、レジスタ1の内容が後ろの番号に移されていく形です。)

なお、レジスタ0と同様「"add」などレジスタを指定して削除・変更した場合は格納されません。
また、1行以下の削除の場合も格納されません。この場合は、後述する小削除用レジスタに格納されます。

3. 小削除用レジスタ "-

1行以下の削除・変更コマンドを実行した場合、削除・変更したテキストは小削除用レジスタに格納されます。
なお、Vimのヘルプでは「1行以下」となってるのですが、どうも改行コードの有無で判別されているようです。改行コードが含まれない場合は小削除用レジスタに格納されるっぽい。

4. 名前付きレジスタ "a から "z

ユーザーが、「"a」のように明示的にレジスタ指定した場合にのみ使用されます。
複数のテキスト箇所をコピペしたい場合に利用することになるでしょう。

なお、「"a」のように小文字で指定すると、当該レジスタの内容を上書きします。
「"A」のように大文字で指定すると、レジスタの既存の内容の後ろに追記されます。

5. 読み取り専用レジスタ ": と ". および "%

読み取り専用レジスタは、明示的に指定してもユーザーのヤンク操作などでは格納できません。
(読み取り専用なので、当たりまえですが。)

レジスタ:

レジスタ:は、直近に実行されたコマンドラインのコマンド(「:」で始まる各種コマンド。別名EXコマンド)が格納されます。

レジスタ.

レジスタ.には、最後に挿入されたテキストが格納されます。

レジスタ%

レジスタ%には、編集中のファイル名(カレントファイル名)が格納されます。

6. 代替ファイルレジスタ "#

カレントウィンドウの代替ファイル名が格納されます。
代替ファイルと言われても、よくわからないかもしれません。要は、複数ファイルを開いた際、現在編集中のファイルの次に控えているファイルのことを指します。

そういう役割のレジスタですので、当然、読み取り専用であり、明示的に指定してもユーザーのヤンク操作などでは格納できません。
正直、読み取り専用レジスタに含めてもいいように思うのですが、Vimのヘルプに合わせて、別項目にしました。

7. Expressionレジスタ "=

割と特殊なレジスタです。「"=」コマンドを打ち込むと、コマンドライン上に「=」と表示されます。ここで、計算式(expression)を打ち込んでEnterを押し、その後「p」などのペーストコマンドを打つと、計算式の結果が貼り付けられます。
計算式は、算術演算だけでなく、Vimスクリプトのファンクションなども利用できます。利用できるexpressionについては、Vimのヘルプ(:h expression)を参照してください。

8. 選択範囲レジスタ "* と "+ および "~

システムのクリップボードに読み書き出来るレジスタです。
Vimのコピペは独自実装のため、無指定のヤンク/ペーストなどでは、クリップボードと別扱いとなります。すなわち、クリップボードを介した別アプリケーションとの連携が出来ません。
レジスタ*またはレジスタ+は、OSまたはX Window Systemクリップボード/Xセレクションと連携しているので、クリップボードを介してコピペしたい場合は、当該レジスタを指定してヤンク/ペーストなどを行います。

レジスタ* および レジスタ+

前回記事でも少し触れましたが、Linux環境においてはレジスタ*がXセレクションのPRIMARY領域、レジスタ+はXセレクションのCLIPBOARD領域に対応しています。
多くの方は、CLIPBOARD領域を使ったコピペを使われるかと思うので、とにかくクリップボードでコピペしたいと思ったら「"+」でレジスタ+を指定しましょう。

なお、Windowsではレジスタ*/レジスタ+に違いはありません。

レジスタ~

レジスタ~は、他のアプリケーションから、テキストをGVimドラッグアンドドロップした際に利用されるレジスタです。

9. 消去専用レジスタ "_

通称、ブラックホールレジスタ
ヤンクや削除などで、「"_」を指定すると、テキストはどこにも格納されず消えてしまいます。
Linuxをお使いの方は、Vim版「/dev/null」だと思えばよいでしょう。

何の役に立つんだと思われる方もいるかもしれませんが、番号付きレジスタに格納せず、テキストを削除したい場合などに利用します。
Vimスクリプトを使った自動化を行う時とかに、使うことがあります。)

10. 最終検索パターン用レジスタ "/

最後に使った検索パターンが格納されるレジスタです。
このレジスタは読み取り専用であり、明示的に指定してもユーザーのヤンク操作などでは格納できません。
しかし、実はちょっとした小技で変更は可能です。コマンドラインから「:let @/ = "検索したい文字列"」で入れ替えることが出来ます。
検索を実行せずにhlsearchで強調表示したい箇所を切り替える時などに利用できます。

最後に

さて、Vimのコピペは割と多機能であり、それゆえにとっつきにくい体系になっていますが、こうやって整理してみるとやっぱりとっつきにくいですね(ふりだしに戻る)。

ちなみに、前節の検索パターンの入れ替えで例示した「:let @/ = "検索したい文字列"」ですが、他のレジスタでも使えます。
「@+」というように@の後ろにレジスタの識別子を入れると、当該レジスタの内容を変更できます。全てのレジスタで出来るわけではありませんが、Vimスクリプトで何か作るときに利用できるかもしれません。

それでは良きVim生活*1を。

 

*1:どんな生活かは不明