Home > Vim script

Vim script Archive

Vimテクニックバイブル紹介(Shougo版)

この記事について

この記事は、開発環境勉強会における「Vimテクニックバイブル」紹介スライドの完全版です。 「Vimテクニックバイブル」については、taku_oさんやmattnさんなども記事を書いていますが、 私の場合はできるだけ本の内容に触れたものにしています。 これを読んでVimテクニックバイブルを購入していただける人が増えれば、著者達にとって最高の喜びです。

Vimテクニックバイブルができた背景

以前にもブログの記事で触れていますが、Vim界には良質な記事や書籍が不足しています。 特に、まともにVim scriptを書ける人が書いた書籍がほとんどありません。 これはVim界の大きな損失であり、Vim scriptプログラマーが育たない大きな原因となっています。 私がVim勉強会に参加すると、必ずといっていいほど聞かれるのが 「Shougoさんは、Vimの書籍を書かないんですか?」ということです。 この声になかなか答えられないのは悲しいものがありました。

Vimテクニックバイブル

と、いうことで……今年ついにVimの書籍が刊行されます! 書名は「Vimテクニックバイブル」です。 中身は「Emacsテクニックバイブル」のVim版となっており、イメージカラーは当然Vimグリーンです。 そういえば、EmacsテクニックバイブルはEmacsブルー(パープル)でしたね。 キャッチコピーは、「unite.vimで進化する新しいVimの常識を教えます。あなたはVimの本当の姿を知っていますか?」 Emacsテクニックバイブルとは違い、unite.vimを全面に押し出しています。

執筆者紹介

執筆陣はかなり豪華です。おそらく、これだけの人達が一冊の書籍を作るために集まることはもうないでしょう。

taku_o

人気サイト「名無しのVim使い」の管理人です。雑誌にVimの記事を執筆したことがあります。 サイトで紹介しているだけあって、様々なプラグインについて、かなりの知見を持っています。

yukimi

章の基礎知識や用語の統一など、細かいところで手伝ってもらっています。Vim使いです。

mattn

webapi-vimやzencoding.vimの作者です。他にも細かなプラグインを作っています。 KaoriYaさんと同じく、昔からVimにパッチを多数送っており、Vimの内部実装や黒魔術に詳しいです。

thinca

quickrunやref.vim, scouter.vimなどの作者です。unite.vimのsourceやvital.vim, eskk.vimなどにも関わっています。 Vim scriptにかなり詳しいです。

fuenor

QFixHowm, QFixGrep, JPFormat.vimの作者で、Vim-UTF8を配布しています。 Windows環境での日本語の扱いについて詳しいです。

Shougo

neocomplcache, vimshell, vimproc, unite.vim, vimfilerなどを作っています。 メンテナンスしているプラグインが多すぎて、なかなか時間が足りないのが悩みです。Vimは環境だと思っています。

内容紹介

もう執筆がほぼ終わっているため、中身は確定しています。プラグインの紹介を中心とした豪華な内容となるようにしました。 紹介しているプラグインは定番からマイナーまで幅広く、作者自ら解説していることもあります。 まだ発売まで期間があるため、詳しい目次を挙げることはできませんが、以下のような内容が含まれています。

vimfiler

vimfilerの使い方や、キーマッピング、マニアックなところではvimfilerを用いた拡張リネーム機能について解説しています。

netrw

netrwによる遠隔地ファイル編集、netrwによるブックマーク、netrwによるファイル操作が解説されています。

quickrun

quickrunの使い方、各種オプション、設定方法について解説されています。

ref.vim

ref.vimの使い方、各種sourceについて解説されています。

vimshell(インタプリタ通信機能を含む)

vimshellの使い方、よく使われる内部コマンド、vimshellのインタプリタ通信機能を解説しています。 ちなみに、Emacsテクニックバイブルでは、eshellについて触れられていません。

Conque

Vimで端末を実現するプラグインであるConqueの使い方、vimshellとの違いについて解説しています。

skk.vim

SKKについて解説しています。eskk.vimも少しだけ書いてあります。それほどページはありません。

neocomplcache

neocomplcacheの使い方、設定方法、neocomplcacheのスニペット機能、スニペットの書き方、 neocomplcacheのsourceの作り方と、大変豪華な内容となっています。 以前Vim Hacksに書いた内容の完全版と言っても良いでしょう。

zencoding.vim

zencoding.vimの基本から、任意の言語への応用例まで挙げられています。

QFixHowm

QFixHowmの使い方、メモの作成方法、メモの検索、ToDo管理について解説されています。

QFixGrep

Windows環境のgrepの注意点についても解説されています。

JPFormat.vim

JPFormatによる日本語の整形方法について解説されています。

autodate.vim

webapi-vim

VimからWebサービスを扱う方法について解説されています。

project.vim

project.vimによるプロジェクト管理やproject.vimの設定方法について解説されています。

Vim scriptが分からない初心者でも安心!

Vimの設定や、Vim pluginについての解説を中心とした書籍となっていますが、 ある程度のVim scriptの知識は必要不可欠です。 そこで、次のような項目について解説しています。 これ以上の詳しい解説については、Vimのヘルプを参照してください。

:helpの読み方

Vimの:helpをすぐに引けるかどうかは、初心者と初級者を分ける大変重要なファクターとなっています。 この本では、Vimの:helpの使い方について解説しています。

Vim script基礎文法最速マスター(改訂版)

これは、thincaさんが以前ブログで書いていた「Vim script基礎文法最速マスター」の改訂版です。 Vim scriptについて一通り学ぶことができます。

マッピングについて

Vimのキーマッピングは大変ややこしいですが、詳しく解説しています。

オプションについて

Vimのオプションには落とし穴が多数あります。Vimのオプションにおける仕様について解説しています。

Vimプラグインの管理

Vimのプラグインをインストールするなら、パッケージマネージャは必要不可欠です。 定番のVundle, pathogenから、vimballに至るまで解説をしています。

テキストオブジェクト

最近のVimを語るにはなくてはならない機能です。 テキストオブジェクトの拡張についても触れられています。

QuickFix

grepやmakeには欠かせない機能です。

:autocmd

外部インタフェース

ちょっとレベルが高いですが、Perl, Pythonの外部インタフェースについて解説されています。

最近のVimといえば、unite.vimは外せないよね!

当然unite.vimについては、1つのChapterを贅沢に使用して解説しています。 Emacsテクニックバイブルはanything.elについて2つのChapterを使っているので、そちらよりは若干量が減ります。 それでも、30ページくらいはあるため、十分満足できると思います。 unite.vimの章では、次の内容を解説しています。 これを読めばあなたもunite.vimマスターに!

vimfiler, vimshellなどといった他のプラグインとの連携

unite.vimの有用なsource

カスタマイズ方法についての解説

unite.vimの各種オプションについて、解説しています。 マニアックなところでは、buffer-name-optionについての解説もあります。

source, kind, action, filterの解説

特にsourceを自作する場合、source, kind, action, filterの概念は重要です。それぞれの仕様について詳しく解説しています。 作者が自ら書いているため、情報が正確で安心です。

sourceの作り方まで載っている!

サンプルsourceの作り方が書いてあります。マニアックなところでは、非同期sourceの仕様についても書いています。

unite.vim Ver.2.2対応(一応)

一応最新版のunite.vimの仕様に準拠しています。残念ながら、あまりにも新しい機能は解説できていません。 不変的な情報に絞って解説しています。 現在開発中のunite.vim Ver.3.0について少しだけ触れています。

もちろん、Emacsの人達にもオススメ

EmacsテクニックバイブルがVimmerにも有用な本であったように、 当然VimテクニックバイブルはEmacsを使っている方々にもオススメです。 Emacsを使っている人も、異文化交流は重要です。 同じ環境で満足していたら、何も生まれません。 auto-complete.elもVimの補完機能を参考にしています。 つまり、Emacs使いであってもVimや他のエディタからも刺激を受けるべきなのです。 この本を読めば、最近のVimの機能やプラグインについて分かります。 例えば、unite.vimとanything.elの違いが分かります。 新人にVimを教えざるをえないときにも使えます。 さらに、一身上の理由により、Vimに乗り換えざるをえないときもVimテクニックバイブルの知識があれば安心ですね。

現在確定している情報

ページ数は384Pで、Emacsテクニックバイブルと同じです。 値段は¥2, 980+税です。基本的に技術書というのは、¥3000を越えると購入までのハードルが上がってしまいます。 ページをできるだけ減らしたこともあり、税抜きでなんとか¥3000は切ったのですが、若干Emacsテクニックバイブルより高くなってしまいました。 発売日は9月中旬予定ですが、詳しい日付けの確定はしていません。 目次については、八月中に確定する予定なので、九月には詳しい情報が出せるでしょう。 まだ発売まで時間があるので、しばらくお待ちください。

残念ながら載せられなかった内容

できるだけ、著名なプラグインは載せるように心がけましたが、 ページ数の都合やその他様々な理由により載せられなかったプラグインがあります。 ここではそれらについて紹介します。

VCSとの連携

VCSと連携できるプラグインとしては、git-vimやfugitive.vimがありますが、決定版と呼べるようなものがなかったためです。 vcs.vimが候補だったんですが、未完成でした。

shadow.vim

時間とページ数の都合が付きませんでした。

snipMate

neocomplcacheのスニペット機能で十分だったためです。解説する人もいませんでした。 ちなみに、snippetsEmuはページ数が足りませんでした。

echodoc

入れてもよかったんですが、他のTipsが削られすぎて入れる暇がありませんでした。

netrwについての詳しい解説

時間とページ数の都合がつきませんでした。 ただし、一部のTipsでnetrwの機能について触れられています。

metarw

使っている人があまりに少ないため削られました。metarwがやっていることは、vimfiler+unite.vimでできるようになる予定です。

vimprocの使い方について

書籍では簡単にvimprocについて触れていますが、さすがに詳しい解説はできませんでした。 想定読者にとっては難しすぎるからです。vimprocをバリバリ使えるような層では、Vim scriptから使い方を解読するのも簡単だと思います。

vital.vim

このプラグインは、プラグイン制作者のためのものです。この本の対象読者にはレベルが高すぎました。 それに、ページ数の余裕もありませんでした。

内容の陳腐化への懸念について

書籍は生物です。コンピュータに関する書籍は出たばかりのときに購入しておかないと、役に立つ前に時代遅れとなってしまうでしょう。 だからこの本が必要なら、発売されたらすぐに購入するのが適切です。特に、一度絶版になってしまったら取り返しがつきません。 本の売り上げが上がると、出版社に対するVimへの印象が良くなり、続編などが企画されるかもしれません:-)

特に私のプラグインは進化が早いため、本が出たらすぐに時代遅れとならないか心配してくれている人がいるようです。 はい。それは正しい指摘です。 ただ、私もそのことは分かっていました。だからわざと新しすぎる機能や、あまり使われない機能については本の中では解説せず、 「適時:helpを参照してください」ということになっています。できるだけ不変であろうことについて解説するようにしています。 それでも現在の実装と齟齬がでてきてしまった場合は、正誤表にて何かしらのフォローをする予定です。

「:helpに全部書いてあるから書籍は必要ない」という意見について

これはある意味事実です。だからこそ、本の対象とする読者は「Vimの基本的な操作や設定はできるが、:helpを自在に引くことはできない層」なのです。 :helpはリファレンスマニュアル的であり、分からない語句を検索するときに使います。 初心者が通読するには向いていません。 本というのは初心者が参照しやすいように、重要な情報をふるい分けることに価値があると考えています。

ただし、私が自分の記事の中で気をつけたのは、できるだけ「設計思想や使い方について解説をする」ことです。 これは:helpに書いていないことが多いうえに、内容が陳腐化することも少ないと考えました。 だから、ヘルプを自由自在に参照することができる、レベルが高いVim使いにとっても役立つ書籍だとは思います。 これが本当かどうかは、自分の目で本を見て確認してください。

なぜ「Vimテクニックバイブル」はVim scriptを学ぶ本ではないのか

それは需要がないからです。考えてみてください。あなたの周囲にVim scriptをバリバリ書けるような人はいますか? Vimが好きだから、Vim scriptを本格的に学びたいと考えている人はいますか? まずいないでしょう。「Vimテクニックバイブル」の内容ですら出版社からはリスクがあると考えられている現状において、 日本でVim scriptを学ぶための書籍が出る確率は0です。おそらく売れません。 「Vimテクニックバイブル」にはVim scriptの解説がある程度書いてあります。 しかし、一流のVim scripterになるための道はまだまだ険しいのです。

それでもVim script本の構想を諦めきれない場合は、まず「Vimテクニックバイブル」を購入し、その本に書いてあることを全てマスターしてください。 さらに「Vimテクニックバイブル」を周囲に宣伝し、全国のVimmerのVimレベルを上昇させてください。 その暁には、Vim script本の出版リスクは低減され、いつの日か発売されるかもしれません。

オマケ

今後、vim-users.jpで「Vimテクニックバイブル」に関する何かが掲載されるかもしれません。こうご期待! ちなみに、Vimテクニックバイブルを購入してもらった場合、勉強会でShougoのサインが貰えるかもしれませんよ!

Shougo

quickrun 0.5.0がリリースされました

変更点1 非同期出力

quickrunは従来から非同期実行を行っていましたが、今回さらにそれに加え、非同期出力も行うようになりました。

例:

(1..20).each do |i|
  sleep 0.2
  puts i
  STDOUT.flush
end

という内容に対し

:QuickRun -runner vimproc:100

のように実行させると、ちょっとずつ結果が出ます。(*1)

変更点2 モジュール化

ところで先ほど-runnerという新しい記法がでていました。これはquickrunのモジュール化に密接に関わってくるオプションです。

quickrun 0.5.0では、実行部分と出力部分をモジュール化しました。

runmode => runner
output => outputter

名前なども変わっております。詳しくは :help quickrun を見てください。

モジュール一覧:

  • runner
    • system
    • shell
    • vimproc
    • remote
    • python
  • outputter
    • buffer
    • message
    • variable
    • file
    • buffered
    • multi

変更点3 式展開記法

quickrun-syntax-option で {} が式展開になっていたものが、%{} に変更されました。多くの人は ~/.vimrc の変更が必要になります。これは大事なところなので、ぜひ一日三回はtweetしてください。

参考文献

http://d.hatena.ne.jp/thinca/20110529/1306677726

  • *1 すごい気がしないでもないけど、通常のプログラムは出力先が端末でない場合自動でバッファリングしちゃうみたいなので、残念ながら普段は恩恵に授かれないと思います。過度な期待はしないでください。
  • *2 ちなみに著者ujihisaは英語版documentの翻訳を行うなどしました。tyruさんとujihisaさんの英語を世界に広めましょう!

author: ujihisa

Hack #220: コマンドラインからコピペする

コマンドラインに何か赤いハイライトで出力されたけど 見えなくなってしまった場合、:messagesあるいは 短縮形である:mesと入力すれば見ることができます。 しかしそのエラーを何か別の場所(twitter,gist,…)に コピペするにはどうすればいいのでしょうか?

解決策1: gvimでマウスで選択し<C-y>を使う

gvimでのみ使える技です。

:mesと入力したあと、 図のようにマウスで選択して<C-y>を押します。 something wrong

解決策2: :redir > {file}を使う

gvimでも端末版vimでも使えます。

:redirというExコマンドを使うと、 Exコマンドの出力をキャプチャーし、 ファイルや変数に保存できます。

:redir > messages
:silent messages
:redir END

これでmessagesというファイルに出力結果が保存されます。 :silentはつけると:messagesの出力をコマンドラインに出力しません。 つけなくてもファイルの中身に変わりはありませんが、 今回はコマンドラインに出力されてもうっとうしいだけなので付けただけです。

tyru

新しいremoteプロトコルがやってくる

こんにちわ。たまにはこっちで書いてもいいかなと、ブラっと立ち寄ったmattnです。

vimには複数のインスタンス間でコマンドや式がやりとりできるremote機能があります。


# vim --servername GVIM --remote-send file.txt

こんな感じに別のvimにファイルを開かせたり


# vim --remote-expr 1+2
3

難しい計算をやってもらったり出来ます。またvimscriptからも扱えます。Windowsではウィンドウメッセージを使ってプロセス間通信が行われており、gvim.exeでもvim.exeでもやりとりが出来る様になっています。ただしLinuxではX11を使ったイベント通信が使われており、X11を入れていない、またはX11が起動していない場合にはこの素晴らしい機能を使う事が出来ませんでした。

またvimはperlやruby、pythonといったスクリプト言語を補助言語として扱う事が出来ますが、これらの言語で処理をバックグラウンドで起動させておきながら編集中にイベントを発生させるといった事が簡単に出来ませんでした。例えば、vimからLingrのchatが出来るlingr.vimがありますが、あれはバックエンドとしてpythonを使っており、発言があった場合にvimのインタフェースを呼び出しています。しかしながらvimはスレッドセーフではありません。インタフェースを呼び出した瞬間にvimが処理中であった場合には問答無用でクラッシュしてしまいます。これはvimにキーを送りつけるfeedkeys()を使っても同じです。

これまでvimhacker達はこれを回避する為に、カーソルが一定時間停止した際に発生するCursorHoldイベントを駆使してそれっぽいvimscriptを書いて来ましたが、このCursorHoldはキーが連続で押下された場合には発生しませんし、イベントが発生するまでの時間を設定出来るupdatetimeオプションはグローバルオプションである為、異なるvimscript同士が干渉しあう事もありえます。

現在、開発フォーラムであるvim_devではこれの代替とするsetInterval()の提案も行われていますが、かなり望み薄です。

vimにバックグラウンドから通知を行ったり、背後でflymakeを行ったりするvimscriptがこれまで無かったのはこれが原因です。


ところが、この問題を解決してくれるであろうプロジェクトがひっそりと始まりました。古参ユーザなら知ってる人もいるであろうYukihiro Nakadairaさんです。

これまでunixがX11で通信していた部分をunix domainソケットで、windowsがウィンドウメッセージで通信していた部分を名前付きパイプで実装を書き直しています。これにより、Xが起動していなくても、またWindowsではtelnetでログインしていたとしてもバックグラウンドから安全にメッセージを受信出きるようになるのです。

現在まだテスト中ですが、基本的な動作は既に実装済みでVIM1からVIM2へ


:echo remote_expr("VIM2", 'remote_expr("VIM1", "1+2")')

といったオウム返しも実行出来ます。すばらしいですね。

現在、おそらくテスターは僕と中平さんだけだと思いますが、皆さんがテストに参加して頂ければこのあと開発フォーラムへのプッシュも楽になると思っています。

ぜひテストに参加してみて下さい。


clientserver without X

Hack #213: ダブルクリックで単語検索するようにする

きっかけ

Vimユーザの方は一日を端末で過ごしている方も多いでしょう。 しかしマウスとはとても便利なものです。 トラックボールを使ったりすると新しい発見があるかもしれません。

キーボードで操作している時はキーボードで操作でき、 マウスで操作している時はマウスで最低限の操作はできるというのが理想です。 最低限の操作とは何でしょうか。 結論から言いますと、あなたがマウスでコードを見ている時必要だと思うことは、大半が単語検索でしょう。

  • 離れた所にある同じ単語に飛ぶ
  • 変数がどこで定義されているか調べる
  • 検索目的ではなくバッファ中にあるテキストをハイライトさせたい

など単語検索でできることは実に様々です。

自分は普通にコードを書いている時でも/コマンドをよく使います。 移動の80%はこれといっていいかもしれません。 言い過ぎだとしても70割かもしれません。 それほど汎用的なコマンドなのです。

(脱線) IDEの場合

IDEだとしたら変数にマウスオーバーした時点で定義場所などの情報がポップアップで表示されるかもしれません。 ただこういう機能は「便利すぎて」ユーザが能動的に情報を探そうとした場合邪魔になることが多いと思うのです。 ちなみにマウスオーバーした時点でポップアップするようなIDEを筆者は知りません。勘で言いました。

自動補完にもこういう側面があると私は思います。 キーをタイプしたらポップアップがめまぐるしく表示され、 頭の中にあったコードがデリートされてしまうなどといったことがありました。

Twitterでチカチカしたアイコンをした人をフォローしてる人には身に覚えがあるかもしれませんが、 気分転換にTwitterを見たらTLにアイコンがチカチカした人がいてとても気分を害されたということがあります。 この対処法としてはtermtterなどの画像が表示されないTwitterクライアントを使うことです。 ちなみにTwitter社はサードパーティ製クライアントを推奨していません

ちなみに筆者は以前自動補完はあまり好きではありませんでしたが慣れました。 自動補完プラグインとしてはautocomplpopneocomplcacheというプラグインが代表的です。 自動補完はとても便利な機能なのでぜひ使いましょう。

閑話休題

無理矢理話を戻すと、マウスでの単語検索を快適にするために必要な設定を本稿では解説したいと思います。

ダブルクリックへのマッピング

ダブルクリックへのマッピングは<2-LeftMouse>を使えばできます。

nnoremap <2-LeftMouse> g*

これで終わりでしょうか?いいえ、まだです。

これだとダブルクリックをしようとした時、 シングルクリック(<LeftMouse>)の時点で<LeftMouse>本来の操作、 つまりクリックした場所にカーソルを移動、が実行されてしまうのです。 カーソルが移動するのは多いに結構なのですが、 問題は'scrolloff'の設定も効いてしまうことです。

'scrolloff'は正の値をセットするとカーソルの上部か下部が 常に'scrolloff'分の行だけ表示されるようになるという非常に便利なオプションですが、 これがマウスのシングルクリックの時に効いてしまうと

  1. シングルクリック (クリック1回目)
  2. カーソル移動
  3. ‘scrolloff’分だけ行を開ける
  4. 表示領域がずれて、マウスカーソルが指していた場所にあった単語も移動してしまう
  5. ダブルクリック (クリック2回目)
  6. 検索するつもりじゃなかった単語を検索してしまう
  7. 一瞬何が起こったのか分からない
  8. 理解し悲しみに暮れる

ということになり非常に悲しいです。 そして「9.Vimを説得する」というのがこの記事を書くに至るまでの過程でした。 ちなみに説得というのはEmacsで言うsetqとかけています。

'scrolloff'の再実装 〜yak shaving〜

これを解決するには、つまりシングルクリック(<LeftMouse>)時の移動を抑制すればいい訳です。 しかし'scrolloff'は設定しておきたい。 ならば'scrolloff'がやることをVimスクリプトで再実装して制御可能にし、一時的に無効にすればいい訳です。 以下がその'scrolloff'の実装です。 'scrolloff'オプションの代わりにg:scrolloffグローバル変数で指定するようになっています。

set scrolloff=0
let g:scrolloff = 15

" Hack for <LeftMouse> not to adjust ('scrolloff') when single-clicking.
" Implement 'scrolloff' by auto-command to control the fire.
autocmd vimrc CursorMoved * call s:reinventing_scrolloff()
let s:last_lnum = -1
function! s:reinventing_scrolloff()
    if s:last_lnum > 0 && line('.') ==# s:last_lnum
        return
    endif
    let s:last_lnum = line('.')
    let winline     = winline()
    let winheight   = winheight(0)
    let middle      = winheight / 2
    let upside      = (winheight / winline) >= 2
    " If upside is true, add winlines to above the cursor.
    " If upside is false, add winlines to under the cursor.
    if upside
        let up_num = g:scrolloff - winline + 1
        let up_num = winline + up_num > middle ? middle - winline : up_num
        if up_num > 0
            execute 'normal!' up_num."\<C-y>"
        endif
    else
        let down_num = g:scrolloff - (winheight - winline)
        let down_num = winline - down_num < middle ? winline - middle : down_num
        if down_num > 0
            execute 'normal!' down_num."\<C-e>"
        endif
    endif
endfunction

そしてこれは:autocmdを使って実装されているので 以下のように'eventignore'オプションという Vimスクリプトを書いているような人しか知らないオプションを使って 一時的に無効にできます。

nnoremap <silent> <LeftMouse> <Esc>:set eventignore=all<CR><LeftMouse>:set eventignore=<CR>

visualstar.vim

ここまででも十分ですが、マウスで選択し、クリックで検索できたらどんなに良い事でしょうか。 visualstar.vimを使えばそれができます。

vmap <LeftMouse> <Plug>(visualstar-g*)

まとめ

ここまでのまとめとして、以下を.vimrcに貼り付ければ完了です。

set scrolloff=0
let g:scrolloff = 15

" Hack for <LeftMouse> not to adjust ('scrolloff') when single-clicking.
" Implement 'scrolloff' by auto-command to control the fire.
autocmd vimrc CursorMoved * call s:reinventing_scrolloff()
let s:last_lnum = -1
function! s:reinventing_scrolloff()
    if s:last_lnum > 0 && line('.') ==# s:last_lnum
        return
    endif
    let s:last_lnum = line('.')
    let winline     = winline()
    let winheight   = winheight(0)
    let middle      = winheight / 2
    let upside      = (winheight / winline) >= 2
    " If upside is true, add winlines to above the cursor.
    " If upside is false, add winlines to under the cursor.
    if upside
        let up_num = g:scrolloff - winline + 1
        let up_num = winline + up_num > middle ? middle - winline : up_num
        if up_num > 0
            execute 'normal!' up_num."\<C-y>"
        endif
    else
        let down_num = g:scrolloff - (winheight - winline)
        let down_num = winline - down_num < middle ? winline - middle : down_num
        if down_num > 0
            execute 'normal!' down_num."\<C-e>"
        endif
    endif
endfunction

" Do not adjust current scroll position (do not fire 'scrolloff') on single-click.
nnoremap <silent> <LeftMouse>   <Esc>:set eventignore=all<CR><LeftMouse>:set eventignore=<CR>
" Double-click for searching the word under the cursor.
nnoremap          <2-LeftMouse> g*
" Single-click for searching the word selected in visual-mode.
vmap              <LeftMouse> <Plug>(visualstar-g*)
tyru

東京電力の計画停電のグループ分けをuniteで検索する

東京電力は昨日、輪番停電のグループ分けを発表しました。

その情報を有志の方がCSVにしていただき、それをuniteと組みあわせて検索するuniteプラグインが作成されました。

東京電力圏内の方は是非これを利用して自分の地域のグループ名を確認してください。

http://codnote.net/2011/03/14/unite-teiden/

Hack #203: 定義されているマッピングを調べる

定義されているマッピングを調べたくなった時はないでしょうか。

  1. このプラグインが作ったバッファではどんなマッピングが定義されているのか
  2. 変なマッピングが定義されていないか
  3. Vimプラグインの作者と会話していてマッピングを調べるように言われた
  4. etc.

様々なケースで必要になってきます。(大半の人にとっては1のケースでしょうが)
どうやって調べればいいでしょうか。

:AllMaps

:AllMapsを使います。
次のコードを.vimrcに貼り付けましょう。

command!
\   -nargs=* -complete=mapping
\   AllMaps
\   map <args> | map! <args> | lmap <args>

kana氏の.vimrcに定義されていた:Allmapにインスパイアされたのでそちらも興味があれば参照してください。

使い方

" 全てのマッピングを表示
:AllMaps
" 冒頭で言った1のケースのように現在のバッファで定義されたマッピングのみ表示
:AllMaps <buffer>
" どのスクリプトで定義されたかの情報も含め表示
:verbose AllMaps <buffer>

短くシンプルながらも他のExコマンドと組み合わせることで効果を無限大に発揮できるExコマンドです。

:Capture

また作者が作った:CaptureというExコマンドがあります。
引数に指定したExコマンドを実行し、
コマンドラインへの出力をバッファに表示するというものです。
出力から検索したい場合などに便利です。
(筆者のブログの記事も参照してください)

command!
\   -nargs=+ -complete=command
\   Capture
\   call s:cmd_capture(<q-args>)

function! s:cmd_capture(q_args) "{{{
    redir => output
    silent execute a:q_args
    redir END
    let output = substitute(output, '^\n\+', '', '')

    belowright new

    silent file `=printf('[Capture: %s]', a:q_args)`
    setlocal buftype=nofile bufhidden=unload noswapfile nobuflisted
    call setline(1, split(output, '\n'))
endfunction "}}}

このExコマンドを使えば次のようにしてバッファに出力を書き込むことができます。

" 全てのマッピングをバッファに書き込む (/コマンドで検索できる)
:Capture AllMaps <buffer>

もう少し:Captureについて (vimshell)

vimshellではコマンドラインでの入力で先頭に:をつけるとVimスクリプトのExコマンドだと解釈してくれます。
これはvexeという内部コマンドを使っているので興味があればそちらも参照してください。
(以下$がvimshellのプロンプトだとします)

$ cd    # ホームディレクトリに移動
$ ls    # /bin/lsを実行 (実際にはlsは内部コマンドで、それが/bin/lsを呼び出しているようです)
bin git
$ :ls   # :lsを実行。バッファリストを表示
1  a   "~/memo/todo.txt"      line 0
3  a   "~/.vimrc"             line 0

とても便利でクールですね。

もう少し:Captureについて (unite.vim)

unite.vimのunite-outputというsource(:help unite-sources)を使えば
Vimスクリプトの出力をuniteバッファに取り込み、絞り込むことができます。
詳しくは:help unite-source-outputを参照してください。

tyru

Hack #195: virtualedit tip

virtualeditはすばらしいものです。 文字が存在しない部分にもカーソルを移動させることができる、 それだけなのですが筆者はこのオプションを知った時ずいぶんと移動が楽になったように感じました。 ちなみにTeraPadやApsalyなどのエディタでも「フリーカーソル」として実装されているようです。 またvirtualeditについてはHack #125も参照してください。

ちなみに自分は.vimrcで

set virtualedit=all

のように設定しています。

問題

しかし、set virtualedit=allをしているとpでのペーストで もし右端($で移動できる場所です)よりも右にいた場合に、 現在いる場所にテキストが挿入されてしまいます。

hello,$      |

$は行末の位置であり、|はカーソルです。 ここで無名レジスタ(:help registers)には「world」が入っているとします。種類はcharacterwise(:help characterwise)とします。 ここでpを押すと

hello,      world

このようになってしまいます。 私が望んだのは

hello,world

であり、余計な空白は入れてほしくありません。 set virtualedit=allだといともたやすく存在しない場所へカーソルを動かすことができるので、 ただ末尾に付け加えたいだけの場合に余計な神経を使ってしまうのです。なんとかできないでしょうか。

解決

以下のコードを.vimrcに貼り付ければ無事解決です。

if has('virtualedit') && &virtualedit =~# '\<all\>'
    nnoremap <expr> <SID>($-if-right-of-$)  (col('.') >= col('$') ? '$' : '')
    nnoremap        <SID>(noremap-p)        p
    nmap p <SID>($-if-right-of-$)<SID>(noremap-p)
endif

一行で書いてもいいでしょう。

if has('virtualedit') && &virtualedit =~# '\<all\>'
    nnoremap <expr> p (col('.') >= col('$') ? '$' : '') . 'p'
endif

<SID>マッピングや<expr>を使うとマッピングを関数のように定義できます。
また<expr>の中では式であればよく、関数も使えるのでぐんと表現力が上がります。
しかし一行で書ける範囲であれば一行で書いた方が可読性は高いでしょう。
また<SID>マッピングを使うなら最低限mapとnoremapの違いは把握してないと使えません。

tyru

Hack #187: Vimのインサートモードをより安全にする

たとえば、Vimでインサートモードに移り、テキストを入力します。 そしてインサートモードを抜けます。 間違った部分があったのでuを押します。 するとVimはインサートモード中に入力した全てのテキストを削除してしまいます。 これはインサートモードで入力した文字はまとめてundoされるというVimの仕様で、 Emacsではundoした場合20文字ごとにテキストが削除されます。 なんとかできないでしょうか?

解決

以下のコードをvimrcに貼り付けます。 するとEmacsと同じく20文字ごとに文字が削除されます。 (<C-g>uというコマンドを使っています。詳しくは:help i_CTRL-g_uを参照してください)

function! s:is_changed() "{{{
    try
        " When no `b:vimrc_changedtick` variable
        " (first time), not changed.
        return exists('b:vimrc_changedtick')
        \   && b:vimrc_changedtick < b:changedtick
    finally
        let b:vimrc_changedtick = b:changedtick
    endtry
endfunction "}}}
autocmd vimrc CursorMovedI * if s:is_changed() | doautocmd User changed-text | endif

let s:current_changed_times = 0
let s:max_changed_times = 20
function! s:changed_text() "{{{
    if s:current_changed_times >= s:max_changed_times - 1
        call feedkeys("\<C-g>u", 'n')
        let s:current_changed_times = 0
    else
        let s:current_changed_times += 1
    endif
endfunction "}}}
autocmd vimrc User changed-text call s:changed_text()

Vimではモードがあり、dやv、テキストオブジェクトを組み合わせた 高い編集能力があるのであまり問題とされていないのでしょう。 EmacsはVimで言えばインサートモードしか存在しないので、 undoした場合どこまで削除すればいいのか明確な基準がなかったために20文字としたのでしょう。

tyru

Hack #171: 編集している関数名を表示する

数あるエディタの中には現在編集中の関数名をステータスバーに表示させたりできるものがあります。
Vimでもできないでしょうか。

解決

current-func-info.vimを使います。
インストールしたあとstatuslineを次のように設定しましょう。

let &statusline = '[%{cfi#get_func_name()}()]'

こうすると現在編集中の関数名が

[func()]

のように表示されます。

cfi#get_func_name()は関数の外側にいる時は空文字を返すので
外側にいる時は「no function」と表示させたい場合は以下のようにします。

let &statusline = '%{cfi#get_func_name() == "" ? "no function" : "[" . cfi#get_func_name() . "()]"}'

これは少し面倒です。
cfi#format()というヘルパー関数を使うとこのように書けます。

let &statusline = '%{cfi#format("[%s()]", "no function")}'

current-func-infoは現在C, Perl, Ruby, Python, PHP, Vimスクリプトに対応しています。

ちなみに

statuslineは

set statusline=...

という風にセットすることもできますが

let &statusline = '...'

としたほうが空白を含む文字列をセットする時にエスケープする必要がなく便利です。

set statusline=this\ is\ my\ statusline

let &statusline = 'this is my statusline'

また

set statusline=%!...

のようにすることもできます。(:help 'statusline' 参照)

tyru

ホーム > Vim script

Search
Feeds
Links
  • 公式
  • 勉強会
  • 情報
  • コミュニティ
  • Meta
    Etc
    Creative Commons License
    This blog is licensed under a Creative Commons License.

    Return to page top