エディタ (Vim)
文章を書くこととプログラミングは全く異なる営みです。 英語のライティングがまとまった文章を書く作業であるのに対し、 プログラミングではファイルを切り替え、コードを読み、辿り、そして編集します。 そのため、英語という言語に適したエディタとプログラム言語に適したエディタがあるのです。(例: Microsoft Word と Visual Studio Code)
プログラマとして我々は大半の時間をコードの編集作業に費やすため、 ニーズに合ったエディタに習熟することは非常に時間対効果が高いといえます。 以下に新しいエディタの使い方を学ぶ際の一般的な方法論を紹介します。
- チュートリアルを始める(例: 本講座 + 紹介資料)
- (たとえ一時的に生産性を損ねても)あらゆる編集作業でそのエディタを使うことに拘る
- 常により良い方法がないかを模索する。もしもっと良い方法がないかという考えが頭をよぎったら、それは必ず存在します。
上記の方法に従い新たなプログラムをエディタの使い方を学ぶ題材にするならば、 タイムラインはこのようになるでしょう。 まず 1、2 時間以内にエディタの基礎機能(ファイルを開いて編集する、保存・終了する、バッファを操作する) を習得します。 20 時間も経てば元のエディタと同じくらいの速度で編集できるようになっているでしょう。 新しいエディタに関する十分な知識を得て、使い方を身体で覚えたならば、 その恩恵を受け膨大な時間を節約することができるようになっていきます。 モダンなテキストエディタは素晴らしく強力なツールです。 あなたは学べば学ぶほどより速い編集能力を身につけることができるでしょう。
どのエディタを学ぶべきですか?
プログラマはテキストエディタに関して様々な選択肢があります。 どのエディタが現在最も人気でしょうか? Stack Overflow での調査 によると、 Visual Studio Code が全体で最も人気があり、 Vim は CLI(コマンドラインインターフェース)のエディタの中で最も支持を集めています。 (ただし、Stack Overflow のユーザは全プログラマを代表するものではないため調査結果にはバイアスが含まれています。)
Vim
本講座では全てのインストラクションに Vim を用います。 Vim には長い歴史があります。 Vim は元々 Vi(1976)として開発され、今日まで開発が継続されてきました。 Vim はいくつかの素晴らしいアイデアに基づいて設計されているため、 多くのツールが現在でも Vim の挙動をエミュレートするモードを採用しています (VSCode においても、140 万のユーザが Vim emulation for VS code をインストールしています)。 つまり、たとえ他のエディタを最終的に使うことになるとしても、Vim は間違いなく学ぶ価値があるといえるでしょう。
Vim の機能全てを 50 分の講座で紹介し尽くすことは到底できません、 そこで本講座は Vim の哲学とその基礎、より高度な機能の一部を紹介するに留めようと思います。 講座の終わりでは Vim に更に習熟するための情報源をまとめて紹介します。
Vim の哲学
プログラミングをする際、我々は殆どの時間をコードを書くことではなく、読むことと編集に費やします。 このため Vim は モーダル エディタとして設計されており、 テキストの挿入と編集にはそれぞれ異なるモードが割り当てられています。 また、Vim はプログラマブル(Vimscript や Python 等他のプログラミング言語で拡張機能を開発可能) であり、覚えやすいキーストロークやコマンドは全て組み合わせて実行することができます。 Vim はマウスの使用を徹底して避けます。マウスでの操作はキーボードのそれと比較して余りにも遅いからです。 更に Vim は矢印キーの使用を避けます、これもキーボード上で必要な移動量が大きすぎるためです。 これらの思想を元に、思考のスピードで編集することが可能なエディタが完成しました。
モーダル編集
多くのプログラマはまとまった長いテキストを書くよりも、 コードを読み、ファイルを辿り、そして僅かに編集を加える という作業に大半の時間を費やしているという事実に着眼して Vim は設計されています。 このため、Vim は複数の操作モードを備えています。
- ノーマルモード:ファイル上を移動し、編集を加える
- 挿入モード:テキストを挿入する
- 置換モード:テキストを置換する
- ビジュアルモード:テキストをブロック選択する
- コマンドラインモード:コマンドを実行する
キーバインドは操作モード毎に異なる機能が割り当てられています。
挿入モードでの x
は単に文字 x の挿入を行いますが、ノーマルモードではカーソル下の文字を消去し、
ビジュアルモードでは選択範囲を消去します。
初期設定では、Vim の画面左下に現在のモードが表示されます。 デフォルトのモードはノーマルモードです。 基本的には、ノーマルモードと挿入モードを行き来することになります。
<ESC>
(Escキー) を押すと現在のモードからノーマルモードに切り替えることができます。
ノーマルモードからは、i
で挿入モード、R
で置換モード、v
でビジュアルモード、V
でビジュアルブロックモード、
<C-v>
(Ctrl-V、^V
とも表記)、コマンドラインモードに :
で入ります。
Vim で編集する際は <ESC>
を頻繁に使うため、
Caps Lock キーを Escape に置換することを検討してみてもいいでしょう
(macOS
instructions)。
基本
テキストを挿入する
ノーマルモードから、i
を押下して挿入モードに入ります。
挿入モードでは、Vim は他のエディタと殆ど同じような挙動をしているでしょう。
そこで <ESC>
を押すとまたノーマルモードに戻ってきます。
これが Vim によるファイル編集の全ての基本になります。
(挿入モードで大半の編集作業を行わず、速やかにノーマルモードに戻るようにして下さい。)
バッファ、タブ、ウィンドウ
Vim ではメモリ上に読み込まれたファイルのことを”バッファ”と呼びます。 Vim のセッションはバッファの表示領域であるウィンドウと、そのウィンドウを集めたタブを管理しています。 ウェブブラウザ等他のアプリケーションとは異なり、Vim のバッファとウィンドウには 1 対 1 の対応関係があるわけではありません。 ウィンドウは単に表示領域に過ぎず、あるバッファの内容を同じタブ、複数のウィンドウに表示することもできます。 これは例えばあるファイルの 2 つの異なる領域を同時に表示したいという場合に役立ちます。
デフォルトでは、1 つのウィンドウを含む 1 つのタブを立ち上げます。
コマンドライン
コマンドモードにはノーマルモードで :
を入力して切り替えます。
画面下に入力領域が移り、:
以降にコマンドを入力することができます。
このモードはファイルを開く、保存する、閉じる、Vimを終了する といった多くの機能を担っています。
:q
終了する(ウィンドウを閉じる):w
保存する (“write”):wq
保存して閉じる:e {ファイル名}
ファイルを開いて編集する:ls
バッファの一覧を表示する:help {topic}
ヘルプを開く:help :w
:w
コマンドに関するヘルプを開く:help w
(ノーマルモードでの移動)w
に関してヘルプを開く
Vim のインタフェースはプログラム言語である
Vim における最も重要なアイデアは、Vimのインタフェース自体もプログラミング言語であるということです。 キー入力にはコマンドが割り当てられ、各コマンドは組み合わせることができます。 この仕様により、一度身体でコマンドを覚えれば、非常に効率的に移動や編集を行うことができるようになります。
移動
編集作業中は、 ノーマルモードにおいてバッファ上を移動することに多くの時間を使っているべきです。 Vim における移動は操作するテキストの断片を参照するため、”名詞”とも呼ばれます。
- 基本の移動:
hjkl
(左へ, 下へ, 上へ, 右へ) - 単語:
w
(次の単語へ)、b
(単語の先頭へ)、e
(単語の末尾へ) - 行:
0
(行の先頭へ)、^
(行先頭の文字へ)$
(行末へ) - スクリーン:
H
(画面の先頭行へ)M
(画面の中央行へ)L
(画面の最終行へ) - スクロール:
Ctrl-u
(上へ)Ctrl-d
(下へ) - ファイル:
gg
(ファイルの先頭へ)G
(ファイルの末尾へ) - 行番号:
:{number}<CR>
または{number}G
({number}
行目へ) - その他:
%
(括弧等対応する要素へ) - 文字への移動:
f{character}
、t{character}
、F{character}
、T{character}
- 現在の行上で
{character}
を前 (f,t) / 後 (F,T) に検索し、該当文字の上 (f,F) / 直前の文字 (t,T) に移動する - 現在の行において、次の該当文字上へ/該当文字の 1 文字前へ/前の該当文字へ 移動する
,
/;
マッチした文字を移動する
- 現在の行上で
- 検索:
/{regex}
、n
/N
正規表現で検索した文字列を前に/後に検索する
選択
ビジュアルモード:
- ビジュアル
- ビジュアルライン
- ビジュアルブロック
は移動キーを用いて選択を行うことができます。
編集
今までマウスで行っていた作業は、 編集コマンドと移動コマンドを組み合わせることで全てキーボードで行えるようになります。 Vim の編集コマンドは先で述べた名詞に対して機能させることができるため、”動詞”とも表現されます。 Vim のインタフェースがプログラミング言語のように感じられてきたでしょう。
i
編集モードに入る- ただし、テキストを操作/消去する際は backspace よりノーマルモードを利用しましょう
o
/O
行を一行下に/一行上に挿入しますd{motion}
{motion} を消去する- 例:
dw
文字を消去する、d$
行末まで文字を消去する、d0
行頭まで文字を消去する
- 例:
c{motion}
{motion} を変更する- 例:
cw
単語を変更する(d{motion}
+i
と同等)
- 例:
x
文字を消去する(dl
と同等)s
文字を置換する(xi
と同等)- ビジュアルモード + 操作
- テキストを選択し、
d
で消去またはc
で変更する
- テキストを選択し、
u
元に戻す、<C-r>
やり直しy
コピーする(d
でも消去した内容のコピーを行います)p
貼り付け~
単語のキャピタライズを切り替える(大文字⇔小文字)
カウント
名詞と動詞は数字カウントを付加して組み合わせることができます。 数字カウントによって、その回数分コマンドを繰り返すことができます。
3w
3単語先に移動する5j
5行下に移動する7dw
7単語消去する
修飾子
名詞の機能を変更する修飾子を付加することができます。
例えば i
は ”inner” ”inside” を意味し、a
は “around” を意味します。
ci(
括弧内の内容を変更するci[
角括弧内の内容を変更するda'
シングルクオートで囲まれた文字を'
を含めて消去する
Demo
これは不完全な fizz buzz の実装です:
def fizz_buzz(limit):
for i in range(limit):
if i % 3 == 0:
print('fizz')
if i % 5 == 0:
print('fizz')
if i % 3 and i % 5:
print(i)
def main():
fizz_buzz(10)
我々は以下の問題を修正しなければなりません。
- Main が呼ばれていない
- イテレーションが 1 ではなく 0 から始まっている
- 15 の倍数のとき、”fizz” “buzz” を別々の行に出力してしまう
- 5 の倍数のとき、”fizz” を出力してしまう
- コマンドライン引数ではなく、ハードコーディングされた入力(10) を使っている
講義ビデオを視聴し、上記の変更が Vim を用いてどのように編集されるか、それが他のエディタを用いた場合といかに異なるかを確認してください。 Vim で必要なキータイプ数が非常に少なく、習熟すればまさしく思考のスピードで編集できるということが 実感できるでしょう。
Vim のカスタマイズ
Vim は VimScript を含んだプレーンテキストの設定ファイル ~/.vimrc
によってカスタマイズすることができます。
Vim では有効化することが推奨される基本設定が多くあります。
そこで我々は入門用として、(ドキュメンテーションされた)基本のコンフィグファイルを用意しました。
やや扱いづらいデフォルトの挙動を修正するこのコンフィグをまず利用することをおすすめします。
ここからファイルをダウンロードし、~/.vimrc
に保存してください。
Vim は隅々までカスタマイズが可能で、カスタマイズオプションを調査しつくす価値は大いに有ります。 GitHub 上で他のユーザの dotfiles を参考にしてもいいでしょう。 例えばインストラクターのコンフィグも GitHub に公開しています (Anish, Jon (neovim ユーザ), Jose)。 また、ネット上には Vim の設定について多くのブログ記事が公開されています。 ただし、単に他のユーザの設定をコピーペーストするのではなく、熟読し、内容を理解し、必要な設定だけを取り入れるようにしましょう。
Vim を拡張する
Vim では非常に多くの拡張プラグインが開発されています。
まずプラグインマネージャを導入する、という解説記事を多く目にするかもしれませんが、
Vim 8.0 以降では必ずしもプラグインマネージャを使用する必要はありません。
その代わりに、Vim 組み込みのパッケージ管理システムを利用することができます。
新規にディレクトリ ~/.vim/pack/vendor/start/
を作成し、このディレクトリにプラグインを(git clone
等で)
配置してください。
我々が愛用しているプラグインの一部を紹介します。
- ctrlp.vim: fuzzy file finder
- ack.vim: code search
- nerdtree: file explorer
- vim-easymotion: magic motions
プラグインの膨大なリストをここで紹介するのは敢えて避けたいと思います。 インストラクタの dotfiles をまず参照し (Anish, Jon, Jose) どんなプラグインを我々が使っているか見てみて下さい。 Vim Awesome では更に多くのプラグインを発見できます。 “best Vim plugins” で検索すれば、優れたプラグインについて多くの記事が見つかるはずです。
ソフトウェアにおける Vim モード
多くのツールが Vim のエミュレーションモードをサポートしています。 その質はツールによって様々ですが、 素晴らしい機能の全てとはいかないまでも基本的な機能は大抵網羅されています。
シェル
もし Bash を使っているならば、 set -o vi
を、Zsh
を使っているなら bindkey -v
を、
Fish
を使っているなら fish_vi_key_bindings
で vi モードを使用してみましょう。
加えて、どのシェルを使っていようとも、 export EDITOR=vim
を環境変数に設定しましょう。
これはあらゆるプログラムがエディタを呼び出す際に、どのエディタを使うかを定める環境変数です。
例えば、 git
はコミットメッセージを入力する際この環境変数で設定されているエディタをデフォルトで起動します。
Readline
多くのプログラムはコマンドラインインタフェースのためのライブラリ GNU
Readline
を使っています。Readline は基本的な vi キーバインドをサポートしています。
~/.inputrc
ファイルに以下の行を追加すると、vi モードを有効化できます。
set editing-mode vi
この設定を有効化すると、例えば Python の REPL も Vim キーバインドをサポートします。
その他
Web ブラウザ にも Vim のキーバインドをエミュレートする拡張機能があります。 有名なものでは Google Chrome 用の Vimium や Firefox 用の Tridactyl があります。 Jupyter notebooks でも Vim のキーバインドが提供されています。
発展的な Tips
このエディタの真価の一端をいくつか紹介します。 全てを教えつくすことはできませんが、Vim を使用するにつれ自然と他のテクニックについても習熟していくでしょう。 Vim での編集作業中、もっと良い方法があるのではという考えが頭をよぎったら、 必ずその方法は存在します。ネットで検索して常に最適な方法を模索する癖を付けましょう。
検索と置換
:s
(substitute) コマンド (documentation).
%s/foo/bar/g
- ドキュメント中全ての foo を bar に置換する
%s/\[.*\](\(.*\))/\1/g
- Markdown のリンクテキストをリンク内の URL に置換する
複数ウィンドウ
:sp
/:vsp
ウィンドウを分割する- 同じバッファに対して複数のビューを持つこともできます。
マクロ
q{character}
レジスタ {character} へマクロのレコーディングを開始q
レコーディングを停止@{character}
レジスタ {character} の内容を実行する{number}@{character}
マクロを {number} 回繰り返す- マクロは再帰的にも実行される
- まず
q{character}q
でマクロをクリアする - マクロを記録し、
@{character}
でマクロを実行する(レコーディングが完了するまで何もしない)
- まず
- 例: xml を json にする (ファイル)
- “name” / “email” キーを持つオブジェクトの配列
- Python のプログラムを使うか?
- sed / 正規表現を使うか?
g/people/d
%s/<person>/{/g
%s/<name>\(.*\)<\/name>/"name": "\1",/g
- …
- Vim コマンド / マクロを使うか?
Gdd
,ggdd
最初と最後の行を削除する- 1 つの要素を整形するためのマクロをレジスタ
e
に登録する<name>
の行に移動qe^r"f>s": "<ESC>f<C"<ESC>q
<person>
を整形する<person>
の行に移動qpS{<ESC>j@eA,<ESC>j@ejS},<ESC>q
<person>
を整形し次の<person>
へ移動<person>
の行に移動qq@pjq
- マクロを最終行まで実行する
999@q
- 手動で最後の
,
を消去し、[
]
で全要素を囲う
参考
vimtutor
はVimと共にインストールされるチュートリアルです。もしVimが既にインストールされている環境ならば、シェルでvimtutor
を実行することができます。- Vim Adventures は Vim を学ぶことができるゲームです。
- Vim Tips Wiki
- Vim Advent Calendar では様々な Vim Tips が紹介されています。
- Vim Golf は Vimのコードゴルフ場です。
- Vi/Vim Stack Exchange
- Vim Screencasts
- Practical Vim (book)
演習
vimtutor
を完了させましょう。80x24 (80 columns by 24 lines) のターミナルで行うのが良いでしょう。- 基本の vimrc を
~/.vimrc
に保存し、コメント含めファイル全体を(Vim を使って)読み、設定ファイルによって Vim の挙動がどのように変化するかを確認して下さい。 - プラグインのインストール、設定を行いましょう。
- プラグインのディレクトリを作成
mkdir -p ~/.vim/pack/vendor/start
- プラグインのダウンロード
cd ~/.vim/pack/vendor/start; gitclone https://github.com/ctrlpvim/ctrlp.vim
- プラグインのドキュメント
を読みます。まず CtrlP を使ってファイルを見つけてみましょう。プロジェクトディレクトリに移動し、Vimを開いて
:CtrlP
を入力します。 - configuration を参考に、
~/.vimrc
へ設定を追加してみましょう。Ctrl-P
で CtrlP を開けるようにします。
- プラグインのディレクトリを作成
- Demo をあなたのマシンで復習しましょう。
- 次の月から全てのテキスト編集にVimを使います。何かが非行率または “もっと良い方法があるはずだ” と感じる度にベストな方法を検索する癖を付けましょう。
- 他のツールを Vim のキーバインディングを使用するように設定してみましょう。
~/.vimrc
を更にカスタマイズしましょう。好みのプラグインを入れてみてもいいでしょう。- (発展)XMLをJSON(example file)に Vim マクロを使って変換してみましょう。躓いたら、マクロ のセクションがヒントになるはずです。
Licensed under CC BY-NC-SA.