はじめに
こんにちは! イタンジ株式会社で更新退去くんというプロダクトを開発している佐藤です。
最近Vimの魅力に取り憑かれてしまった一人です。
約3ヶ月前にVimに手を出して、もう後戻りできないくらい夢中になっています🤩
(VScode1年、RubyMine1年を経て、Vimに辿り着きました🎉)
Vimは毎日新しい発見があり、とても面白いです!
特に、最近「グローバルコマンド(global command)」なるものを発見!
少し触ってみたところ、勉強しがいがあるかもと思いました!
今日はこのグローバルコマンドを一緒に勉強して行けたらなと思います。
グローバルコマンドって何?
Vimにはたくさんの機能がありますが、今日はその中でも「グローバルコマンド」に焦点を当てます。
このコマンドは、特定のパターンにマッチする行に対して一括でコマンドを適用するものです。
基本的な使い方
基本的な使い方は非常にシンプルです。:g
で始め、その後にパターンとコマンドを指定します。
:g
と :g!
の基本構文
:g/pattern/command
:pattern
にマッチする行にcommand
を適用:g!/pattern/command
:pattern
にマッチしない行にcommand
を適用
pattern と command
patternは正規表現で指定でき、commandはVimの各種コマンド(例:d
で削除、s
で置換)です。
実際の例
:g/foo/d
:foo
という文字列を含む全ての行を削除:g/^#/normal dd
:#
で始まる行をdd
コマンド(行削除)で削除
実用例:各種コマンドを使ったテクニック
削除(Delete)
変更前
# TODO: Remove this method def hello puts "Hello, World!" end
コマンド
:g/TODO/d
変更後
def hello puts "Hello, World!" end
解説
このコマンドで、TODO
を含むコメント行が削除されます。
置換(Substitute)
変更前
<div className="oldClass">Content1</div> <span className="oldClass">Content2</span> <div className="oldClass">Content3</div>
コマンド
:g/<div className="oldClass"/s/oldClass/newClass/g
変更後
<div className="newClass">Content1</div> <span className="oldClass">Content2</span> <div className="newClass">Content3</div>
解説
一般的には、:s
(または:%s
)コマンドで置換が可能です。
しかし、:g
と組み合わせることで、特定のパターンにマッチする行だけに置換を適用する操作が可能になります。
このコマンドで、<div className="oldClass">
というパターンにマッチする行のみ、oldClass
が newClass
に置換されます。
ノーマルモードコマンド(Normal)
変更前
const x = 10; const y = 'hello';
コマンド
:g/const/normal A // eslint-disable-line
変更後
const x = 10; // eslint-disable-line const y = 'hello'; // eslint-disable-line
解説
:normal
コマンドを使うことで、ノーマルモードのコマンドをExコマンド内で実行できます。
(Exコマンドは、コマンドラインモード(":")で使用されるコマンド群です)
(今回はg
というExコマンド内で使うという文脈で使用している)
この例では、const
を含む各行の末尾に // eslint-disable-line
というESLintを無効にするコメントを追加しています。
表示(Print)
変更前
const Button = () => { return <button className="primary">Click Me!</button>; }; const Alert = () => { return <div className="alert">Warning!</div>; };
コマンド
:g/className/p
実行結果
return <button className="primary">Click Me!</button>; return <div className="alert">Warning!</div>;
解説
:p
コマンドは、マッチした行を表示するためのコマンドです。
この例では、className
属性を持つJSX要素が表示されます。
応用例: パターン範囲を使用する
パターン範囲とは?
Vimでは、特定の行だけでなく、行の範囲に対してもコマンドを適用することができます。
パターン範囲は、:/pattern1/,/pattern2/
のように、2つのパターンで始点と終点を指定します。
(厳密には範囲の指定方法の一種なので、パターン範囲という名称があるわけではないです)
(ただ単にマッチした行を範囲の行指定子の対象にできるということです)
この範囲内のすべての行がコマンドの対象となります。
一般的な形式
:[range]command
range
: 範囲。例::/begin/,/end/
など。command
: 適用するコマンド。例:delete
など
例: 複数行のコピー
変更前
class UsersController < ApplicationController def show @user = User.find(params[:id]) end end
コマンド
:g/def show/,/end/t$-1
変更後
class UsersController < ApplicationController def show @user = User.find(params[:id]) end def show @user = User.find(params[:id]) end end
解説
この例では、:t
コマンドとアドレス範囲:g/def show/,/end/
を組み合わせて、def show
からend
までのブロックをファイルの末尾から1行上にコピーしています。
まとめ
globalコマンド便利ですね!
私自身、この記事を書きながら新しい発見がたくさんありました。
(恥ずかしながら、パターン範囲は記事を書いている最中に知りました🤯)
おかげで今回もVimmerとしてのランクアップを遂行することができました🫡
最後に一言
「お前もVimmerにならないか?」
参考資料
https://vim-jp.org/vimdoc-ja/cmdline.html
https://vim-jp.org/vimdoc-ja/cmdline.html#cmdline-ranges
https://vim-jp.org/vim-users-jp/2009/06/22/Hack-30.html
https://vim-jp.org/vimdoc-ja/repeat.html#:global