2013-05-13
同一視されるキーに注意
Vim Advent Calendar 2012 の 164 日目の記事です。
Vim は元々端末で動作していたソフトウェアで、それ故のキー周りに関する制限がいくつかあります。端末版の Vim を使うのであればある程度は仕方のないことですが、いくつかの制限は gVim にも残っています。
一部のキーが同一視される
以下のキーは端末ではその仕様上の制限により同一視されて区別できないのですが、Vim では GUI 版でも同じように同一視されて区別することができません。
- <C-i> == <Tab>
- <C-m> == <Enter>
- <C-[> == <ESC>
つまり、以下のようなことはできません。
inoremap <expr> <Tab> MySuperTab() " ↓これは <Tab> のキーマッピングを上書きしてしまう! inoremap <C-i> <C-o><C-i>
<C-[> くらいならそんなに困ることはないんですが、残りの2つははまったことがある人もいるのではないでしょうか。
今のところ解決方法はなく、きちんと問題を認識して回避するしかありません。gVim 版では技術的には区別可能なはずなので、将来のバージョンで解決される可能性はあります。
ちなみに似たようなキーの組み合わせに <C-h> と <BS> がありますが、これらは区別可能です。
これらとは別に、GUI 版では使用できるけど CUI 版では仕様できないキーの組み合わせも結構あります*1。CUI と GUI の両方を使う人はきちんと把握しておくと良いでしょう。
2013-05-09
Ruby で Haskell や Clojure の iterate
欲しかったので探したけど見つからなかったので書いてみた。
def iterate(init, &block) Enumerator.new do |y| loop do y << init init = block.call(init) end end end p iterate(1, &:succ).take(10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
ブロックを渡している関係上引数の順序が逆だけど気にしない。
と言うか、すごく便利なのに本当に標準でないのか? 私が見つけられてないだけってことは…。Rubyist の皆さんは普段どうしているのだろう。
2013-04-26
意外と知られていない diff に関する機能
Vim Advent Calendar 2012 の 147 日目の記事です。
137 日目の tyru さんの記事で、Vim の diff 機能について紹介がありました。この記事ではもう少し細かい diff の機能について紹介したいと思います。
:diffthis
比較したい対象がファイルではない場合、例えば、外部からデータを無名バッファにコピーしてきた場合に、それらのバッファの diff を表示したいことがあります。この場合は、:diffsplit は使えません。
こういう場合は :diffthis を使います。diff を適用したいバッファでそれぞれ :diffthis をすると、実行したバッファ同士の差分を見ることができます。
これを利用した設定に、help で紹介されている :DiffOrig があります。(:help :DiffOrig)
これは現在編集中のファイルと、最後に保存したときのファイルとの差分を表示するコマンドです。
command DiffOrig vert new | set bt=nofile | r ++edit # | 0d_ \ | diffthis | wincmd p | diffthis
現在のタブページに差分の対象にしたいバッファしか開かれていない場合は、:windo diffthis が便利です。
:diffoff
:diffthis で差分を表示した後、元に戻したい場合は :diffoff です。:diffoff! をすると、現在のタブページ内の全ての差分モードを終了します。
ちなみに、:diffthis や :diffoff は実際にはいくつかのオプションを書き換えるだけのコマンドで、その中には 'foldmethod' や 'wrap' なども含まれています。なので、:diffthis :diffoff を実行すると、これらのオプションが実行する前の値から変わってしまう場合があるので注意してください。
:diffupdate
マージ作業をする場合などは、差分をただ眺めるだけでなくバッファを更新していくことになると思います。そして、作業をしていると差分のハイライト表示がおかしくなる場合があります。
その場合、:diffupdate を実行するとハイライトを更新してくれます。
その他
今回は省略しますが、次の差分/前の差分にジャンプしたり、差分を反対側に適用したりすることも可能です。気になる方は :help diff を見てみてください。
2013-04-21
TokyoVim#14 に行ってきた
TokyoVim#14 に行ってきたよ。
今回はおやつにミスドでドーナツを買っていった。
ミスドでドーナツ買っていきます。 #TokyoVim
ドーナツも含めて、チョコレートやら飴やらカントリーマアムやら、今回はおやつが充実しすぎててやばかった。
早くも大量のお菓子が #TokyoVim
どーなつおいしいです。 #TokyoVim
どーなつおいしいです #TokyoVim
無印良品のブラウニーチップっていうお菓子がおいしい #TokyoVim
成果物
今回、私は Vim の help の folding をするプラグインを作ってた。
https://github.com/thinca/vim-ft-help_fold
元々私の個人設定ファイルに入っていて、プラグイン化の要望があったので今回作業するついでに色々動作を改良していた。
改良していたら時間内に終わらなかったので、帰宅後にこの記事書きつつ残りの改良とhelp書きとリリース作業などしてた。時間かけすぎた…。
help の区切りで使われる === な行や --- な行、あとは help の tag の部分 (*word*) を目安に折り畳まれるようになっている。あとは foldtext をかなりがんばった。改良の甲斐あってそこそこいい感じにできた感。
ただ、foldlevel=1 からいきなり foldlevel=3 になってしまう場合があって、そこの動作が若干残念な感じではある。直せそうにないので諦めた。
スーパーShougoタイム
そして今回は、スーパーShougoタイムがあった。kana さんがプロジェクタを出してきて、使いたい人どうぞ、としたところ、Shougo さんが残酷な天使のエディタを熱唱しました。以下各位の反応。
Shougo さんが残酷な天使のエディタを歌うそうです。 #TokyoVim
やべぇ。歌くるのか #TokyoVim
全く予想もしていなかった事態に!? #TokyoVim
今からカラオケ会場になります。 #TokyoVim
Shougoタイムきたー #TokyoVim
Shougoさんやばい #TokyoVim
暗黒美夢王が歌ってる #TokyoVim
#TokyoVim みんな目を合わせない #残酷な天使のエディタ
2013-04-20 16:08:29 via web
#TokyoVim ちょっと!この空気どうにかして!(笑)
2013-04-20 16:09:28 via web
kana さんがなんとも言えない表情をしている #TokyoVim
なんだこれw #TokyoVim
やめたほうがよかった
2013-04-20 16:07:57 via web
懇親会
懇親会は雨にも関わらず7名参加。適当なお店に入って色々お話した。
色々お話したはずなんだけど、@kefir_ さんと @ShougoMatsu さんが端末談義で終始盛り上がっていたのでそこにほぼ話題が持っていかれた感じ。いや、端末について色々聞けて楽しかったから良いのだけど!
Shougo「Vimと端末に乾杯!」 #TokyoVim
後は、Vim温泉が必要って話とか出たので誰か主催してください。
今回はいつもに比べて、全体的に交流できたような気がする!
今回残念ながら参加できなかった人や、懇親会に参加できなかった人は恐らくあるであろう次回にお会いできるのを楽しみにしてます!
2013-04-10
カラースキームを作ってみよう
Vim Advent Calendar 2012 の 131 日目の記事です。
毎日のように Vim を使っているみなさんは、恐らくお気に入りのカラースキームがあったりすると思います。中には一部が気に食わなくて改造してみたり、更にはすでに自作している方もいるかもしれません。
今回は、「カラースキーム作ってみたいけど作り方がよくわからない><」「改造して使ってるけど実はよくわかってないんだよね…」といった方を対象に、カラースキームの作り方について簡単に説明してみようと思います。長くならないように、適時端折っていこうと思います。
始めに
ぶっちゃけてしまうと、最初は既存のカラースキームを改造するところから入るのが楽です。真似して書くとだいたいそれっぽくなるものです。
この記事では 0 から作ることを想定して解説していきますが、チュートリアル的な内容と言うより知識的な解説になっているので、改造だけするにしても参考になるかと思います。
ハイライトグループ
カラースキームを作るというのは、ハイライトグループに対してハイライト(色や書式)を設定していく作業になります。
ハイライトグループは大きく分けて2通りあります。
- Vim 本体の部品で使うハイライトグループ
- ステータスラインや行番号、補完のポップアップなど
- :help highlight-groups
- 編集領域内で使うハイライトグループ
- Syntax 機能で使う色、文字列(String)やコメント(Comment)など
- :help group-name
使われ方が違うだけで、色を設定する上で特別区別する必要はありません。
それぞれで示した :help を見ると、どのようなグループがあるかがわかります。カラースキームを作る際には、ひと通り色を指定するのが理想です(ただし後述のリンクも参照)。指定しなかった場合はデフォルトの色が使用されます。古いカラースキームを使うと補完がキツい紫っぽい色になっているのはあれがデフォルトだからです。
カラースキームファイルを作る
何はともあれ、まずはカラースキームファイルを作りましょう。
その前に、カラースキームの名前を決める必要あります。使える文字などには恐らく特に制限はありませんが、名前がそのままファイル名になります。なので、英数字と -_ 辺りの記号のみで構成しておくのが無難です。また、公開する予定がある場合は既存のカラースキームを検索して被らない名前にしておくと良いでしょう。
決めたら 'runtimepath' 内の colors/{決めた名前}.vim と言うファイルを作成します。例えばカラースキム名が "thinca" なら、Windows なら ~/vimfiles/colors/thinca.vim、Linux 系なら ~/.vim/colors/thinca.vim になります。このファイルにカラースキームの定義を書いていきます。
コンセプトを決める
カラースキームには大きく分けて暗い背景のものと、明るい背景のものがあります。作る際には、どちらのものを作るか決める必要があります。両対応にすることも可能です。
決めたら、以下のテンプレートが使えます。
暗い背景用
let g:colors_name = expand('<sfile>:t:r') set background=dark highlight clear " ... ここに定義を書いていく
明るい背景用
let g:colors_name = expand('<sfile>:t:r') set background=light highlight clear " ... ここに定義を書いていく
両対応
let g:colors_name = expand('<sfile>:t:r') highlight clear if &background ==# 'dark' " ... ここに暗い背景用の定義を書いていく else " ... ここに明るい背景用の定義を書いていく endif
g:colors_name には、カラースキームの名前を入れます。こう書いておくと、ファイル名を変えても自動で追従するので便利です。たまに、改造のために既存のカラースキームをコピーして、ファイル名は変えたけどここを変えてないと言うケースを見ます。正しく設定されていないと Vim の動作に支障をきたすことがあるので気を付けましょう。
'background' オプションには "dark" か "light" を設定します。見ての通り、"dark" が暗い背景で、"light" が明るい背景です。
:highlight clear は、定義されている全てのハイライトを消してデフォルトに戻します。この時、'background' の値によってデフォルトが変わるので、先に 'background' を設定しておく必要があります。
補足: syntax reset について
既存のカラースキームを見ると、必ずと言っていいほど highlight clear の下に以下のように書かれています。
if exists("syntax_on") syntax reset endif
今回この記事を書くにあたって調べてみたのですが、この syntax reset で行っている内容は、highlight clear の段階でほぼ行われているようです。少なくとも私には syntax reset が必要な理由が見付けられませんでした。
これが慣習で残っているものなのか、それとも私が何か見落としていて実は普通に必要なものなのかはちょっとわかりません。もし必要な理由をご存知の方がいたら教えていただけると助かります。
気になる人は、syntax reset も書いておくとよいです。既存のカラースキームではほぼ書かれているので、実害はないはずです。
ハイライトの設定方法
いよいよハイライトを設定します。:highlight コマンドを使って以下のようにします。
" highlight {group-name} {key}={arg} ... highlight Comment ctermfg=Cyan guifg=#80a0ff
この例では Comment グループの文字色を設定しています。ctermfg は CUI 版の Vim で使われる文字色、guifg は GUI 版の Vim で使われる文字色を指します。
このように、CUI 版と GUI 版の設定は別々に行います。CUI 版は特に対応が面倒なので、必要なければ GUI 版のみに対応したカラースキームを作っても大丈夫です。幸い、CSApprox など、GUI 版のカラースキームを CUI 版に変換するようなものもあるので、複雑なものでなければこのようなものを使うのも手です。
実際には、この highlight コマンドを設定したいグループの数だけ列挙することになります。もちろん Vim script なので、必要であれば if や :execute でより複雑な定義もやろうと思えば可能です。
以下では、どのような設定ができるのかをもう少し詳しく見ていきます。
:highlight では文字の属性や、前景色(文字色)、背景色が設定できます。
文字の属性を指定することで、太字にしたり、斜体にしたり、下線を引いたりできます。CUI 版では、端末によって制限がある場合が多いです。
" 指定できるパラメータは :help attr-list を参照 highlight Comment cterm=italic gui=italic
前景色、背景色は、CUI 版では色名か色番号、GUI 版では色名か #RRGGBB 形式で指定できます。
色名については、:help cterm-colors や :help gui-colors などを参照してください。環境依存ですが、:help win32-colors や :help rgb.txt なども使えます。
" 例なので混ぜて使っているが、指定する形式は統一した方が良い highlight ErrorMsg cterm=bold ctermfg=231 ctermbg=Red gui=bold guifg=#ffffff guibg=Red
特に端末で 256 色のものを作ろうと思ったら名前での指定はできないので色番号の指定が必須になります。かなり大変なので、先ほど紹介したツールなどで GUI 版から変換するのがおすすめです。
また、見ての通り、属性や色を複数同時に指定できます。指定しなかったものについては変化しません。なので、1つのハイライトグループの定義を分けて書くことも可能です。
ハイライトのリンクについて
:help group-name で見られる構文グループの一覧ですが、説明を読むと、リンクされている、などと書かれています。
ハイライトにはリンク機能があり、特定のハイライトグループが別のハイライトグループと同じになるように設定することができます。
例えば、Constant については help に以下のように書かれています。
*Constant o 定数
String o 文字列定数: "これは文字列です"
Character o 文字定数: 'c', '\n'
Number o 数値定数: 234, 0xff
Boolean o ブール値の定数: TRUE, false
Float o 不動小数点数の定数: 2.3e10
これは、ここに書かれている Constant 以下のハイライトはデフォルトで Constant にリンクしている、つまり特に設定していない場合は Constant と同じようにハイライトされることを示しています。
具体的には Vim script で以下のように定義されています。
highlight default link String Constant highlight default link Character Constant highlight default link Number Constant highlight default link Boolean Constant highlight default link Float Number
これはつまり、Constant などの help で * が付いているものだけを最低限定義しておけばとりあえず一通りハイライトされることを意味しています。もちろん、全てに対してハイライトを細かく設定することも可能です。
ちなみに、画面内のどの要素が Constant でどの要素が String なのか、などは Syntax の定義によります。
おまけ: カラースキームと Syntax
色を付ける対象であるハイライトグループの一覧は :help highlight-groups と :help group-name で確認できることはすでに説明しました。しかし実際には、このリストのものに限らず任意の名前のグループに対してハイライトを設定できます。これを利用して、一歩進んだカラースキームも作れます。
Vim では Syntax 機能を使って、編集中のテキストの各箇所に構文グループを割り当てることができます。例えば、テキストのここからここまでは Function、この単語は Statement、と言った具合です。ここで割り当てた構文グループの名前は、先ほど説明したハイライトグループと同じものになります。つまり、構文グループ名に対して直接色を設定できます。
この構文グループ名は、通常はファイルタイプを接頭子にした名前が使われます。例えば vim なら、vimString vimComment と言った感じです。なので実際には、先ほど説明したハイライトのリンク機能を使ってリンクの設定をしています。
" vimString は String グループで、vimComment は Comment グループでハイライト highlight link vimString String highlight link vimComment Comment
これはつまり、特定の言語に対して細かく色を変えることも可能だということです。例えば Ruby では、文字列が rubyString、正規表現が rubyRegexp になっています。これらに直接ハイライトを設定することで、別々にハイライトすることも可能です。
※わかりやすくするためにあえて全然違う色にしてます
最後に
最初にも書きましたが、既存のカラースキームを見るとどんな感じか雰囲気が掴めると思います。
最後に便利サイトを紹介します。Vim の画面から直接色をいじってカラースキームが生成できます。
いじれない部品もあったりして網羅的ではないのですが、各部位がなんという名前のハイライトグループか、などが触っててわかるのが良いです。簡単なカラースキームならこれでも作れそうです。
さて、いかがでしたか。皆さんもぜひ、自分用のこだわりカラースキームを作ってみてください!
ちなみに私自身は配色センスが皆無なため自作はおろか改造もしてません。残念ですね。


