Home

Vim-users.jp

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, Vimスクリプトに対応しています。

ちなみに

statuslineは

set statusline=...

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

let &statusline = '...'

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

set statusline=this\ is\ my\ statusline

let &statusline = 'this is my statusline'

また

set statusline=%!...

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

tyru

Hack #170: テキストを折り畳む – 基本編

長いテキストやソースコードを閲覧したり編集する場合、全体の俯瞰が知りたかったり、必要のない部分を無視したいことがあります。 こういった場合、Vim の折り畳み機能が便利です。

本 Hack では何回かに分けて折り畳み機能について解説します。

Folding (折り畳み)

Vim にはテキストを折り畳むための Folding と呼ばれる機能があり、これを使うことで複数行を 1 行にまとめて表示することができます。まとめられた行には要約が表示されます。 折り畳み機能を使うことで、テキストをセクション単位や関数単位などで折り畳んで簡潔に表示することができます。

折りたたまれたテキスト

折り畳まれた行は zo で開き、 zc で閉じることができます。詳細は操作編で解説します。

折り畳みレベル

折り畳みは入れ子にすることができます。これにより、構造化された文書やソースコードを階層ごとに折り畳むことができます。 各行には折り畳みレベルというものがあり、入れ子は実際にはこれによって表現されています。折り畳みレベル 0 が、折り畳みがない状態です。

階層化された折り畳みは zR で全て開き、zM で全て閉じることができます。

折り畳みの種類

折り畳みには、以下の 6 つの種類があります。’foldmethod’ オプションに対して以下のいずれかを設定します。

概要
manual 手動で折り畳みを作成します。
marker 特定の印により折り畳みを作成します。
indent インデントによって折り畳みを作成します。
expr 式を使って柔軟に折り畳みを作成します。
syntax syntax での指定により折り畳みを作成します。
diff diff の際に変更されていないテキストを折り畳みます。

‘foldmethod’ オプションはウィンドウローカルなので、同じバッファを別のウィンドウで別の方法で折り畳むこともできます。

折り畳みの作成と削除

基本編ということで、最後に折り畳みの作成/削除の方法を簡単に紹介しておきます。

‘foldmethod’ が “manual” の場合、自分で折り畳みを作成することになります。折り畳みの作成は zf{motion} か Visual-mode で範囲を選択して zf 、もしくは :{range}fold コマンドで行います。繰り返して実行することで、折り畳みレベルを深くすることができます。

zd でカーソル位置にある折り畳みを削除できます。また、zD でカーソル位置にある折り畳みを再帰的に全て削除できます。

thinca

Hack #169: neocomplcacheを拡張する 後編

前編からかなり間が空いてしまいましたが、ここではneocomplcacheのプラグインの記述方法を解説します。neocomplcache Ver.5.1ではプラグインの構成がかなり変化したので、この記事を参考にしてください。

プラグインの仕様

プラグインはautoload/neocomplcache/sourcesにインストールしたものが自動的に読み込まれます。 プラグインには、neocomplcache#sources#プラグイン名#define()が絶対必要です。 これはneocomplcacheが初期化するときに呼ばれ、neocomplcacheにディクショナリ変数を渡します。 ここではディクショナリ変数に必要な要素について説明をします。

name

プラグインの名前です。

kind

プラグインの種類を現します。plugin, ftplugin, complfuncの三種類があります。これらの違いについては後述します。

filetypes

ftpluginにのみ存在します。どのファイルタイプで補完するかを表すディクショナリ変数です。

initialize()

プラグインの初期化時に呼ばれます。コマンドの登録等を行います。ftpluginの場合、これが呼ばれるのはfiletypesに対応するバッファで補完されたときです。

finalize()

neocomplcacheの無効化されるときに呼ばれます。ここで不要になったコマンドやautocmdを削除します。

get_keyword_list(cur_keyword_str)

pluginにのみ存在します。a:cur_keyword_strにマッチするリストを返すために呼ばれる関数です。get_keyword_list()が返す補完リストは、特定のキーを含むディクショナリのリストとなっています。詳しくは「補完リストの仕様」の項を参照してください。

get_keyword_pos(cur_text)

ftpluginとcomplfuncに存在します。cur_textにマッチする補完位置を返します。

get_complete_words(cur_keyword_pos, cur_keyword_str)

ftpluginとcomplfuncに存在します。a:cur_keyword_strにマッチするリストを返すために呼ばれます。get_complete_words()が返す補完リストは、特定のキーを含むディクショナリのリストとなっています。詳しくは「補完リストの仕様」の項を参照してください。

補完リストの仕様

get_keyword_list()get_complete_words()が返す補完リストは、特定のキーを含むディクショナリのリストとなっています。一部のキー以外はVim標準の補完で使用するものと同じです。

word, abbr, menu, info, icase, dup

Vim標準の補完で使用するものと同じです。word以外は省略することができます。詳しい解説は、[Hack #14: ]Insert mode補完 自作編を参照してください。 menuはどのプラグインの候補で補完しているかを[B]のような記号で表す習慣になっています。ftpluginは[vim]や[ghc]のように、長めの文字列を使います。

プラグイン用ヘルパ関数

autoload/neocomplcache.vimには、プラグインから呼び出せるようにヘルパ関数が実装されています。ここでは、よく使われる関数について解説します。

neocomplcache#keyword_filter(list, cur_keyword_str)

get_keyword_list()で使用できる、単純なフィルターです。a:listの中から、a:cur_keyword_strにマッチするリストを返します。filter()とは違って、listは変更されるとは限りません。

neocomplcache#unpack_dictionary(dict)

リストの辞書をリスト化して返します。

neocomplcache#unpack_dictionary_dictionary(dict)

辞書の辞書をリスト化して返します。

neocomplcache#keyword_escape(cur_keyword_str)

a:cur_keyword_strをマッチングに使えるようにエスケープします。

neocomplcache#get_cur_text()

現在のカーソル文字列を取得します。

neocomplcache#get_completion_length(plugin_name)

plugin_nameの自動補完する文字列長を返します。

neocomplcache#set_completion_length(plugin_name)

plugin_nameの自動補完する文字列長を設定します。ただし、これはプラグイン側で初期値を設定するためのもので、ユーザーが補完文字列長を設定している場合、そちらが優先されます。

neocomplcache#get_keyword_pattern_end(filetype)

文字列の最後にマッチするfiletypeのキーワードパターンを返します。filetypeは省略可能で、省略すると現在のバッファのfiletypeを参照します。

neocomplcache#get_keyword_pattern(filetype)

文字列にマッチするfiletypeのキーワードパターンを返します。filetypeは省略可能で、省略すると現在のバッファのfiletypeを参照します。

neocomplcache#is_auto_complete()

自動補完の時に1を返します。

neocomplcache#print_caching(string)

キャッシュ時のメッセージを表示します。

neocomplcache#print_error(string)

エラーメッセージを表示します。

キャッシュ用ヘルパ関数

autoload/neocomplcache/cache.vimには、プラグインから呼び出せるキャッシュのヘルパ関数が含まれます。 量が多いので、ここでは詳しく説明することは避けますが、うまく利用すると簡単にキャッシュを使ったプラグインを記述できます。 ちなみに、neocomplcache Ver.4以降では、ほとんどのプラグインがキャッシュ用ヘルパ関数を使うように書き直されています。

プラグインのサンプル

neocomplcacheに標準添付のプラグインを参考にしても良いのですが、機能が複雑化しているため、プラグイン作りの勉強のために見るのは大変です。 eagletmtさんが作成したghc_completeはfiletype pluginでほどよい長さなので、勉強に最適でしょう。

plugin, ftplugin, complfuncの違い

neocomplcache Ver.3.00より、complfuncが実装され、より自由度の高い補完が実装できるようになりました。 pluginとcomplfuncの違いは、pluginはカーソル前のキーワードから補完しますが、complfuncは独自に補完位置を決定できるというところです。 ftpluginとはneocomplcacheのオムニ補完です。 基本的な仕様はcomplfuncと同じです。ただし、必要な時にのみ初期化や呼び出しされるというところが違います。

Shougo

Hack #168: シェル以外から立ち上げたVimでもシェル側の環境変数PATHを考慮したコマンドの呼び出しを行う

問題

:!ruby %

このコマンドが呼び出すrubyとして期待されるものは、/usr/bin/rubyであったり、/usr/local/bin/rubyであったり、はたまた~/git/ruby/local/bin/rubyのように独自で用意したものであったりします。

zshなどのシェルでは、~/.zshrcなどの設定ファイルに

export PATH=~/git/ruby/local/bin/ruby:$PATH

などと記述することによって、単にrubyなどとしてコマンドを呼び出したときに実際にどの場所のコマンドが呼び出されるか制御でき、またそのシェルから起動したVimもそれに準拠します。これはCUIでもGUIでも同様です。

しかしながら、シェルを経由せずVimを起動した場合。~/.zshrcなどに記述したロードパスに関する情報は得られません。MacのDockなどから起動しつつ、そのVimであなたのホームディレクトリ以下にあるrubyなどを呼び出すにはどうすればいいのでしょうか。

解決法

vimprocを用います。vimprocはVimの変数$PATHを参照してコマンドを実行します。

vimprocを用いてのコマンドの実行とVimのデフォルトの機能との対応は以下のようになります。

  • コマンドを単に実行する

    • Vim: :!command
    • vimproc: :call vimproc#system('command')
  • コマンドを実行した結果をバッファに書き足す

    • Vim: :r!command
    • vimproc: :call append(line('.'), vimproc#system('command'))
  • コマンドを実行した結果を変数に格納する

    • Vim: :let x = system('command')
    • vimproc: :let x = vimproc#system('command')
  • コマンドをバックグラウンドで実行する

    • Vim: :!command &
    • vimproc: :call vimproc#system_bg('command')

冗長で不便なので、キーマッピングを追加するか、あるいは:!の使用をさけてかわりにvimshellを用いるとよいでしょう。

nnoremap :! :call vimproc#system('

さて、:!system()を間接的にもっとも頻繁に使うのはなんといってもquickrunでしょう。quickrunでvimprocを用いるためには、以下の設定を~/.vimrcに記述します。

let g:quickrun_config['*'].runmode = "async:remote:vimproc"}

余談ですが、著者はこれにquickrun分割場所指定もあわせ、以下のように指定しています。

let g:quickrun_config['*'] = {'runmode': "async:remote:vimproc", 'split': 'below'}

これで、quickrunで好きなrubyを使いたい放題です。

補足

本Hackは一般的な外部コマンドの実行について述べましたが、この方法は特に、Rubyのような複数の同名のコマンドをインストールする必要があるようなコマンドで役に立ちます。著者はRuby 1.8.6, 1.8.7, 1.9.2, 1.9.3をすべて使用しているため、本設定が大変効いてきています。

なおVimによるRubyプログラミングをより効率的かつ快適に行うための方法については、"Vim" at RubyKaigiに参加し、基調講演を聞く、ライトニングトークの発表を聞く、ライトニングトークで発表する、そしてほかの参加者とその場で情報交換することによって、活き活きとした生の情報を大量に得ることができることは疑いの余地がないでしょう。

参考文献

ujihisa

Vim 7.3 がリリースされました

少し告知が遅れましたが、ついにVim 7.3がリリースされました。
それぞれのプロジェクトの動向を見てみましょう。
※大幅に加筆修正しました。

本家

http://code.google.com/p/vim/
ダウンロードは以下のページからできます。
http://www.vim.org/download.php

Kaoriya

http://www.kaoriya.net/
Kaoriyaからは7.3はまだ出ていません。

MacVim

http://code.google.com/p/macvim/
メインブランチではないものの、別ブランチ(macvim73)で7.3が公開されているようです。
じきにメインブランチにマージされるものと思われます。
※splhackさんによるとSnow Leopard限定のようです。

MacVim-Kaoriya

http://code.google.com/p/macvim-kaoriya/
http://blogger.splhack.org/2010/08/macvim-kaoriya-20100817.html
Mac OS Xなら現在こちらが提供しているdmgファイルからインストールするのが一番手軽でしょう。
※splhackさんによるとMacVim-KaoriYa 20100817はOS X 10.5ppc/10.5intel/10.6で動作するとのことです。

またリポジトリのそれぞれのブランチは次のような構成になっています。

  • kaoriya73
    • Kaoriya + 7.3
  • macvim73
    • MacVim + 7.3
  • macvim73-kaoriya
    • MacVim + Kaoriya + 7.3

どこのプロジェクトのブランチをベースにしたものかなどはwikiを参考にしてください。

その他のURL

Hack #167: Vimスクリプトで無名関数やクロージャを使う方法

無名関数

function! s:foo()
    let foo = {}
    function foo.funcall() dict
        echo 'lambda'
    endfunction
    return foo
endfunction

call s:foo().funcall()

クロージャ

function! s:foo(num)
    let foo = {'i': a:num}
    function foo.funcall() dict
        let self.i += 1
        return self.i
    endfunction
    return foo
endfunction

echo s:foo(1).funcall()
let s:clos = s:foo(5)
" 6
echo s:clos.funcall()
" 7
echo s:clos.funcall()
" 8
echo s:clos.funcall()

説明

Vimスクリプトでは辞書型に関数をキーとして代入することができます。
その場合関数はほぼ無名のような存在になります。
また辞書型に格納した「dict」つきの関数からはその辞書を「self」という変数で参照できるので
辞書に関数内で使う変数などを辞書に保存しておけば関数内からその変数を参照できる、いわば疑似的なクロージャを実現することができます。

  1. 自分で変数を渡す必要がある
  2. obj.funcall() を自分で呼ぶ必要がある

などなど他言語と比べかなりプリミティブですが、これを駆使すればVimスクリプトでも現実的に無名関数やクロージャが扱えることがわかるでしょう。

またVimスクリプトでは辞書型を使ったプロトタイプ指向によりクラスなども扱うことができます。
そこまでしなくても辞書型を活用することでモジュールを分けられるのでいろんな活用方法があります。

tyru

Wanted: Lightning talkers at the “Vim” sub-event in RubyKaigi 2010

Requirements

  1. RubyKaigi 2010 Conference Pass (Don’t you have one yet?)
  2. Passion to talk about Vim

About presentation

Theme: Anything which is related to both Vim and Ruby.

  • Time limit: 5 minutes (not including question-and-answer session)
  • Spoken language: English or Japanese
  • Please use xx-large font for live Vim session.

Application

Please send email to vimkaigi2010 at googlegroups.com with the following information:

  • Subject: “Vim at RubyKaigi2010 LT Proposal”
  • Your name (real name and/or handle, you may conceal either of both names if you want so)
  • Self-introduction (for example: the size of ~/.vimrc, Vim plugins you made)
  • Title of your presentation
  • Its abstract
  • Anything else (message to the organizer of this sub-event)

Editor: kana

Hack #166: ローマ字の大文字/小文字を変換する

ローマ字の大文字と小文字を変換する機会は意外に多いです。なので、Vim にはこれを行うための便利な機能があります。

~

~ を押すと、カーソル下のローマ字の大文字/小文字を相互に変換します。大文字は小文字に、小文字は大文字になります。この際、カーソルを右に進めます。 [count] を指定することで複数の文字を同時に変換することができます。変換は一括で大文字/小文字にするのではなく、文字単位で作用します。つまり VimHack は vIMhACK になります。

gu gU g~

これらはオペレータで、対象に対してそれぞれ、gu は小文字への変換を、gU は大文字への変換を、g~ は大文字/小文字の相互変換を実行します。 例えば、現在のカーソルのある単語を全て大文字にしたい場合は gUiw です。 また、yy などと同様に行に対して動作する gugu guu gUgU gUU g~g~ g~~ があります。

Visual mode での u U ~

これらは Visual mode では g なしで動作します。

'tildeop'

'tildeop' オプションをオンにすると、~ はオペレータに変化します。g~ を頻繁に使う場合には便利でしょう。

正規表現

もっと複雑な変換を行いたい場合もあるでしょう。正規表現で置換する際、結果の大文字/小文字を指定することができます。 置換後のパターンに u があると、次の文字は大文字になります。l があると小文字になります。

:s/\w\+/\u\0/g
"bram moolenaar" → "Bram Moolenaar"

また、U や L があると、E が出現するまでそれぞれ大文字/小文字に変換します。

thinca

RubyKaigi2010企画 “Vim” におけるライトニングトークの発表を募集します

参加条件

  1. RubyKaigi2010参加チケットをもっている (お持ちではないですか? まだ間に合います)
  2. Vimについて語りたい熱い気持ちをもっている

発表について

内容はVimかつRubyに関することならばなんでもよいです。

  • 発表時間は一人5分。時間を超過すると問答無用で次の人が割り込んで発表を開始します
  • 口頭の言語は日本語または英語
  • Vimを画面にうつすときはかなり大きなフォントサイズで

応募方法

以下の情報を記載して vimkaigi2010 at googlegroups.com にメールを送信してください。subjectは “Vim at RubyKaigi2010 LT Proposal” などにしてくださると分かりやすいです。

  • 発表者の名前 (公開されます。実名でなくともかまいません。例: 漆黒の竜)
  • 発表者の自己紹介 (~/.vimrcの行数、vim.orgやgithubに公開しているプラグインなど)
  • 発表タイトル
  • 発表概要
  • その他 “Vim” 運営者にメッセージ, 自己紹介など

文責: ujihisa

Hack #165: neocomplcache Hacks(6) インクルード補完

今回はインクルード補完です。neocomplcacheに実装されたインクルード補完はあらかじめ設定しておく必要がありますが、使いこなせばタグ補完を越えた使い勝手となります。

インクルード補完とは

インクルード補完とは、バッファ中のインクルード文を解析して、補完候補に加える補完のことです。Vim自体にもインクルード補完が備わっていますが、Perlなど'path'が多数のディレクトリに設定されている言語では重すぎて使いものになりません。neocomplcacheのインクルード補完は結果をキャッシュすることで、Vim標準のインクルード補完に存在する欠点を補うために開発されました。タグ補完と比較すると、インクルードしているファイルだけ解析するので補完候補が多すぎる問題が発生しにくい、あらかじめタグファイルを生成する必要がない、といった利点があります。

インクルード補完の制限

インクルード補完は強力ですが、万能ではありません。'path''includeexpr', 'include'といったオプションが適切に設定されている必要があります。特にWindows環境では、ftpluginなどで設定する必要があるかもしれません。インクルード補完ではctagsを利用するので、システムにインストールされている必要があります。ctagsが存在しなかったり、ctagsに対応していない言語の場合(D言語など)はバッファをそのまま解析するので、buffer_completeと動作が同じになります。

今後のインクルード補完

現在実装されているインクルード補完はまだ実験的な意味合いが強いです。 今後は、gtagsへの対応やechodocへの対応、遅延キャッシュなどを考えています。 ただしgtagsはカレントディレクトリにタグファイルを作るらしく、ctagsのように簡単に解析するのは難しそうです。

参考文献

neocomplcache.vim のインクルード補完の使い方 thincaさんのインクルード補完解説記事。neocomplcache Ver.3.06を対象としていて、neocomplcache Ver.5.0がリリースされた現在では変数名等が古くなっていますが、参考になると思います。

Shougo

Home

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

    Return to page top