VimでDvorakしよう ― 2013年02月13日 00:02
この記事は Vim advent calendar の75日目です。74日目は Mi_Sawaさん の template/snippet plugin for Battle Programmer でした。
標準的には25日目までなはずですから、なんと3倍!クリスマスっていつでしたっけ。明日はバレンタインデーですよ。えっ……中止?
あなたはQWERTY派?それともDvorak派?
突然ですが、キーボードレイアウトの時間です。
みなさまおなじみQWERTY
+----+----+----+----+----+----+----+----+----+----+----+----+
| ! | @ | # | $ | % | ^ | & | * | ( | ) | _ | + |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = |
++---++---++---++---++---++---++---++---++---++---++---++---++
| | | | | | | | | | | { | } |
| Q | W | E | R | T | Y | U | I | O | P | [ | ] |
++---++---++---++---++---++---++---++---++---++---++---++---+
| | | | | | | | | | : | " |
| A | S | D | F | G | H | J | K | L | ; | ' |
++---++---++---++---++---++---++---++---++---++---++---+
| | | | | | | | < | > | ? |
| Z | X | C | V | B | N | M | , | . | / |
+----+----+----+----+----+----+----+----+----+----+
Dvorak
+----+----+----+----+----+----+----+----+----+----+----+----+
| ! | @ | # | $ | % | ^ | & | * | ( | ) | { | } |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | [ | ] |
++---++---++---++---++---++---++---++---++---++---++---++---++
| " | < | > | | | | | | | | ? | + |
| ' | , | . | P | Y | F | G | C | R | L | / | = |
++---++---++---++---++---++---++---++---++---++---++---++---+
| | | | | | | | | | | _ |
| A | O | E | U | I | D | H | T | N | S | - |
++---++---++---++---++---++---++---++---++---++---++---+
| : | | | | | | | | | |
| ; | Q | J | K | X | B | M | W | V | Z |
+----+----+----+----+----+----+----+----+----+----+
私は、ながらくDvorakつかっています。Dvorak布教するつもりはあまりないので理由は延べませんが、使い始めてそろそろ11年経ったことに気づきました。うぎゃぁー
……えっと、残念ながらハードウェアでDvorakなキーボードは所持しておりませんが、ソフトウェアでDvorak設定にする派です。
プライベートで使ってる端末はすべてDebianのインストーラで真っ先にDvorakを選択しますし、 「いかんともしがたい理由により」Windowsな端末の場合でも、定番の「窓使いの憂鬱」やその後継の「のどか」を入れて、さくっと設定します。 場合によってはレジストリでもいいかもしれませんね!
大抵の場合は、キーボードレイアウトは、ソフトウェアレベルで比較的自由に設定できます。自由すばらしい。
私が本当にほしいのはたぶん自由ではなく「私に合った不自由」だと思うのですが、そんな意味不明な主張はさておきまして、やっとVimの話です。
DvorakでVim
Dvorak派のひとでも、Vimを使う場合、(特にノーマルモードの)コマンドのキーだけはQWERTYにしたい、という話をたびたび見かけます。 特に、QWERTY なら右手ホームポジション付近で横に並んでる HJKL が Dvorak では散り散りになってしまうののを嫌う向きは多いみたいです。
ですが、Dvorakのそのままでもいいじゃん、というひともいます。
私はまさに、この考え方に同意します。HJKLを使う頻度ってそれほど高くない気はするものの
jk が隣り同士でしょ。h と l は離れてるけど、きちんと左と右側に位置してるでしょ。
しゅごい!!
しゅごいのです!!!
補足しますと、垂直移動の jk が左手、水平移動の hl が右手に分かれているのが、なんともすばらしい。
ほとんど排反といっていい操作が同じ側の手に、独立であってほしい操作が違う側の手に、それぞれきれいに割り当てられています。 片手での操作の難易度が上がるというデメリットはあるものの、普通に使う分には Dvorak の方が効率的な操作が期待できます。
実に合理的です。Dvorak配列でVim、こわくないです。
+----+----+----+----+----+----+----+----+----+----+----+----+ | | | | | | | | | | | | | | | | | | | | | | | | | | ++---++---++---++---++---++---++---++---++---++---++---++---++ | | | | | | | | | | | | | | | | | | | | | | | L | | | ++---++---++---++---++---++---++---++---++---++---++---++---+ | | | | | | | | | | | | | | | | | | | H | | | | | ++---++---++---++---++---++---++---++---++---++---++---+ | | | | | | | | | | | | | | J | K | | | | | | | +----+----+----+----+----+----+----+----+----+----+
……まあ、そういうことを考えてきめたというわけではないのですが、私はDvorakのままVimをカラダで覚えてしまっています。
立場をまとめてみます。
Vimつかってるよ派 (世界全体) | +-- QWERTYだよ派 (多数、保守) | +-+ Dvorakだよ派 (少数、革新) | +-- ノーマルモードとかのコマンドはQWERTYっぽいのがいいよ派 (穏健) | +-- Dvorakそのままでつかうよ派 (原理主義) ← 私はココ
長くなりましたが、ここまで前置きです。
QWERTYでVim ……というディストピア(私限定)
ある日突然、QWERTYなキーボードで仕事することになったら……キーボードレイアウトの設定も変えられなかったら。 あんまり考えたくない事態です。でも、ありえないとは言い切れません。
もっとも、エディタはVim以外ありえません。ここはいいですね。先の図にも書いたとおり、Vimは世界全体です。
つまり、普段 DvorakのままVimを使っている私が、QWERTYでVimを使うことになったら何が起きるのか考えてみます。
たとえば、カーソル行とその一つ下の行を繋げたいとしましょう。もちろん J です。
Dvorakでは、左手中指下段です(私は人差し指で拾いますが)。アタマより先にカラダが動いてこのキーを押下!
結果……行末まで消えてしまいました。
そう、QWERTYキーボードでこの位置には C があります。
私はただ、次の行を繋げたかっただけなのに。行末まで消えてしまい、あまつさえ挿入モードに切り替わるだなんて。
こんなの絶対おかしいよ!
もうひとつ考えてみましょう。こんどは、カーソル行に新しく空行をつくりたいとしましょう。もちろん O です。
Dvorakでは、左手薬指ホームポジション!もちろん反射的に押下します。
結果……カーソル行の内容が消えてしまいました。
そう、QWERTYキーボードでこの位置には S があります。
たしかに空行はできましたが……私はあたらしい空行がほしかったのに。カーソル行の内容が犠牲になるだなんて。
こんなのってないよ!あんまりだよ!!!ひどすぎるよ……
たった2つだけの例ですが、恐ろしさは伝わりましたでしょうか。でもこれは氷山のほんの一角に過ぎません。
- 左に動かそうとしたカーソルが下にいた。何を言ってるのかわからねーと思うが(ry
- 行頭に挿入開始しようとおもったら最下行にいた。何を言ってのるかわか(ry
- コロンを打ってみたつもりが反応がないのでもう一度打ったら、上書き保存されてVimが終了した。何を(ry
こんな環境に置かれ続けたら、私の魂はあっというまに穢れていくことでしょう。
VimでDvorak
取り越し苦労の最中、ふと気づいてしまいました。端末のキーボードレイアウトを設定できなくても、.vimrcで設定すれば、Vimの中でだけはDvorakが実現できるんじゃないか、と。 シェルには戻らずすべて :! とか徹底すれば、Vimの外に出ずに済むかもしれません……完璧!?
.vimrc は空に近いほどよいという私の好みには合いませんが、穢れきった私の魂が呪いを生み出す存在と成り果ててしまうよりはマシです。
Vimおねえちゃん、Dvorakを使い始める前の、ばかな私を、たすけてあげてくれないかな。
その結果、魂を対価に得られたものがこれです。
no - [
no! - [
no = ]
no! = ]
no q '
no! q '
no w ,
no! w ,
no e .
no! e .
no r p
no! r p
no t y
no! t y
no y f
no! y f
no u g
no! u g
no i c
no! i c
no o r
no! o r
no p l
no! p l
no [ /
no! [ /
no ] =
no! ] =
no a a
no! a a
no s o
no! s o
no d e
no! d e
no f u
no! f u
no g i
no! g i
no h d
no! h d
no j h
no! j h
no k t
no! k t
no l n
no! l n
no ; s
no! ; s
no ' -
no! ' -
no z ;
no! z ;
no x q
no! x q
no c j
no! c j
no v k
no! v k
no b x
no! b x
no n b
no! n b
no m m
no! m m
no , w
no! , w
no . v
no! . v
no / z
no! / z
no _ {
no! _ {
no + }
no! + }
no Q "
no! Q "
no W <
no! W <
no E >
no! E >
no R P
no! R P
no T Y
no! T Y
no Y F
no! Y F
no U G
no! U G
no I C
no! I C
no O R
no! O R
no P L
no! P L
no { ?
no! { ?
no } +
no! } +
no A A
no! A A
no S O
no! S O
no D E
no! D E
no F U
no! F U
no G I
no! G I
no H D
no! H D
no J H
no! J H
no K T
no! K T
no L N
no! L N
no : S
no! : S
no " _
no! " _
no Z :
no! Z :
no X Q
no! X Q
no C J
no! C J
no V K
no! V K
no B X
no! B X
no N B
no! N B
no M M
no! M M
no < W
no! < W
no > V
no! > V
no ? Z
no! ? Z
これをvimrcに貼り付けるなりsourceするなりで設定が効きます。
ちなみに こういうスクリプト で生成しました。
実際試してみて、ある程度Dvorakが実現できていることを確認しました。
……が、残念ながらCtrlのときはQWERTYのままです。
Ctrlのときの設定も少し挑戦してみましたが、ターミナルに奪われる場合とか、 Vimの外のことをやっぱり考えないといけない感じで、非常時に頼るわけにはいかない完成度です。今後の課題としましょう。
なお、Dvorakなキーボードレイアウトのときにこの設定をすると、大変なことになります(なりました)。注意しましょう。
明日は @tyruさん です。こんどこそ「ばよえ〜ん」ですね!おめでとうございます。
キーボードマクロで遊ぼう ― 2011年12月25日 06:06
こんにちは。Vim Advent Calendar 2011 25日目の@plasterです。Vimって素敵なエディタですよね。
今日の記事のネタのメモをどこに保存していたか忘れてlocateとfindとgrepを重ねた挙句、
Vim起動して[CTRL-O]ですぐ見つかりました。知らなかったひとは今すぐ:h CTRL-Oしましょう。
エディタは生産性の源だと思います。
さて今日は、その生産性を効率的にむだづかいする方法の紹介です。いいんです、実用性などに縛られないからこその愛なのです。目指せ極北!
というわけで、かんたんなアスキーアート生成と、数列の生成と、迷路ソルバやります。全部キーボードマクロで。
フィボなっち
まずはアスキーアートの生成から。見出しの「フィボなっち」というのは
(●´ー`●) (●´ー`●) (●´ー`●)(●´ー`●) (●´ー`●)(●´ー`●)(●´ー`●) (●´ー`●)(●´ー`●)(●´ー`●)(●´ー`●)(●´ー`●) ...
1行あたりの(●´ー`●)の個数が 1, 1, 2, 3, 5, ……とフィボナッチ数列になっているテキストです。
特になっちに思い入れがあるわけではないのですが、なんとなく和むAAなので、ちょっと気に入っています。 このテキストの入力を Vimで自動化してみましょう。
種
最初の2行は、そのまま入力します。- O(●´ー`●)Yp
ステップ
今、バッファが
(●´ー`●) (●´ー`●)
となっていて、2行目にカーソルがあるはずですね。ここで ykjpgJと入力すれば、次のようなバッファになります。
(●´ー`●) (●´ー`●) (●´ー`●)(●´ー`●)
カーソルは3行目です。ykjpgJを打つたびに、最後の2行をつなげたものが最終行に追加されます。たかだか6回の打鍵ですが、自動化してしまいましょう。
キーボードマクロの記録と呼び出し
qaでマクロの記録を開始します。その後qで記録を終了し、@aでマクロの呼び出しができます。たとえばqaykjpgJqと入力すれば、ykjpgJを実行しつつ記録するわけです。
(●´ー`●) (●´ー`●) (●´ー`●)(●´ー`●) (●´ー`●)(●´ー`●)(●´ー`●)
以後、最終行にカーソルがある状態で@aを入力するたびに1行ずつ増えていきます。
(●´ー`●) (●´ー`●) (●´ー`●)(●´ー`●) (●´ー`●)(●´ー`●)(●´ー`●) (●´ー`●)(●´ー`●)(●´ー`●)(●´ー`●)(●´ー`●)
3@aとか打てば、3行ふえます。99@aとかももちろんアリ!ですが、すごいことになるので注意しましょう。万一やってしまって Vim が暴走しちゃったら、落ち着いて[CTRL-C]です。
フィボナッチ数列
コピペでひたすらテキストを増やしていく例を紹介しましたが、もちろん普通にフィボナッチ数列を作ることもできます。
……とその前に、[CTRL-A]を紹介します。あと、レジスタとマクロの関係を説明します。
CTRL-A
たとえば、バッファに
1
とある状態で、1の部分にカーソルを持っていって[CTRL-A]すると
2
になります。もう一度[CTRL-A]すると
3になります。[CTRL-A]するたび1ずつ増えるね!ってことです。 10とすれば10ふえます。
13
マクロとレジスタ
さきほどはqa~qを使ってキーボードマクロを記録しました。記録されたマクロは@aで呼び出すことができるわけですが、 実はレジスタに入っている内容ならば、なんでも呼び出して実行することができます。
Vimしらない人がこの記事を読んでくださってるのか謎ですが念のためにひとことで説明しておくと、レジスタっていうのは、Vimにおけるクリップボードみたいなものです。 テキストをヤンクや削除したりキーボードマクロを記録したりすると、とにかく レジスタ というものに記憶されるんだと覚えておけば間違いありません。
ヤンク内容を実行できる機能は、バッファに「自動で実行したい内容(の一部)」が書かれているようなときに大変役立ちます。キーボードマクロで遊ぶときの基盤技術ともいえます。 たとえばバッファに
10
という行があって、この行の行頭にカーソルがあるとします。
y$すると無名レジスタ"に10が入ります。
この状態で@"と入力すると、10を入力したのと同じことになります。続けて[CTRL-A]を入力すれば、全体では10したのと同じことになり、この行のテキスト10は10インクリメントされて、次のように変化しているはずです。
20
この先の展開が丸見えの方もいらっしゃるかと思います。 準備できたので、フィボナッチ数列の生成をしてみましょう。
種
最初の2行はそのまま入力してしまいます。
- O1Yp
バッファは次のような2行になり、2行目にカーソルがあるはずです。
1 1
ステップ
フィボなっち のときと同様に、ykjpgJします。
1 1 11
カーソルは最下行の2桁目、最初の1の直後にあるはずです。この状態で、Dしましょう。
1 1 1
ご存知のとおりDは、カーソル位置から行末までを削除します。
これは1行未満の削除なので、小削除用レジスタ-に削除内容が入ります。
ここで@-することで、さきほど削除された1がVimに入力されている状態になります。さらに[CTRL-A]すると、残った部分がインクリメントされます。
1 1 2全部1ばかりでわかりづらかったので、キーボードマクロを記録しがてら、もう1ステップ見てみましょう。3行めにカーソルがある状態でqaykjpgJすると:
1 1 2 12
続けてD
1 1 2 1
カーソルは4行目にあり、小削除用レジスタ-には2が入っています。
ここで@-[CTRL-A]と入力すれば、2[CTRL-A]するのと等価なので、4行目が2インクリメントされて
1 1 2 3
となります。qを入力してマクロ記録を終了して、以後@aと打つたびに、つぎつぎとフィボナッチ数がふえていきます。 10@aとかも余裕です。
1 1 2 3 5 8 13 21 34 55 89 144 233 377
迷路を解こう
ちょっと前、、、といっても2年近く経ってしまったようなのですが、迷路ソルバが流行ってましたよね。たしか、Vimスクリプトで解いてた方もいらしたように記憶しています。
私も実は anarchy golf の maze solving にあるものをVimで解いたことがあるので、その中身を紹介します。 ただし、
- Vimといってもキーボードマクロで実装します。
- 実装の都合上、以下の制限があります。
- ナイーブな「深さ優先探索」するので、 迷路の形状によっては必ずしも最短経路になりません。
- 外壁が矩形になっていることを前提とします。
- スタート地点(として扱うことのできる外壁の空き)が、 外壁の上辺または左辺にあることを前提とします。
(以下の設問および解答は anarchy golf からの引用です。)
こういう迷路があったとき (「#」が壁、空白が通行可能箇所)
############################# ########### # # # # # # # # # # # ### ##### ### ### ### ##### # ##### # # # # # # # # # # # # # # # ### # ####### # ##### ### ### # # # # # # # # # # # # # # # # ### # ### # ### # # ### # ##### # ##### # # # # # # # # # # # # # # # ########### ##### ### # ### # # # # # # # # # # # # # # # # # # # # ##### ####### # # ### # ##### # # # # # # # # # # # # # # # ########### # # ##### ####### ####### # # # # # # # # # # # # # # ### ####### # ##### # ##### # # ### # # # # # # # # # # # ##### ### ### ####### ####### # ##### # # # # # # # # # # # # # # ##### ### ##### # ### ### # # # # # # # # # # # # # #########################################
「.」で入口から出口までの経路を示すのがミッションです。
#############################.########### # # #.......# # #.....# # # # # ###.#####.### ### ### #####.# ##### # # # #...# #.......# # #.....# # # # # #.### # #######.# #####.### ### # # # # #...#...# # #...# #.....# # # # # ### #.###.#.### # #.### #.##### # ##### # # #.....#...# #.# #.# # # # # # # ###########.#####.### #.### # # # # # # # # #.....#.# #.# # # # # # # # ##### #######.#.# ###.# ##### # # # # ..# # # #.#.....#.......# # # # #.########### # #.#####.#######.####### # #.# # # .# #...# #... # # #.# # ### #######.# #####.# #####.# # ### #.# # # #... #.......#.# # # #.##### ### ###.####### #######.#.##### # #.#.......# #.....# # #.#. # # # #.#.#####.### #####.# ### ### #.#.# # # # #... #...........# # #...# # #########################################
設問に入口と出口の区別はないのですが、 とにかく「外壁のあいてる2箇所をつなぐ経路を出しましょう」ということですね。
解き方の方針
- スタート位置にカーソルを持っていき、
- カーソル位置の文字が空白
なら、以下 3. ~ 8. を順に実行する。 そうでなければ、何もしない。 - カーソル位置の文字を
.で上書きする。 - カーソルをひとつ右に移動し、2. を再帰的に実行し、カーソルをひとつ左に移動する。
- カーソルをひとつ下に移動し、2. を再帰的に実行し、カーソルをひとつ上に移動する。
- カーソルをひとつ左に移動し、2. を再帰的に実行し、カーソルをひとつ右に移動する。
- カーソルをひとつ上に移動し、2. を再帰的に実行し、カーソルをひとつ下に移動する。
- カーソル位置に空白
を書き込む。
なお、途中でカーソルの移動が失敗したら(つまり出口にたどり着いていたら!)、大域脱出して実行終了ということにします。
実装
まずバッファに次のようなテキストを1行、書いておきます。
yl@=@0==" "?"r.l@1hj@1kh@1lk@1jr ":""
この行でddして、テキストをレジスタ1に入れます。
あとは、カーソルを迷路の入口
↓ココ ############################# ########### # # # # # # # #
に持ってきて@1すれば、迷路が解けます。1行で解けるんですね、Vimってすごい!
実行してみた様子のキャプチャを以下に貼ります:

解説
肝になっているというかキモいのが、expression用レジスタ=です。
「式を評価して、その中身がレジスタに入っているものとして扱う」という代物で、ふつうは
- (ノーマルモードで)"=7*6p
- (挿入モードで)=7*6
のように、即席で計算式を書いて、その計算結果を文書中に張り付けたいときに活用すると便利なものです。 ところで、これももちろんレジスタなので、計算結果の値をマクロとして直接実行できます。それが@=なのです。(式にどんなものが書けるのか知りたい方は、今すぐお手元のVimで:h expressionしましょう!)
今回の@1で何が起こるか順を追って説明すると:
- ylでカーソル位置をヤンクし、レジスタ
0に入れる。 - @=が来たので、続けて入力されるものを式とみなしてその値をマクロ実行する。
- 式
@0==" "?"r.l@1hj@1kh@1lk@1jr ":""を評価し、その値をマクロ実行する。- カーソル位置が空白文字だった場合、
式の値は文字列
"r.l@1hj@1kh@1lk@1jr "になるので、 r.l@1hj@1kh@1lk@1jr を実行する。これは前述「解き方の方針」3. ~ 8. に相当。 - そうでなければ、式の値は空文字列
""になるので、何も実行しない。
- カーソル位置が空白文字だった場合、
式の値は文字列
という具合に、素直な再帰実行しています。なお、マクロ実行はコマンドにひとつでも失敗すると即座に中止されます。どんなに深い再帰をしていても全部中断、つまり大域脱出してくれます。今回はこれがぴったりハマりました。
キーボードマクロとanarchy golf
私が expression用レジスタ のこのような使い方を知ったのは anarchy golf の Tower of hanoi の Vim で nnさん に完敗したときです。 まさかキーボードマクロで素直な再帰が実現できるとは微塵も思っていなかったので目から鱗だったというか、その後の Vimゴルフをまったく違ったものにしてしまう、(少なくとも私の中では)強烈な事件でした。
今更ですが anarchy golf についてひとこと説明しますと、お題を満たすプログラムのソースを投稿して、ソースの短さを競うというものです。プログラムが正しいかどうかは、既定の(最大)3通りの入力に対して、正しい出力を出すこと、で判定されています。
Vimの場合は、「入力が予めバッファに入っている状態で、正しい出力の形にバッファ内容を変更する」ためのキー入力をプログラムとして与えます。それを1バイトでも短くするには、しばしば、キーボードマクロが大変有効なのです。
つまり何が言いたいかというと、キーボードマクロで遊ぶのに anarchy golf は最高ってことですね。 クリスマスに年越しに、Vimゴルフっていいものですよ。
- 0が0回の繰り返しじゃなくて行頭移動なことにブチキレそうになったり
- [CTRL-J]と[Enter]の挙動の違いに気づかずハマったり
- :sで置換対象がなくてもエラーにしないために最後につけるeがもったいなかったり
いろいろ言い足りないことがある気がするのですが、またの機会ということで。 それではみなさん、(Vimと)よいクリスマスをお過ごしくださいませー。私はこれから寝ます(キリッ
最近のコメント