Vimの思想についてZennconvers39🧘‍♂️Vimの思想について2023/10/29に公開2024/01/17VimNeovimtechはじめに大きなタイトルにしてしまいましたが、自分がVimを使ってきて思った、その背後にある哲学を、Vimの「Zen」としてをまとめました。Vimというタイトルで、こちらにシンプルなバージョンをアップしていますが、少し展開して書いてみたいと思います。memorize.Vimは、構成的(composable)な言語を使っているテキストの構造をテキストオブジェクトとして理解しているVimの多種多様なコマンドを駆使して素早くナビゲートしたり変更したりするのが、Vimmerにとって一番気持ちいいところかもしれません。これによって「効率的に」仕事ができるし、格好づけにも最適です。その根底にあるのは、Vimの多くのコマンドは、英語のプレーズの略語となっています。この表現のシンタックスが宣言的なもので、ほとんど我々が喋る言葉のままです。objects)となっています。belowこのパターンは理解しやすく、拡張もしやすい。実際に、多くのプラグインもこのパターンに沿って実装されています。このパターンを理解するために、まずOperator(演算子)、とテキストオブジェクトは避けられません。Operatorよく使われる演算子を羅列します。operatorで確認できます。cabの違いで、テキストオブジェクトの内部(inner)だけか、境界線も含めるか(around)があります。wayに慣れればプラグインもすぐに使い慣れるのがここにあります。演算子は主に、テキストの編集に使われますが、編集先を素早く見つけるために、移動(motion)の方法も非常に豊富です。patternといった使い方ができるのです。テキストオブジェクトこの概念は非常に大事で、Vimを接し始めた頃に知っておけばよかった概念のトップ1です。blockといった基本的なユニットから構成されています。これも人間にとって、テキストをうまく整理するために違う粒度の単位があるとかなり好都合なものです。<h1></h1>といったHTML/XMLのタグ上記のVimデフォルトのテキストオブジェクトだけでなく、カスタムテキストオブジェクトを作ることができるので、さらに可能性が広がります。neovim0.9から、treesitterとの言語解析のプラグインをマージしましたが、treesitterの力を借りて言語別のテキストオブジェクトが使えるようになります(プラグイン)。functionで、関数のテキストオブジェクトを単位に編集可能になります。twice全ての編集は繰り返し可能。ここで主に2つの考え方があります。ドットコマンド.を押すことで、最後に行った編集操作を繰り返すことができます。.を行うと、diwの操作を2回以上押さなくて良いのです。....で良いでしょう(もちろん、フォーマッターを使うのが最もですが)。マクロドットは最後に行ったコマンドしか記録しないのですが、より複雑な操作を行う場合、マクロを使うのが良いでしょう。マクロはVimのレジスター(register、詳細は次節)に任意のキーストロークの連続をレコーディングしてくれます。qを押すとレジスターを選ぶようになり、次にa-zとかのキャラクターを入れると、該当レジスターにコマンドを記録することができます。一度qを押すとレコーディング終了です。複雑な操作をレコードする最中でよく間違いをしてしまいます。一つのtipsとして、コマンド自体をまずテキストとして記録し、それが思う通りの操作になるか検証をしてみます。次に使いたいレジスターに、テキストをコピペすれば、次回は@qとかで呼び出すことができるのです。マクロ版のドットコマンドとして、@@では最後に実行されたマクロを実行してくれるのです。traveller.全ての編集は繰り返し可能だけではなく、取り消しもできるのです。実際に使うのは、主にuでundoをし、逆にundoをやめたい場合はctrl+rでredoを行います。時間旅行ができるのは、それなりの理由があります。Vimは、そのための情報を色々と覚えてくれています。レジスターVimには10種類のレジスターがあります。:registersで現在のレジスターの中身を確認できます。呼び出すには"<register>を使います。次のリストは全部"から始まります。こちらはd,c,s,x,yといったオペレータの対象テキストが生まれます。クリップボードには近いものです。VimのクリップボードをOSと共通するためによくこれを利用します。この辺りは、y(copy)とdの中身が保存されます。0はコピー、1-9は削除です。実際にレジスターに何かを記録させる(例えばマクロ)時に基本こちらのレジスターを利用します。ドットは先ほどのドットコマンドです。registers)。こちらはほぼ使うことがなく、ファイルの間を切り替えする際に、現在のファイルの一個前に開いたファイルのパスが保存されているようです。こちらはテキストを保存するよりも、入力された内容(expression)を評価してその実行結果をペーストすることです。Insertモードでctrl+=を押して、次にsystem('ls')を実行すると、その結果が挿入されます。unnamedレジスターをクリップボードとして使うと、Vimでコピーされた(yに限らず、"に保存された)テキストはOSのクリップボードにも現れます。逆のパターンとして、他のプログラム、例えばブラウザーで何かをコピーした時、こちらのレジスターにほぞんされるのです。OS->Vimもクリップボード("レジスター)を使いたい場合、unnamedplusに設定する必要があるのです。何も保存されないレジスター。削除されたテキストは通常1,2,3に保存されますが、痕跡を残さない方法はこれを使うのです(実際使ったこと全くないが)。パターン検索する時のパターンを保存してくれます。マークレジスターは様々な情報を保持してくれます。それに対して、マークは言葉通り、bookmark的にカーサーの場所を記録してくれるのです。:marksで現在のマークを確認できます。呼び出すには'<mark>もしくは`<mark>を使います。区別というと、'の場合では、カーサーの位置した行の一個目の文字にマークをつけるが、`の場合では、行だけではなく列まで精確にマークする。移動と編集の履歴これらの履歴は、先ほどのレジスターである程度情報を取れるものの、レジスターの目的は別にあります。移動と編集の履歴はスタックの形で、jumplistとchangelistに保存されています。jumplistはカーサーのいた場所を覚えてくれています。ctrl+i/oで新しい・古い順でジャンプできます。最後の居場所(stack.peekのような)と現在のカーサーを``で素早く行き来できます(''は同様、マークと同じ区別)。changelistは、jumplistと結構近く、要するに変更を行った場所を記録してくれるのです。g,とg;で新しい・古い順でジャンプできます。こちらは:changesで確認できます。listというのがありますが、ファイル間ではなく、現在のバッファのみを対象にしています。基本的にqflistで全てのニーズに満たすはずなので、loclistをほとんど使わずに済むかと思います。qflistの本来の目的は、名前通り、ファイル間のエラー情報を集めて、リストアップしてすぐにエラーの場所に辿り着いてフィックスするためのものです(いわゆるedit/compile/fixサイクル)。Vimではもちろんエラーだけではなく(trouble.nvimというプラグインが強力)、何かを検索してそのマッチする結果をリストとしてまとめるより汎用的な機能となっています。qflistにリストされているエントリーに対して、全てのエントリー所在のバッファーに対してコマンドを実行することが可能です。全てのエントリーに対してコマンド実行。%s/<target>/<new>)とか。上記と近いのですが、fはファイルという意味で、エントリーより粒度が大きくなります。このように、本来のアイディアとなるedit/compile/fixというサイクルよりも、qflistは、search/index/motion&editとのサイクルになるのです。Execute.何が自然なのかかなり主観的な部分かもしれません。terminalといったモードの切り替えと、それぞれのモードにおける違う動作パターンを持つことが強調されています。ノーマルモードのおかげで、移動と編集が非常にやりやすくなりました。モードの切り替えは、Vimの特徴的な部分としてあまり見過ぎない方が良いのではないかと考えています。いうのは、開発者にとってほとんどの時間はコードを書いているよりも、何かを読んでいるのです。Codeで言われているように、1:10の比例になっているらしい。この長い読みの流れの中で、「たまたま」何か変更を行います。ノーマルモードは、この「読みモード」と称するべきで、むしろ開発者の動きにとって自然なもので、逆にいつまでもinsertとの「書きモード」にしか存在できない一般的なテキストエディターのほうが不自然です。このコーディングの流れを、移動->編集(undo,redo含め)->移動とのサイクルに集約できます。insertモードに入らなくても、1で示したように、normalモードで編集できます。normalモードにおいての、効率の良い各種の検索と移動手段が、編集というたまたま発生する行為とよりスムーズに連携できるようになっているのです。insertモードは、どちらかと言うと、normalモードで完成できない動きを補完しているとも言えます。smellと主張していました。visualモードに入っているのであれば、よりVimらしい解決方があるのでは?、との匂いです。この観点について半分賛成です。Visualモードは名前通り、見ているものからセレクトしているので、1で言及しているテキストオブジェクトを利用することが難しくなります。2つ全く違う視点、客観的と主観的、表面的と意味的となるのです。word)して、pをやっていました。wayではなく、繰り返しができないのです。word)となり、次の箇所で.でリピートするのです(siwはプラグイン必要)。反対する半分というのは、Visualモードというか、マルチカーサーを使う時があるのです。これは、意味(テキストオブジェクト・パターン)に対して関心を持たない時の選択肢です。どの単語か関係なく、とりあえず次の10行に括弧をつけて、最後にコンマをつけたいといった、繰り返しの動きを、マルチカーサーを介して1回で終わらせる場面です。ほとんどの場合はパターンマッチや、ドットやマクロで対処できるのだが、そこの考え方と好き嫌いはあるので、自分はマルチカーサーという「Vimらしくない」やり方に肩を入れたいのです。いずれにしても、Vimの誇らしさ、強み、特徴というのは、モードにあるわけではないと考えています。モードの切り替えは、Vimの考え方を発揮させるための土台にすぎません。Vimの考え方に慣れると、モードも自然に忘れるだろう。extensibleなエディターです。Vimのマインドセット、考え方を学び、其の後はいかに自分が気持ちよく、効率よく使えるか、設定をいじりまくればよいです。NvChadといったpreconfigされたものをスタート地点とするのがおすすめです。プラグインの更新などをあまり頻繁にやらない方が良いのです。こちらの記事のように、いつの間にかプラグイン無限地獄に陥る可能性があり、結局時間を多く使ってしまい、諦めることもあり得ます。自分は現在、NvChadを使っているのですが、割と安定しているので、基本月単位で設定を更新しているのです。Environmentを構築し続けるのが、Vimmerのロマンだと考えています。終わりに自分が開発を学び始めた頃、初めてVimを触った時、案の定ファイルから出られない問題で頭を抱えました。当時はVimとは何かすらわからず、シェルのデフォルトエディターとして無理やり使わせられたのです。その後、知り合いの勧めでVimというハードモードを選んでみました。pluginを使ったり、Vimをセットアップして何回も失敗してVSCodeに戻ったり、最終的にVim/NVimのDistroを使って、SpaceVim,AstroNvimを経て、NvChadに辿り着きました[1]。Vimを使い続けてくるのか、今振り替えてみると2つあるかと思います。Vimは移動と編集の操作を簡潔かつ効率よく言葉で伝えるのです。これは自分の考えの延長として、認知的負荷がないほど体に覚えられています。Vimを学ぶ道には終わりがないところ。常に前に進められる感覚が、何よりです。おすすめの読み物この記事を作成する際には色々と記事と本を参考にしました。その中で特におすすめしたいものをリストアップしました。こちらの記事を読んで、かなり共感できる気がしました。vimの学ぶステージをignorance->curiosity->denial->embrace->enlightmentとまとめられています。自分も学ぶ経験とも結構被るところが多かったです。Learnerバッジを贈って著者を応援しようバッジを受け取った著者にはZennから現金やAmazonギフトカードが還元されます。Proよくある質問LinksX(Twitter)GitHubメディアキットLegal利用規約プライバシーポリシ。