VimキーバインドまとめとAtom, Jupyter, ChromeにおけるVimキーバインド



テキストエディタVimの効率的なキーバインドは、他のテキストエディタやJupyter、Webブラウザといったさまざまな環境で使えます。つまり、Vim自体を使わなくても、Vimキーバインドを学ぶことで作業を効率化できます。

この記事では、まずVimのキーバインドについてまとめます。そして具体的に、

- テキストエディタAtom
- インタラクティブコーディング環境Jupyter NotebookおよびJupyter Lab
- WebブラウザChrome

におけるVimキーバインドについて見ていきます。各内容は独立しているので、興味があるところだけお読み下さい。

※以下で出てくる`<C-{key}>`, `<S-{key}>`, `<A-{key}>`という表記は、それぞれCtrl+key, Shift+key, Alt+keyのことです。例えば、`<C-r>`はCtrl+rのことです。

**目次**

- [Vimについて](https://qiita.com/nakasan/items/ec7741f075f1062350f4#vim%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
- [Vimキーバインドまとめ](https://qiita.com/nakasan/items/ec7741f075f1062350f4#vim%E3%82%AD%E3%83%BC%E3%83%90%E3%82%A4%E3%83%B3%E3%83%89%E3%81%BE%E3%81%A8%E3%82%81)
- [AtomにおけるVimキーバインド](https://qiita.com/nakasan/items/ec7741f075f1062350f4#atom%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8Bvim%E3%82%AD%E3%83%BC%E3%83%90%E3%82%A4%E3%83%B3%E3%83%89)（vim-mode-plus, ex-mode）
- [JupyterにおけるVimキーバインド](https://qiita.com/nakasan/items/ec7741f075f1062350f4#jupyter%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8Bvim%E3%82%AD%E3%83%BC%E3%83%90%E3%82%A4%E3%83%B3%E3%83%89)（jupyter-vim-binding, jupyterlab_vim）
- [ChromeにおけるVimキーバインド](https://qiita.com/nakasan/items/ec7741f075f1062350f4#chrome%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8Bvim%E3%82%AD%E3%83%BC%E3%83%90%E3%82%A4%E3%83%B3%E3%83%89)（Vimium）
- [Vimにまつわる諸問題](https://qiita.com/nakasan/items/ec7741f075f1062350f4#vim%E3%81%AB%E3%81%BE%E3%81%A4%E3%82%8F%E3%82%8B%E8%AB%B8%E5%95%8F%E9%A1%8C)（IME切替だるい問題、Escキー遠すぎ問題）

**参考文献**

- [help - Vim日本語ドキュメント](http://vim-jp.org/vimdoc-ja/)

---

# **Vimについて**
### **テキストエディタ概観**
テキストをよく編集する人たちにとって、テキストエディタ選びは作業の生産性を大きく左右する重要なファクターだ。世の中には色んなテキストエディタがある。手軽に使える有名どころとしては、TeraPad、サクラエディタ、秀丸エディタ、Notepad++、miなどがある。一方で、テキスト編集作業の概念をうまく抽象化して構造化することによって、慣れるのに時間がかかるものの、とても効率的に複雑な作業ができるエディタがある。それがEmacsとVimだ。どちらにも熱烈な愛好者たちがいて、とくに狂信的な愛好者たちはエディタ戦争と呼ばれる宗教戦争に日々馳せ参じている。

- Emacs上で作られ、Vimのキーバインドを使えるようにしたりとEmacsを色々改良したSpacemacs (2014) というエディタも良さそう
（参考：[spacemacsについて \~\~spacemacsが最強で最高で神エディタであると思い始めた件\~\~](https://qiita.com/nobkz/items/994c6b3e6f42a0e33fef)）

- Vimをリファクタリングして改良しているNeovim (2014) というエディタもある。例えば、Vimの中でシェルを起動するターミナルモードなどが追加されている。現在進行形のプロジェクトだ

- 現代的なエディタとしては、Sublime Text (2008), GitHub社のAtom (2014), Microsoft社のVisual Studio Code (2015) などがある

- 大規模なソフトウェア開発においては、テキストエディタよりもIDE（Integrated Development Environment, 統合開発環境）を使うほうが良いと思う。IDEとしては、JetBrains社のものや、Eclipse、Visual Studioなどがよく知られている。PythonではPyCharmが人気だ


### **Vimの特徴**
Vimの特徴としては、モードの概念、コマンドの構造化、独自のスクリプト言語による高度なカスタマイズ、が挙げられると思う。

**モードの概念**
ただの文字入力じゃない高度な操作をする命令（コマンド）の入力は、何らかの方法で通常の文字入力と区別する必要がある。多くのテキストエディタでは、CtrlやAlt, Shiftといった装飾キーと同時に文字キーを押すことでコマンドを入力して、文字入力と区別している。一方Vimでは、モードと呼ばれる状態の概念を導入して、今どのモードにいるかによって文字入力とコマンド入力を切り替える方式を採っている。（ロラン・バルトが言うモードとはたぶん関係ない。）

**コマンドの構造化**
また、Vimではコマンドはうまく構造化されていて、コマンドを部品として組み合わせて複雑なコマンドを作れる。例えば、作用内容と作用対象の概念は分離されていて、動詞+目的語のような文法構造を取っている。他にも、自然数でコマンドを定数倍したりできる。

このモードの概念とコマンドの構造化はとても強力なので、Vimのキーバインドは元の実装を離れて、さまざまな環境において有志達の手によって実装されている（感謝！）。

**スクリプト言語によるカスタマイズ**
`~/.vimrc`ファイルにVim script（VimLともいう。LはLanguageの略）と呼ばれる独自のスクリプト言語で詳細設定を書いてカスタマイズする機能もVimの大きな特徴だ。Vimの熟練者達はみな、自分だけの最強のvimrcファイルを育てているらしい。けれどVim以外の環境ではさすがにそこまでは実装されてないので、この記事ではあまり立ち入らないことにする。


### **Vimの学習方法**
**vimtutor**
何も知らない状態からは、まずvimtutorというチュートリアルを一通りやるのが一番よいと思う。日本語化もされてる。

- vimが入っていれば、Unixシェルで`vimtutor`と打てば起動する。windowsだとどこか探せば出てくる

**Vimチートシート**
世の中にいろいろあるVimチートシートなどを眺めてみるのも参考になる。

- [Vim日本語チートシート作った](https://qiita.com/zipper/items/8fbed306e203b17be0c3)
- [Vim Cheat Sheet](https://vim.rtorr.com/lang/ja/)
- [Vim モーション譜](https://qiita.com/kumazo/items/9d334256694c6253944a)

**実践Vim**
[実践Vim](https://www.amazon.co.jp/dp/B00HWLJI3U/)という本もよく薦められていて、Vimの本と言えばこれ、といった感じだ。こういう使い方ができるのか！と、とても参考になる。とくに、`.`（直前の変更を繰り返す）コマンドの威力を思い知ることになる。詳しすぎるので、全部読む必要はないと思う。


# **Vimキーバインドまとめ**
### **モードの変更**
**ノーマルモード**
キーの入力でコマンドを実行する。名前の通り、基本的にこのモードに居ることになる。

- `<Esc>` ノーマルモードに戻る

**インサートモード**
カーソルが文字と文字の間にあり、キーの入力でそこに文字を挿入していく。

- `i` カーソルの直前でインサートモードに入る (Insert)
    + `I` 行頭でインサートモードに入る。`^i`と同じ
- `a` カーソルの直後でインサートモードに入る (Append)
    + `A` 行末でインサートモードに入る。`$a`と同じ
- `o` 下に空行を追加してインサートモードに入る (Open line)。`A<Enter>`と同じ
    + `O` 上に空行を追加してインサートモードに入る。`ko`と同じ

**置換モード**
キーの入力で既にある文字を置き換えていく。

- `R` 置換モードに入る (Replace)

**ビジュアルモード**
文字列の範囲指定をする。範囲指定の始端は固定されてて、終端をカーソルで動かす。

- `v` ビジュアルモードに入る (Visual)
    + `V` 行を選択できるビジュアルモードに入る
    + `<C-v>` 矩形を選択できるビジュアルモードに入る
    + モーション（後述）で移動したり、オペレータ（後述）に渡したり、テキストオブジェクト（後述）で範囲指定できる
    + `o` 始端と終端を入れ替える。始端を変えたいときに使う


**コマンドラインモード**
Exコマンドという特殊なコマンドを実行する。

- `:` コマンドラインモードに入る
- `/{string}` コマンドラインモードに入り、文字列stringを前方検索。後方検索するには、`?{string}`
    + `n`で次のヒットへ、`N`で前のヒットへ移動 (Next)

### **モーション**
モーションは文字の位置を表す。モーションコマンドを単独で入力すると、単にカーソルをその位置に移動する。

**1文字**

- `h` 左、`j` 下、`k` 上、`l` 右
    + ホームポジションを崩さずに、右手で完結するのがウリ

行が長文になって画面端で折り返しはじめると、ディスプレイの表示で何行目か（表示行、物理行）と、行番号で何行目か（論理行）、の概念が違ってくる。`j`, `k`は論理行を上下する。表示行を上下するには、`gj`, `gk`を使う。


**単語**

- `w` 前方で最寄りの、単語の先頭 (Word)
    + `e` 前方で最寄りの、単語の末尾 (End of word)
- `b` 後方で最寄りの、単語の先頭 (Backward)
    + `ge` 後方で最寄りの、単語の末尾

空白だけじゃなく、`.`や`-`, `)`といった記号類も単語の区切りと解釈している。空白だけ単語の区切りと解釈するには、大文字にした`W`, `E`, `B`, `gE`を使う。もっと速く動ける。

**行**

- `0` 今居る行の先頭
    + 空白を無視するには`^`あるいは`_`
- `$` 今居る行の末尾
    + `{N}$` N-1行下の行末
- `-` 上の行の先頭
- `+`, `<Enter>` 下の行の先頭
- `f{char}` 右で最寄りの、文字charの位置 (Find)
    + `F{char}` 左で最寄りの、文字charの位置
- `t{char}` 右で最寄りの、文字charの位置の1個前 (To)
    + `T{char}` 左で最寄りの、文字charの位置の1個前

いずれも、検索を繰り返すには`;`、逆方向に繰り返すには`,`を使う。

**より大きな単位**

- `}` 下の段落との境界
    + `{` 上の段落との境界
- `)` 下で最寄りの、段落の先頭
    + `(` 上で最寄りの、段落の先頭
- `gg`, `G` ファイルの先頭、末尾
    + `{N}gg`, `{N}G` ファイルのN行目

**画面**

- `H`, `M`, `L` 画面表示の上部 (Home)、中部 (Middle)、下部 (Last)

**その他**

- `*` 前方で最寄りの、今居る単語と同じ単語の先頭
    + `#` 後方で最寄りの、今居る単語と同じ単語の先頭
- `%` 対応する括弧の位置


### **オペレータ**
オペレータは作用対象を引数に取って、その対象に対して作用する。作用可能な対象としては、モーション、テキストオブジェクト、ヴィジュアルモードでの選択範囲、がある。

- `{operator}{motion}`の形で、今居る位置とモーションの間の文字列に作用する
    + `{motion1}{operator}{motion2}`とすれば、まずmotion1に移動してからオペレータがmotion2までの範囲に作用するので、motion1からmotion2までの範囲に作用できる。例: `ggyG`で全てコピー
- `{operator}{text-obj}`の形で、テキストオブジェクト（後述）に作用する
- ヴィジュアルモードでオペレータコマンドを入力することで、選択された範囲に対して作用する

**オペレータコマンド**

- `d` 削除 (Delete)
- `c` 変更 (Change)。対象を削除してインサートモードに入る
- `y` ヤンク (Yank)
    + コピーのこと。CopyのCはChangeに取られていたので、コピーと言わずにヤンクと言うことになった
- `>`, `<` 右にシフト、左にシフト
- `gu` 小文字にする
    + `gU` 大文字にする (Uppercase?)

**2回連打**
同じオペレータを2回連打することで、今居る行全体を作用対象にする。

- `dd` 今居る行を削除
- `yy` 今居る行をヤンク
- `>>`, `<<` 今居る行を右にシフト、左にシフト
- `guu` 今居る行を小文字にする
    + `gUU` 今居る行を大文字にする
    + `gugu`, `gUgU`でもよいけど打ちづらい

**大文字**
オペレータを大文字にすることで、行末までを対象にする。

- `D` 行末まで削除。`d$`と同じ
- `C` 行末まで変更。`c$`と同じ
- `Y` はなぜか行末までではなく、今居る行をヤンクする。`yy`と同じ
    + vimの先祖であるviとの互換性のために仕方なくこうなってるらしい

**ショートカット**

- `x` 今居る文字を削除。`dl`と同じ
    + `X` 今居る文字の左を削除。`dh`と同じ
- `s` 今居る文字を変更。`cl`と同じ
    + `S` 今居る行を変更。`cc`と同じ

**直前にヤンクや削除した内容の貼り付け**

- `p` 右に貼り付ける。内容が行単位の場合は下に貼り付ける (Put)
    + `P` 左に貼り付ける。内容が行単位の場合は上に貼り付ける


### **テキストオブジェクト**
オペレータの作用対象として使う。`a{char}`の形で、ある範囲を表す（冠詞のa）。`i{char}`の形で、ある範囲の内側を表す (Inner)。charとして可能なもの：

+ `w` 今居る単語。`a`では末尾の空白も含む
    + 例えば`daw`で今居る単語を消去
+ `s` 今居る文 (Sentence)。 `a`では直前の空白も含む
+ `p` 今居る段落 (Paragraph)。`a`では下の空行も含む
+ 括弧`(`, `[`, `{`, `<`や引用符`'`, `"`, `` ` `` それらで囲まれた今居る範囲。`a`ではそれら囲む記号も含む
    + `b`は`(`, `B`は`{`と同じ (Block)。例えば`cib`で今居る`()`の中身を変更

### **カウント**
[count]{command}でcommandをcount倍できる。例：

- `3j` 3行下に移動
- `3<Enter>` 3行下の先頭に移動
- `3dd` 3行消去
- `3p` 同じ内容を3回ペースト
- `3i{string}<Esc>` 文字列stringを3回挿入

例えば、3単語消去は`3dw`とも`d3w`とも書ける。`3d5w`ってやると3*5=15単語消える

### **直前の変更に対する操作**
- `.` 直前の変更を繰り返す
- `u` 直前の変更を取り消す (Undo)
- `<C-r>` 直前の取り消された変更をやり直す (Redo)


### **その他**
- `r{char}` 今居る文字を別の文字charに置換 (Replace)
- `J` 今居る行と下の行を結合 (Join)
    + 間に空白を挟まないようにするには、`gJ`
- `~` 今居る文字の大文字と小文字を入れ替えて右に進む

### **コマンドラインモード**
`:`によって入れるコマンドラインモードでは、Exコマンドと呼ばれるコマンドを実行できる。Exコマンドを打ち終えるには`<Enter>`が必要。

- `w` 上書き保存 (Write)
    + `w {filename}` 別名で保存
- `q!` 変更を破棄して修了 (Quit)
    + 末尾の`!`は強制の意味。`q`だと変更を保存してないと怒られる
- `wq` 変更を保存して終了
- `!{command}` shellコマンドを実行する
- `r {}` 挿入する
    + {filename} ファイルの中身を挿入する
    + !{command} shellコマンドの出力を挿入する
- `s/{string1}/{string2}` 最寄りのstring1をstring2に置換 (Substitute)
    + 最後に`/g`を付けると、その行全体で置換 (Global)
    + 最後に`/gc`を付けると、1つ1つ確認を取りながら変更する (Confirm?)
    + `{num1},{num2}s/` num1行目からnum2行目の範囲で置換
    + `%s/` ファイル全体で置換


# **AtomにおけるVimキーバインド**

### **Atomについて**

Atomは、2014年にGitHub社によってリリースされた現代的なテキストエディタだ。特徴を挙げると、

- 優れたデザイン、使いやすいGUI
- 管理が楽で豊富なパッケージ
- Gitとの連携機能
- ファイル・フォルダのツリービュー
- 動作が重い、メモリ食う、サイズが大きいファイルは苦手。（徐々に改善している）

テキストエディタに標準的にあるとうれしい機能もちゃんとある。

- ペイン分割（画面分割）
- タブ切り替え
- コードの折りたたみ
- シンタックスハイライト
- 自動で括弧や引用符を閉じる

マークダウンエディタとしても優秀だ。マークダウンファイルを編集中に`<C-M>`(Ctrl+Shift+m)と打てば、画面分割してレンダリング結果を同時にリアルタイムに表示してくれる。
Qiitaに記事を投稿するときにブラウザ上に現れるマークダウンエディタと比べても、

- markdownもシンタックスハイライトされる
- レンダリング結果の同期が速い（Qiitaだと長文になるとすぐ同期しない）
- 豊富なパッケージが使える

などの点で優れている。この記事もAtomでできている。

Atom上でJupyterを動かすHydrogenっていうパッケージもあるそうだ。すごい。命名の由来も面白くて、木星（Jupiter）の体積の90%が水素ガスだからだそうだ（そのガスはhydrogen atomじゃなくてhydrogen moleculeだけども）

- 星間ガスなら、水素分子だけでなく水素原子や水素イオンとしても存在する

### **vim-mode-plusパッケージ、ex-modeパッケージ**
AtomでVimのキーバインドを実装しているパッケージが、vim-mode-plusパッケージだ。Atomでパッケージを入れるのは簡単で、環境設定->インストール、でパッケージ名を打って検索するだけだ。

- パッケージ開発の経緯については、作者@t9mdさんのQiitaの記事「[2015年、Atom に乗り換えた。そして vim-mode-plus をリリースした。](https://qiita.com/t9md/items/17754b3383932aa8e782)」に書いてある。大変な苦労を窺い知ることができる。開発して頂いて、本当にありがとうございます！

Vimのキーバインドが驚くほどしっかりと再現されていて、この記事で挙げたようなコマンドならほぼ全て使える。

コマンドラインモードを使うには、さらにex-modeというパッケージを入れる。実装されているExコマンドの一覧については、https://github.com/lloeki/ex-mode/wiki/CommandsAvailable で確認できる。

- 名前が紛らわしいけど、歴史的事情によって存在するvim-mode、vim-mode-plus-ex-modeパッケージは非推奨



# **JupyterにおけるVimキーバインド**

### **Jupyter Notebook, Jupyter Lab**
Jupyter Notebookはコードやマークダウンや数式、グラフといった画像や動画からなるノートブックを作成、共有できるWebアプリケーションだ。ノートブックはそれ自体がインタラクティブなコーディング環境で、40種類以上の言語をサポートしている。

- `pip install jupyter`で入れられて、`jupyter notebook`で起動できる
     + Jupyter自身はさまざまな言語をサポートしているけれど、Pythonの環境が必要になる。Pythonの環境の構築方法については、著者別記事の「[[覚え書き] Pythonの環境構築について](https://qiita.com/nakasan/items/73c6d6546f9994c0083c)」を是非ご覧下さい
- 以前はIPython Notebookという名前だった。Python以外の言語も広くサポートするようになって、改名した。名前はプログラミング言語のJulia, Python, Rから取られている
- このインタラクティブなノートブックという概念は、Mathematicaノートブックからきている。ノートブックは、セルと呼ばれる構成単位を縦に並べることでできている
- ノートブックはファイルとして共有もできるし、簡単にWebページにもできる
- データ分析環境としてとても優れている

現在、Jupyter Notebookの次世代版としてJupyter Labが開発中で、アルファ版が公開されている。将来的にはNotebookはLabに移行するそうだ。

- `pip install jupyterlab`で入れられて、`jupyter lab`で起動できる
- 画面分割ができるようになった。ファイルブラウザ、ターミナル、csvファイル、ライブラリリファレンスなども同時に表示できる
- マークダウンのレンダリング結果もリアルタイムに同時に表示できる
- タブ切り替え機能もある

### **Vimキーバインド拡張機能**
**jupyter-vim-binding, jupyterlab_vim**
Jupyter Notebookの拡張機能はnbextensionという。Vimキーバインドを実装したnbextensionとして、jupyter-vim-bindingがある。

- その開発経緯については、作者lambdalisueさんのブログ記事「[Jupyter (旧 IPython notebook）の本来あるべき姿を垣間見る](http://lambdalisue.hatenablog.com/entry/2015/12/22/233817)」に詳しい
- CodeMirrorという、Web上でコードエディタを実現するJavaScriptライブラリのVimキーバインドを利用している
- nbextensionを入れるには、jupyter_contrib_nbextensionsパッケージが必要。`pip install jupyter_contrib_nbextensions`して`jupyter contrib nbextension install --user`すればよい
- さらにnbextensions_configuraterというextensionを入れておけば、jupyter notebook上にnbextensionタブが現れて、そっから各nbextensionのオン・オフが簡単にできるようになる。`pip install jupyter_nbextensions_configurator`して`jupyter nbextensions_configurator enable --user`とすればよい

しかし、その開発はほぼ停止してる。作者が転職してJupyter Notebookを使わなくなったらしく、Jupyter Labへ移行される可能性もほぼない。

- 参考：https://github.com/lambdalisue/jupyter-vim-binding/issues/114

一方、Jupyter Labにおける拡張機能はlabextensionという。Vimキーバインドを実装したlabextensionとして、jupyterlab_vimが開発中だ。開発中だけど、一応もう使える。

- `jupyter labextension install jupyterlab_vim`で多分入れられる。node.jsが入ってないと、`'NoneType' object has no attribute 'rfind'`とかいうわけの分からないエラーが出て失敗する（ひどい）
    + 参考：https://github.com/jupyterlab/jupyterlab/issues/1362
- jupyter-vim-bindingの水準を目指したいと作者が宣言してる

今は過渡期なので、どちらを使う選択肢もありえると思う。

**3つのモード**
Jupyterには元々２つのモード、コマンドモードとエディットモードがある。エディットモードはセル内のテキストを編集するモードで、セルを選択して`<Enter>`することで入れる。コマンドモードはセルを選択したりセルを制御するモードで、`<Esc>`で入れる。

Vim拡張機能を入れると、このモードが３つになる：

- Jupyterモード：　セルを制御する。拡張前でいうコマンドモードにあたる。`<S-Esc>`でこのモードに入れる。セルを選択して`<Enter>`や`i`を押すか、セルをダブルクリックするとコマンドモードへ移る
- Vimコマンドモード：　Vimコマンドが普通に使える。Vimでいうところのノーマルモード。Vimと同じく、`i`や`a`などでインサートモードへ移る
- Vimインサートモード：　文字を挿入できる。`<Esc>`でコマンドモードに戻る

Vimコマンドモードでも、`<C-o>`を押せばJupyterモードのコマンドが使えるようになっている。このおかげで、可能な限りJupyterモードに立ち入らずに、Vimコマンドモードで過ごすことができる。

とくに、Vimコマンドモードのままでも、次のコマンドでセルを移動できる：

- `<C-j>`, `<C-k>` 上下のセルに移動（Vimコマンドモードでは、`j`, `k`では普通にセル内を上下に移動する）

jupyter-vim-bindingではさらに、JupyterモードでのキーバインドまでVimライクになっている。一方、jupyterlab_vimでは拡張前のJupyterのコマンドモードでのショートカットキーと同じだ。なので、両方まとめておく。

### **Jupyterコマンドモードのショートカットキーまとめ**
**一般**

- `h` キーバインド一覧を表示するかどうかをトグル (Help)
- `f` 検索、置換 (Find)
- `s` ファイルを上書き保存 (Save)

**セルの移動**

- `j`, `k` セルの上下移動
    + `J`, `K` セルを複数選択しながら上下移動

**セルの実行**

- `<S-Enter>` セルを実行して下のセルへ移動
    + 末尾のセルなら下に空セルを作る
- `<C-Enter>` セルを実行するが下のセルに移動しない
- `<A-Enter>` セルを実行して下に空セルを作る

**セルの操作**

- `a` 上に空セルを作る (Above)
- `b` 下に空セルを作る (Below)
- `c` セルをコピー (Copy)
- `dd` セルを削除（クリップボードにコピーしない）
    - `x` セルをカット（クリップボードにコピーする）
    - `z` セルの削除、カットの取り消し
- `v` セルを下に貼り付け
    + `V` セルを上に貼り付け
- `m` セルをマークダウンセルへ変更 (Markdown)
- `y` セルをコードセルに変更
- `M` 下のセルと結合。複数選択の場合はそれらを結合 (Merge)

**画面表示**

- `l` 行番号を表示するかどうかをトグル (Line number)
    + `L` 全てのセルでトグル
- `o` セルの出力を表示するかどうかをトグル (Output)
    - `O` セルの長い出力をスクローリング表示するかどうかをトグル

**カーネル**

- `ii` カーネルを中断　(Interrupt)
- `00` カーネルを再起動



### **jupyter-vim-bindingでの変更点**
jupyter-vim-bindingのJupyterモードでは、上のショートカットキーの一部もVimライクに変更されている。

- `H` キーバインド一覧を表示するかどうかをトグル (Help)
- `gg` 先頭のセルへ移動
- `G` 末尾のセルへ移動
- `/` 検索、置換
- `yy` セルをコピー
- `dd` セルをカット（クリップボードにコピーする）
    + `u` セルの削除の取り消し
- `o` 下に空セルを作成
    + `O` 上に空セルを作成
- `p` セルを下に貼り付け
    + `P` セルを上に貼り付け





# **ChromeにおけるVimキーバインド**

### **WebブラウザにおけるVimキーバインド**

Webブラウジングはテキスト編集とはだいぶ違う作業なので、Vimキーバインドとはいってもさすがにエディタと同じようにはいかない。ただ、Vimのコマンドを知っていれば、意味にそれなりに納得できるようなキーバインドが世の中にある。

Chromeは言わずとしれたGoogle社のWebブラウザで、ブラウザ戦争の勝者だ。
ChromeでVimキーバインドを実装した拡張機能としては、Vimium, Vichrome, Vrome, cVimなどいくつかある。そのうち、圧倒的に人気なのがVimiumだ。

- [ChromeウェブストアのVimium公式サイト](https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb)からChromeに追加すれば入る

- Firefoxでは、VimperatorというアドオンがVimキーバインドを実装したものとしてとても優秀だったようだ。しかし、2017年11月にリリースされたFirefox QuantumでFirefoxの仕様が大きく変わってしまい、Vimperatorは動かなくなりサポートも停止した

Vimiumを使えば、マウスやトラックパッドを使わずに、キーボードだけでWebブラウジングができる。具体的に最も便利なのは、ページ内の好きなリンク先のページに飛べる`f`コマンドだと思う。`v`で入れるヴィジュアルモードもちゃんとあって、キーボードだけでWebページ上の文字列の範囲選択ができて、`y`でコピーしたり、`p`で内容を検索したりできる。`yy`で今居るページのURLをコピーするとかも地味に便利だ。

推奨する初期設定について3つ紹介してから、Vimiumのキーバインドについてまとめる。

### **Vimium推奨初期設定**

**デフォルトキーバインドの変更**
「[Chromeをvimライクに使えるようにするvimium](https://qiita.com/satoshi03/items/9fdfcd0e46e095ec68c1)」で紹介されているように、デフォルトのキーバインドは変えた方が使いやすい。アドレスバー右側に出現した丸Vマークを押して、Optionsを選び、Custom key mappingsの入力フォームに次を記入する。

```
map h goBack
map l goForward
map H previousTab
map L nextTab
map i LinkHints.activateMode
map I LinkHints.activateModeToOpenInNewTab
```

- デフォルトでは`h`, `l`は左右にスクロールに設定されているけれど、普段べつに使わないので、もっとよく使う「戻る」と「進む」に割り当てている
- デフォルトでは`H`と`L`が「戻る」と「進む」に割り当てられてるけれど、今や小文字でできるので、「左のタブに移動」「右のタブに移動」に割り当てなおしている。これは`J`, `K`と同じだけども
- `i`と`I`はほぼ何の働きもしてないので、`f`と`F`と同じくページ内のリンクを開く役割を割り当てている

**「次へ」のリンクをすぐ飛べるようにする**
`]]`や`[[`といったコマンドで`next`や`>`, `previous`や`<`といった名前のリンクを移動できる機能があるのだけど、日本語の名前も追加しておくと便利だ。

- 参考：[Chrome を Vim ライクにする Vimium を使うなら「戻る」「次へ」の設定はしといたほうが良い](https://hori-ryota.com/blog/vimium-pre-next-patterns-jp/)

同じくアドレスバー右側の丸Vマークを押して、Optionsの画面でShow Advanced Optionsボタンを押し、現れたPrevious patternsの入力フォームに「前へ」「戻る」「前のページ」を追加して次のようにする：

```
prev,previous,back,older,<,‹,←,«,≪,<<,前へ,戻る,前のページ
```

同じように、Next patternsの入力フォームに「次へ」「進む」「次のページ」を追加して次のようにする：

```
next,more,newer,>,›,→,»,≫,>>,次へ,進む,次のページ
```

これで例えば、`]]`, `[[`コマンドによってGoogleの検索結果の次のページ、前のページへ移動できるようになる。

**Vimiumを無効化するサイトを指定**
Jupyter NotebookやJupyter Labなど独自のキーバインドを持っているサイトでも、Vimiumのキーバインドが優先されてしまう。独自のキーバインドを使いたいサイトでは、キーバインドが衝突しないようにVimiumを無効化する。その無効化したいサイト上でアドレスバー右側の丸Vマークを押して、Save Changesボタンを押せばよい。

Optionsから無効化されたURLの一覧が見られる。例えばJupyter Notebookなら`https?://localhost:8888/*`, Jupyter Labなら`https?://localhost:8890/*`と入っている。



### **Vimiumキーバインドまとめ**

**ヘルプ**

- `?` キーバインドの一覧を表示する。困ったらこれを叩こう

**移動**

- `j`, `k` 画面を上下にスクロールする
- `h`, `l` 戻る、進む
- `J`, `H` 左のタブへ移動
- `K`, `L` 右のタブへ移動
- `g0`, `g$` 最初のタブ、最後のタブへ移動
- `gg` ページの先頭に移動
- `G` ページの末尾に移動
- `u`, `d` 半ページ上下にスクロールする
    + Vimでいう`<C-u>`, `<C-d>`を意識している (Up, Down)
    + もし使わないなら、Custom key mappingsに`map d removeTab`, `map u restoreTab`を追加して、今居るタブを閉じる（`x`と同じ。Delete）、閉じたタブを開く（`X`と同じ。Undo）として使うとよいと思う
    + 普段スペースキーでスクロールしている人は、さらに`j`, `k`を`J`, `K`と入れ替えるとよい。小文字の`h`, `j`, `k`, `l`だけで生きていけて、大文字の`H`, `J`, `K`, `L`を使わずに済む：

```
map d removeTab
map u restoreTab

map j previousTab
map k nextTab
map J scrollDown
map K scrollUp
```

**ページ内のリンクを開く**

- `f`, `i` ページ内のリンクに文字を割り振る。その文字を打つことでリンク先のページを開く
    + 新しいタブで開くには、文字を大文字で打つか、あるいは`F`, `I`を使う

**検索**

- `/{string}` 文字列stringを検索。`n`で次のヒット、`N`で前のヒットに移動

**ヤンク・貼り付け**

- `yy` 今居るタブのURLをクリップボードにコピー
- `yf` ページ内のリンクに文字を割り振り、その文字を打つことでリンク先のURLをクリップボードにコピー
- `yt` 今居るタブを複製
- `p` クリップボードのURLに移動。URLでなければその内容で検索
    + 新しいタブで開くには`P`

**ヴィジュアルモード**
`v`でヴィジュアルモードに入り、テキストの範囲指定ができる。

- 複数行を範囲指定するには、`V`を使う
- 選択範囲を動かすには、`h`, `j`, `k`, `l`だけでなく、`w`, `e`, `b`も使える
- 検索`/`などであらかじめ始端を指定していなかったら、ヴィジュアルモードには入らず、カーソルを動かして始端を指定するためのキャレットモードというモードに入る。始端を指定したら、`v`を押して改めてヴィジュアルモードに入る必要がある

**ヴィジュアルモードでできること**

- `y` 選択範囲をクリップボードにコピー
- `p` 選択範囲の内容で検索
    + 新しいタブで開くには`P`
- `o` 始端と終端の入れ替え
- `c` キャレットモードに入る。始端を指定したら、`v`でビジュアルモードに戻る


**ページを開く**

- `t` 新しいタブを開く (Tab)
    + `T` 開いているタブから検索して移動
- `o` ブックマークや履歴から検索してページを開いたり、URLを開いたり、何かを検索する
    + 新しいタブで開くには`O`
- `b` ブックマークから検索して開く (Bookmark)
    + 新しいタブで開くには`B`
- 複数現れる候補は、カーソルキーの上下あるいはTabとShift+Tabで上下できる


**その他**

- `r` ページを更新 (Reload)
- `x` 今居るタブを閉じる
    + `X` 閉じたタブを開く
- `gi` ページ内の入力フォームに移動
    + `{num}gi`でnum番目の入力フォームに移動
- `<<`, `>>` タブの順序を左右と入れ替える
- `W` 今居るタブを新しいウィンドウで開く (Window)

カウント機能もサポートしている。例えば、`3x`でタブを3つ閉じる。



# **Vimにまつわる諸問題**

### **IME切替だるい問題**
Vimでは、ノーマルモードとインサートモードの間を頻繁に行き来することが想定されている。しかし、日本語の文章を書くためには、インサートモードに入ったら毎回日本語IMEに切り替え、インサートモードを出る度に毎回日本語IMEを切る必要がある。これだと頻繁に行き来するのがだいぶだるい。日本語でコマンドを打ってしまうというミスを、誰しもがやらかす。

そこで、インサートモードを出るときに自動的に日本語IMEを切る方法が幾つか提案されている。

- KaoriYaさんのMacVimやGVimを使っている場合、vimrcファイルに`set imdisable`と書く
- Google日本語入力を使えば、Escキーを押すとIMEを切るよう設定できる
    + 参考: [SSHを介してVimを使う人に感動的なESCキーを押すとESCキーが効きつつIMEがオフになる設定(Google日本語入力とVimの相性は最強！)](http://d.hatena.ne.jp/sifue/20120411/1334161078)
- macOSなら、キーバインド用アプリKarabinerを使って何とかできる
    + 参考: [Vimを使う上でのIME(日本語入力)の取り扱い]( https://rcmdnk.com/blog/2013/06/20/computer-mac-keyremap4macbook-vim/)、<a href="http://dackdive.hateblo.jp/entry/2015/09/04/094644" title="タイトル">vimでEsc(またはCtrl+[)キーを押した時に自動的に日本語入力モードを解除する</a>
    + macOS Sierra以降はKarabinerが動かなくなったので、代わりにKarabiner-Elementsを使う
    + Windowsでも、AutoHotKeyというキーマップ変更ツールでできるとか

他にも、1文字置換`r{char}`や該当文字への移動`f{char}`が日本語文字では失敗するとか、全角括弧を他の括弧類と同じようにうまく扱えないとか、日本語文章には細々といろんな問題がある。検索すればこういった問題を何とかするVim用のプラグインが色々出てくるけれど、Vim以外の環境でVimキーバインドを使っている場合、どうして良いかはちょっと分からない。


### **Escキー遠すぎ問題**
Vimでは、ノーマルモードに戻るためにEscキーを頻繁に使うことが想定されている。しかし、Escキーはキーボードの左上端、1キーの上、より悪いことにさらに上のF1キーの上にあることすらある。キーの大きさもなんか小さかったりする。明らかにあんまり頻繁に打ちたいキーではない。

- 遙か昔々、vimの先祖のviが開発された頃、Escキーは今で言うTabキーの位置、Qキーの左にあった。当時は気軽に打てたのだろう

**解決策１： `<Esc>`と同じ意味の`<C-[>`を代わりに使う**

- JIS配列のキーボードでは`[`もあまり打ちやすいキーとは言えないものの（US配列だともう1キーぶん近い）、それに目をつぶれば万能ではある

**解決策２： がんばって別の何かを`<Esc>`に割り当てる。`<C-j>`や`jj`（jキーの2連打）が人気だ**

- 打ちやすさで言えば`jj`が最高だ。`j`が連続する文章を書くことはほぼないので、実用上問題が起きない。いざとなれば、めっちゃゆっくり`j`を連打すれば打てる。ただ、上の「IME切り替えだるい問題」と同時に解決する方法はよく分からない・・・macOSならKarabinerでできるんだろうか。macOS以外ではどうすればいいんだろう
- Vimでは、`~/.vimrc`に（Vim scriptで）キーマッピングを追加すればできる：

```vim
vnoremap jj <Esc>
noremap! jj <Esc>
vnoremap っｊ <Esc>
noremap! っｊ <Esc>
```
を追加すればいい。`vnoremap`はヴィジュアルモードで、`noremap!`はコマンドラインモードとインサートモードでのキーマップ設定だ。ノーマルモードでも設定してしまうと、下に移動しようとしてjを押すとちょっと待機時間が発生してもたつくので避ける。「っｊ」も設定しておけば、日本語IMEを切ってなくてもノーマルモードに戻れる

- Atomでは、Atom->キーマップを押すと現れるCoffeeScriptファイルkeymap.csonに

```coffeescript
'atom-text-editor.vim-mode-plus.insert-mode':
  'j j': 'vim-mode-plus:activate-normal-mode'
```
を追加すればできる（参考:  [jj shortcut. How to implement this? #669](https://github.com/t9md/atom-vim-mode-plus/issues/669)）。この場合、日本語の「っｊ」も追加する方法はよく分からない

- Jupyter Notebookのjupyter-vim-bindingでは、[公式ページ](https://github.com/lambdalisue/jupyter-vim-binding)にあるように、JavaScriptファイル`~/.jupyter/custom/custom.js`（無ければ作る）に

```js
// Configure CodeMirror Keymap
require([
  'nbextensions/vim_binding/vim_binding',
], function() {
  // Map jj to <Esc>
  CodeMirror.Vim.map("jj", "<Esc>", "insert");
});
```
と書き込めばできる。やってみた感じ、jキーをある程度速く2回連打する必要がある。Jupyter Labのjupyterlab_vimでのやり方はよく分からない

---

以上です。一緒にVimキーバインドライフを楽しみましょう！

<br>
追記： UnixシェルでVimキーバインドを有効にする方法について簡単なメモ

- bash: 設定ファイル`~/.bashrc`に`set -o vi`と追記する。`jj`でノーマルモードに戻るには、さらに`bind '"jj":vi-movement-mode'`と追記
- zsh: 設定ファイル`~/.zshrc`に`bindkey -v`と追記する。`jj`でノーマルモードに戻るには、さらに`bindkey -M viins 'jj' vi-cmd-mode`と追記
- fish: 設定ファイル`~/.config/fish/config.fish`に`fish_vi_key_bindings`と追記する。`jj`でノーマルモードに戻るには、さらに`bind -M insert -m default jj force-repaint`と追記
    + bashやzshでは、テキストオブジェクトが使えないっぽい。他にも使えない機能があるかは不明
    + fishではテキストオブジェクトが使えるけど、`3dw`といったカウント機能が使えないっぽい。そして、そもそもシェルにundoが実装されてないので`u` (undo) コマンドが働かない