Home > Vim Hacks

Vim Hacks Archive

Hack #161: Command-line windowを使いこなす

普段我々が何げなく使っているCommand-line modeですが、使いこなすうちに様々な欠点が目につきます。このHackでは、Command-line modeを捨て去ってしまうことを提唱します。

Command-line modeの欠点

なぜCommand-line modeが使えないかというと、次のような欠点があるからです。

編集能力が貧弱

Command-line modeは基本的にラインエディタなので、シェル並の編集しかできません。テキストオブジェクトといった便利な機能も使えないのです。

自動補完ができない

もはや筆者は自動補完のある環境が普通になってしまい、neocomplcacheがないと仕事になりませんが、残念ながらCommand-line modeでは使えません。さらに、Command-line modeは補完も貧弱なので、困ったものです。

設定が分散する

Insert modeとCommand-line modeは独立しているので、キーマップ等は別々に定義しなければなりません。これは不便です。

履歴検索が面倒

Command-line modeでは、履歴検索が簡単にはできません。

cnoremap <C-n>          <Down>
cnoremap <C-p>          <Up>

とキーマップを定義する手はあります。これなら現在入力されているものにマッチする候補を検索することができます。しかしvimshellのように一覧から履歴を検索する方法はなく、そもそも設定が面倒です。検索にはfuzzyfinderkuを使うという手もありますが、この程度のことで外部プラグインに依存するというのもどうでしょうか。

Command-line window

そこで、本HackではCommand-line modeの代わりに、Command-line windowという機能を使うことを提案します。 Command-line windowとは何かというと、Vimに組み込まれている、Ex commandを実行できるバッファのことです。 Command-line windowは'filetype'がvimであるため、Vimのvim filetype pluginがすべて使えます。 特にneocomplcacheはVimのオムニ補完を搭載し、ユーザー定義のコマンドも解析できるため、併用するとneocomplcacheのパワーを存分に発揮することができます。 neocomplcacheは補完だけでなく、コマンドの引数情報をエコー領域に表示することもできます。 neocomplcacheに実装されている、Vimのオムニ補完は仕組みが複雑なので、今後のVim Hacksで詳しく解説する予定です。 Command-line windowについて詳しい情報は、:help cmdwinを参照してください。

Command-line windowを設定する

Command-line windowはウインドウに入ったときにInsert modeにならなかったり、neocomplcacheと相性が悪かったりして使いづらいので、カスタマイズする必要があります。筆者は.vimrc中で、次のように設定しています。この設定では:を入力したときにCommand-line windowに遷移するようにしています。CmdwinEnterにautocmdを設定すれば簡単にカスタマイズできるので、皆さんも最適な設定を探してみてください。

nnoremap <sid>(command-line-enter) q:
xnoremap <sid>(command-line-enter) q:
nnoremap <sid>(command-line-norange) q:<C-u>

nmap :  <sid>(command-line-enter)
xmap :  <sid>(command-line-enter)

autocmd MyAutoCmd CmdwinEnter * call s:init_cmdwin()
function! s:init_cmdwin()
  nnoremap <buffer> q :<C-u>quit<CR>
  nnoremap <buffer> <TAB> :<C-u>quit<CR>
  inoremap <buffer><expr><CR> pumvisible() ? "\<C-y>\<CR>" : "\<CR>"
  inoremap <buffer><expr><C-h> pumvisible() ? "\<C-y>\<C-h>" : "\<C-h>"
  inoremap <buffer><expr><BS> pumvisible() ? "\<C-y>\<C-h>" : "\<C-h>"

  " Completion.
  inoremap <buffer><expr><TAB>  pumvisible() ? "\<C-n>" : "\<TAB>"

  startinsert!
endfunction

追記: Command-line windowでは、altercmdが使用できません。これでは不便なので、tyruさんがCommand-line windowでも使えるように改造したものを公開しているので、こちらを使ってください。 私は次のように設定しています。

function! s:init_cmdwin()
        call altercmd#define('b', 'gr[ep]', 'Grep', 'i')
        " AlterCommand <buffer><mode:i> gr[ep] Grepでも可
endfunction
Shougo

Hack #160: JavaScript開発環境

問題

Vimのデフォルトの状態でJavaScriptのコードを書くと、以下のような問題が発生します。

  1. インデントがおかしい

    var a = {
      a_
    

    この状態で:を打鍵しますと、

    var a = {
    a:_
    

    のようにインデントが一つもどってしまいます。

  2. キーワードがおかしい

    jQuery時代、$ではじまる変数名を使う機会が増えています。

    var $a = 1;
    

    このaの位置から*を打鍵しますと、$aではなくaという単語だけを検索対象にしてしまいます。

  3. 予約語functionが長い

    JavaScriptでは関数定義時だけでなく無名関数を用いるときにもfunctionという長い予約語を打鍵する必要があります。

解決法

いつくかのプラグインを導入します。

  1. JavaScript syntax プラグインの導入

    http://www.vim.org/scripts/script.php?script_id=1491

  2. Javascript Indentation プラグインの導入

    http://www.vim.org/scripts/script.php?script_id=1840

    var a = {
      a_
    

    この状態で:を打鍵しますと、

    var a = {
      a:
    

    のようになります。

    このプラグインはIndentAnythingというライブラリを使用しているため、こちらのライブラリも導入する必要があります。

    http://www.vim.org/scripts/script.php?script_id=1839

  3. smartchr.vimプラグインの導入

    たとえばプログラミング言語Haskellでは、無名関数を作成するにあたってバックスラッシュを使用します。

    map (\x -> f (x * 2)) [1, 2, 3]
    

    これはJavaScriptでは, jQueryを用いると

    $.map([1, 2, 3], function(x) { return f(x * 2); });
    

    となります。このことから類推すると、\と打鍵することでfunction(と入力されることが望ましいことが分かるのですが、 文字列リテラル内で\を入力するときにfunction(と展開されてしまうと開発に大きな支障をきたしてしまいます。

    文脈に応じて\キーの意味を動的に変更させるという解決方法もありますが、もっと単純にsmartchr.vimを用いて、\一回打鍵するとfunction(に展開し、その状態でもう一度\を打鍵すると\になるという挙動をとるようにすれば、シンプルにして必要十分な解決策となりうるのでないかと筆者は思っています。

    smartchr.vimについて詳しくはHack #131: Rubyで#{をラクに入力するをご覧ください。

    smartchr.vim導入後、以下の設定を~/.vimrcに記述しましょう。

    augroup Ujihisa " {{{
      autocmd!
      autocmd FileType javascript inoremap <buffer> <expr> \  smartchr#one_of('function(', '\')
    augroup END
    

    あるいは、以下の設定を~/.vim/ftplugin/javascript/ujihisa.vimに記述しましょう。

    inoremap <buffer> <expr> \  smartchr#one_of('function(', '\')
    

補足

そもそもJavaScriptを直接記述するのを避け、CoffeeScriptで代用するという手もあります。

ujihisa

Hack #159: オプションの値を気にせずsplit, vsplitする

Vimの標準のコマンドである:split:vsplit、 またはそのマッピング版である<C-w>s<C-w>vは それぞれ&splitbelow&splitrightに依存しており、 自分の思った通りの方向にウインドウを開いてくれない場合があります。

そこで、このようなマッピングを定義します。

nmap spj <SID>(split-to-j)
nmap spk <SID>(split-to-k)
nmap sph <SID>(split-to-h)
nmap spl <SID>(split-to-l)

nnoremap <SID>(split-to-j) :<C-u>execute 'belowright' (v:count == 0 ? '' : v:count) 'split'<CR>
nnoremap <SID>(split-to-k) :<C-u>execute 'aboveleft'  (v:count == 0 ? '' : v:count) 'split'<CR>
nnoremap <SID>(split-to-h) :<C-u>execute 'topleft'    (v:count == 0 ? '' : v:count) 'vsplit'<CR>
nnoremap <SID>(split-to-l) :<C-u>execute 'botright'   (v:count == 0 ? '' : v:count) 'vsplit'<CR>

こうすることでいつでも自分の思った通りの方向にウインドウを開くことができます。

また

nmap spj <SID>(split-to-j)
nmap spk <SID>(split-to-k)
nmap sph <SID>(split-to-h)
nmap spl <SID>(split-to-l)

の部分は自分の好きなように変えてください。 筆者は上のようにそれぞれspj, spk, sph, splに割り当てています。

追記: kana氏の指摘によりコードを大幅修正しました。

追記2: [count]を取れるようにしました。30sphなどとすると30の幅を持つウインドウが左に開きます。 ちなみに現在筆者はマッピングを<Space>sj, <Space>sk, <Space>sh, <Space>slに変更しました。 押しやすいマッピングはVimmerの数だけあるので、各人押しやすいマッピングを常に追求しましょう。 ちょっとでも押しにくいと感じたら積極的に他のマッピングを検討すべきです。

tyru

Hack #158: ユーザコマンドを定義する

: でコマンドラインモードに入ると使えるコマンドは、ユーザが自由に定義することができます。

定義方法

:command コマンドを使用します。書式は以下のようになります。

:command[!] [{属性}...] {コマンド名} {実行するコマンド}

これを見てわかるように、コマンドを定義すると言うことは誤解を恐れずに言うと別のコマンドに対するショートカットを定義しているに過ぎません。 複雑なことをしたい場合、ここは大抵関数の呼び出しになります。 :command 自体に ! を付けた場合、同名のコマンドが定義済みだった場合に上書きします。通常はエラーになります。

コマンド名

コマンド名は、組み込みコマンドと区別が付くように大文字で始めなくてはいけません。また、コマンド名には英数字のみ使用できます。

属性

属性は、-{属性名} もしくは -{属性名}={引数} の形式で指定します。詳細な説明は :help に譲るとして、ここでは概要を紹介します。

-nargs
コマンドの引数の数を指定します。
-nargs=00 個
-nargs=11 個
-nargs=*0 個以上
-nargs=?0 個もしくは 1 個
-nargs=+1 個以上
記号は正規表現と同じと考えれば覚えやすいでしょう。この属性を指定しなかった場合、0 (引数なし) を指定したことになります。
-complete
コマンドの補完方法を指定します。
-complete=augroupオートコマンドのグループ
-complete=bufferバッファ
-complete=commandEx コマンド(と、引数)
-complete=dirディレクトリ
-complete=environment環境変数
-complete=eventオートコマンドのイベント
-complete=expressionVimの式
-complete=fileファイルとディレクトリ
-complete=shellcmdシェルコマンド
-complete=function関数
-complete=helpヘルプの主題
-complete=highlight強調グループ
-complete=mappingマップ
-complete=menuメニュー
-complete=optionオプション
-complete=tagタグ
-complete=tag_listfilesCTRL-D を押した時にタグ、ファイル名を表示
-complete=varユーザ変数
-complete=custom,{func}{func}によるユーザ定義の補完
-complete=customlist,{func}{func}によるユーザ定義の補完
custom や customlist では関数を指定できますが、ここでは割愛します。
-range
コマンドに範囲(:[range]Command)を指定できるようにします。この属性がない場合、範囲の指定はできません。属性の引数で無指定時の初期値を指定します。
-range範囲指定。無指定時は現在行
-range=%範囲指定。無指定時はファイル全体(1,$)
-range=N範囲指定。無指定時は任意の数字 N
-count
コマンドにカウント(:[N]Command [N]) を指定できるようにします。この属性がない場合、カウントの指定はできません。属性の引数で無指定時の初期値を指定します。
-countカウント指定。無指定時は 0
-count=Nカウント指定。無指定時は任意の数字 N
コマンドにカウントを両方(コマンドの前と後)に指定した場合、後に指定したものが有効になります。
-bang
コマンドに ! を付けられるようになります。
-bar
コマンドの後ろに | を付けることで別のコマンドを実行することができます。また、" はコメントの開始になります。 コマンドの引数に | や " を含めたい場合は、| や " とします。 別の言い方をすると、普通に定義したコマンドの引数は :map 系のコマンドのように扱われますが、-bar を付けることでその他のコマンドのような扱いになります。
-register
:delete:yank のように、1つ目の引数にレジスタ名を指定できます。
-buffer
バッファローカルなコマンドになります。

{実行するコマンド}で使える書式

実行するコマンドを指定する箇所では、以下の <…> の形式の特別な文字列を使用できます。

<line1>
指定された範囲の最初の行
<line2>
指定された範囲の最後の行
<count>
与えられたカウント
<bang>
-bang がある場合で、コマンドが ! 付きで実行された場合は ‘!’ と言う 1 文字に、それ以外は空文字列になります。
<reg> <register>
レジスタ名に置換されます。指定なしの場合は空文字列になります。
<args>
与えられた通りのコマンド引数。カウントやレジスタは含まれません。
<lt>
‘<’文字。特別な文字列をそのままの意味で使用したい場合に使います。

特別な文字列の最初に q- を加えると、式の文字列として扱えるようにクォートされます。 例えば、<args> の代わりに <q-args> を指定すると abc は "abc" に、a"bc は "a\"bc" に置き換えられます。引数がない場合は空文字列になります。

<f-args> を使うと、引数を空白で区切ったものを関数の引数として渡せるようにそれぞれをクォートしてカンマで区切ったものに展開します。 実際のルールはもう少し複雑です。詳細は :help <f-args> を参照してください。

thinca

Hack #157: neocomplcache Hacks(5) タグ補完 ディクショナリ補完

今回はタグ補完とディクショナリ補完です。タグ補完は微妙ですが、ディクショナリ補完は便利に使えるでしょう。

タグ補完とは

タグ補完とは、’tags’から補完候補を取ってくることで補完することです。 Vim標準では<C-x><C-v>を用います。 neocomplcacheではtags_completeというプラグインによって実装されています。 .->といったg:neocomplcache_member_prefix_patterns[&filetype]にマッチする入力のあるときに補完を行うと、 クラスのメンバのみが補完候補となる機能を持っています。 要望があったので実装しましたが、私は個人的にタグ補完が好きではありません。なぜなら、タグ補完は候補が多くなりすぎるからです。 候補が多いとneocomplcacheのキャッシュや補完動作が明らかに遅くなります。 そこでtags_complete.vimでは、g:neocomplcache_caching_limit_file_sizeよりも大きいタグファイルは自動的にキャッシュしません。 どうしても使いたいならば、:NeoComplCacheCachingTagsコマンドを実行してください。 ctagsではタグを生成できない言語も多いので、現在ではより高機能なインクルード補完を用いるべきでしょう。インクルード補完については、今後のVim Hacksで解説予定です。

ディクショナリ補完とは

ディクショナリ補完とは、登録された辞書ファイルから補完候補を取ってくることで補完することです。 前回解説したシンタックス補完も一種のディクショナリ補完と言えます。 Vim標準では<C-x><C-k>を用います。 neocomplcacheではdictionary_completeというプラグインによって実装されています。 g:neocomplcache_dictionary_filetype_lists[&filetype]に辞書ファイルを登録しておけば、自動的にキャッシュされます。 例えば、vimshellでは履歴ファイルを辞書ファイルとして登録しておけば便利です。 g:neocomplcache_dictionary_filetype_lists[&filetype]が存在していない場合、自動的に’dictionary’の値が使われます。

Shougo

Hack #156: PHPで配列リテラルを楽に入力する

問題

プログラミング言語Ruby, JavaScript, Vim scriptにおける配列は角括弧のみで構成された配列リテラルを用いて[1, 2, 3]のように表現することができます。一方、PHPというプログラミング言語ではarray(1, 2, 3)のように、arrayという予約語を用いて表現する必要があり、このことがRuby, JavaScript, Vim scriptプログラマを当惑させてきたという伝統があります。

<?php [1, 2, 3] ?>
#=> Parse error: syntax error, unexpected '[' in a.php on line 1

<?php array(1, 2, 3) ?>
#=> (nothing)

解決法

[array(と入力するようにします。ただしこのままだと[自体を入力したいときに困りますので、文脈に応じて挙動を変化させます。

PHPのFiletype Pluginファイルに以下のコードを追加します。

function! s:last_char()
  return matchstr(getline('.'), '.', col('.')-2)
endfunction
inoremap <buffer><expr> [ a:last_char =~ '\w\\|]' ? '[' : 'array(')

Filetyle Pluginは~/.vim/ftplugin/{filetype}.vimあるいは~/.vim/ftplugin/{filetype}/*.vimです。とりあえずすぐに上記機能を導入したいのであれば、

~/.vim/ftplugin/php/ujihisa.vim

に上記4行のみを記述すればよいでしょう。

上記設定を導入すると、英数文字あるいは]の直後に[を打鍵すると[がそのまま入力され、そうでない文字の直後ならばarray(に展開されます。

もう少し詳しく説明しましょう。そもそもPHPで[という記号を入力する必要があるのは、配列の要素を参照するときでしょう。配列の要素を参照するのは、カーソル位置を_で示すとして

print($aaa_

のように変数名の直後か、

print($aaa['bbb']_

このように配列の要素の参照の直後です。なお、fff()['aaa']といった書き方は言語仕様上Syntax Errorとなるので)の直後に[がくることはないと仮定できます。

それ以外の場合は[が必要ないので、全てarray(に展開します。

補足1

PHPのarray()はてっきり関数だと思っていたのですが、公式ドキュメントによるとリテラルとのことです。

Note: array() is a language construct used to represent literal arrays, and not a regular function.

http://www.php.net/manual/en/function.array.php

補足2

s:last_char()という関数で定義した、カーソルの直前位置の文字を取得する機能に関連して、カーソル位置の文字を取得する機能の実装が以下のページで議論されています。Vim scriptを書く人は参考にしてみてはいかがでしょうか。

http://gist.github.com/444017

補足3

はじめは[1, 2, 3]といった記法でも配列となるようにPHPのパーサの方をいじろうと思ったのですが、PHPをビルドするためにはかなり古いバージョンのautoconfが必要で、それをインストールするのが大変面倒そうであったため、挫折しました。

補足4

冒頭のサンプルコード

<?php array(1, 2, 3) ?>

はセミコロンがないことからエラーになりそうで、実はエラーになりません。

補足5

いろいろあって、いま著者の~/.vim/ftplugin/php.vimの該当部分以下のようになっています。

function! s:last_char()
  return matchstr(getline('.'), '.', col('.')-2)
endfunction

function! s:php_smart_bracket(last_char)
  if a:last_char == '['
    return "\<BS>("
  elseif a:last_char =~ '\w\|]'
    return '['
  else
    return 'array('
  endif
endfunction

inoremap <buffer><expr> [ <SID>php_smart_bracket(<SID>last_char())
inoremap <buffer><expr> ] smartchr#one_of(']', ')')

smartchrプラグインと組み合わせ、[を二回打鍵すると(になるようにしています。そもそもPHPでは[[は必ず出現しないため、わざわざ(を打鍵するよりもより容易な[[を用いるのが合理的と判断したためです。

ujihisa

Hack #154: タグジャンプをさらに活用する

タグジャンプをさらに活用する

Hack #43ではタグについての基本的な使用方法をまとめました。 本稿ではさらに踏み込んだタグジャンプの活用法をまとめます。

親ディレクトリにあるタグファイルを指定

もし自分が/project/a/src/というディレクトリにいた場合に、できれば/project/a/tagsや、 または全てのプロジェクト用のタグファイル(ライブラリの関数など)もタグジャンプに使いたいとします。

/project/a/src/ (現在のディレクトリ)
/project/a/tags (指定したいタグファイル)
/project/tags   (指定したいライブラリ関数のタグファイル)

その場合、.vimrcには以下のように書くことで可能になります。

if has('path_extra')
    set tags+=tags;
endif

こうすることで、もしタグファイルが存在するなら /project/a/tags/project/tagsにある関数も<C-]>で飛ぶことが可能になります。 また;+path_extra機能がサポートされていない場合では使えないため、 has('path_extra')で機能の有無をチェックしています。

階層数を指定

ただ;をつけただけではルートディレクトリまでさかのぼってしまいます。 そこで;の後に上限となる親ディレクトリを指定することができます。

if has('path_extra')
    set tags+=tags;/project/a
endif

こうすることで/project/aまでで検索を終了し、/project/tagsは見つかりません。

子ディレクトリにあるタグファイルを指定

前項では親ディレクトリのtagsを指定しましたが、 今度はある特定のディレクトリにあるタグファイルを 現在のディレクトリから指定したい場合はどうすればいいでしょう。

/project/a/src/          (現在のディレクトリ)
/project/a/src/libA/tags (指定したいタグファイル)
/project/a/src/libB/tags (指定したいタグファイル2)

その場合、以下を.vimrcに書けばいいでしょう。

if has('path_extra')
    set tags+=./*/tags;
endif

また、/project/a/src/libA/tagsなどの1階層下のディレクトリにあるタグファイルだけではなく /project/a/src/libA/src/tagsなどの何階層か下のタグファイルを指定するには以下のようにできます。

if has('path_extra')
    set tags+=./**/tags;
endif

階層数を指定

ただ**は30階層までの深さのディレクトリにマッチするということになっています。 なので場合によっては非常に重くなるかもしれません。 その場合は階層の深さの最大値を次のように指定することができます。 (この例では3階層下のディレクトリまでマッチするように設定しています)

if has('path_extra')
    set tags+=./**3/tags;
endif

親ディレクトリから**を使う

これは前項と前々項の合わせ技です。 現在のディレクトリが/project/a/srcの時に

set tags=**;

とすると、

/project/tags
/project/a/tags
/project/a/libA/src/tags
/project/a/libB/src/tags
/project/b/tags
/project/c/tags

これら全てが指定されることになります。 つまり**;とは、現在のディレクトリが/project/a/srcの時には

/project/a/src/**
/project/a/**
/project/**
/**

という場合に展開され、それぞれの場所から検索されます。 またこの指定は上記全ての場所から検索されるので重い処理となります。

その他色々

  1. この設定はHack #112: 場所ごとに設定を用意すると組み合わせると非常に相性がいいです。ぜひ合わせて使いましょう。また必ず:setでなく:setlocalを使いましょう。
  2. これらの指定方法は’path’, ‘cdpath’などでも使うことができます。
  3. 詳しくは:help file-searchingを当たってください。
tyru

Hack #153: 検索したパターンで置換する

置換を行いたい場合でも、パターンが合っているか、そもそも対象が存在するかを確認するために、まずは検索をしてみるということはよくあります。検索は * による単語の検索やHack #104: Visual mode で選択したテキストを検索するで紹介した方法などで手軽に行えますが、置換となるとそうは行きません。

:substitute の検索パターン

:substitute コマンドの検索パターンに空を指定すると、直前の検索パターンを指定したことになります。これは通常の検索や * によって検索されたパターンも含まれます。つまり、

  1. まずは検索を行う。
  2. :%s//{置換文字列}/g を実行する。

を行うことで、検索パターンを手軽に指定して置換を行うことができます。さらに検索結果をハイライトする設定になっていれば、どこが置換されるかも一目瞭然です。

thinca

Hack #152: VimとGVimの相違点について知る

普段何気なく使っているVimとGVimですが、二つのVimには様々な違いがあります。違いを正しく知って、使い分けることが真のVim使いへの近道です。

Vimの利点

GUIがなくても動作する

sshでリモートログインしてVimを使用する場合、当然ですがGVimは使用できません。

screenやシェルとの連携が楽

GVimでは外部コマンドを呼び出すとDos窓が開いたり(Windows版)、細かな動作が端末時と異なったりと、連携しづらい面があります。 特にユーザーからの入力が必要な場合に厳しいです。screenと連携できるのもVimのみです。外部コマンドを別のscreenで実行しながらVimを併用するというやり方がオーソドックスでしょう。

GVimの利点

描画が高速

端末は古い仕様を引きずっているので基本的に描画が遅いですが、GVimは高速に動作します。特に、Macの端末は描画が遅いようです。

フルカラーが使用できる

特にWindowsの端末はひどく、16色しか使用できません。下線など、GVimにしかない機能もあります。GVim用のcolorschemeを256色環境で使用するには、雑多な設定が必要であるなど、手間もかかります。この辺りの設定については、[Hack #64: 256色ターミナルでVimを使用する]を参照してください。

日本語が使用しやすい

端末の場合、日本語の特殊記号の描画が乱れることがあります。 IMEとの連携も簡単です。端末の場合はそうもいかないので、skk.vimやUIMのvi協調モードを使う必要があります。

設定が簡単である

端末上のVimだと、一部に摩訶不思議な設定をしないと動作しないことがあります。

特殊なキーを利用できる

端末では使用できるキーにかなり制限があります。

複数のGVimを開くことができる

端末ではscreenを使用するか、端末のタブ機能を使うしかありません。

クリップボードを使用できる

端末でクリップボードと連携するにはkana氏の作成した、fakeclip.vimをインストールする必要があります。使い方に癖があるので、注意が必要です。

マウスとの連携

キーボード派からは邪道と言われるかもしれませんが、右クリックでポップアップメニューが使えるのは便利です。

アイコンの使用

エラー部分にxpm形式のアイコンが使用できます。表示がわかりやすくなって便利です。

自由なフォントの使用

通常のVimの場合、フォントは端末に制限されてしまいます。GVimではEmacsのように英字と日本語でフォントを変更したり、フォントの大きさを変えるのも自由自在です。ただし、Mac OS X以外ではプロポーショナルフォントは使用できません。Mac OS Xでプロポーショナルフォントを使用する方法については、次のHackを参照してください。[Hack #92: Vimでプロポーショナルフォントを使う (Mac OS X編)]

Emacsではどうか

EmacsはGUI版で画像が表示できたり、ツールチップに対応しているなど、圧倒的にGUI版が高機能であるうえに、 外部シェルとの連携やEmacsを端末化することも容易です。 よって、screenと連携したり、リモート接続する場合を除きGUI版を利用する人が多いようです。

GVim+vimshell

GVimには前述の通り、欠点もあります。しかしWindowsでは端末とシェルがしょぼすぎる上に、外部コマンドも貧弱、screenもないのでGVim一択となることでしょう。外部コマンドの連携についても、vimshellと併用することで、シェルが必要な作業の90%はこなせると思います。ただしvimshellにはパイプがまともに使えないなどのバグがあります。cursesを用いた複雑なプログラムも動作しないため、そのようなときは端末上のVimを使用せざるをえないでしょう。

筆者の使用環境

筆者はWindowsでもLinuxでも、ほぼGVimのみを使います。なぜなら筆者はVim上ですべての作業を完結させたいと考えていることに加え、端末の描画が遅いことが気になるからです。 日々のシェルを使用する作業はGVim内からvimshellの機能を用いて行います。 どうしようもなければ、時々端末も使用しますが、動作確認でもない限り端末上のVimはほとんど使用しません。

Shougo

Hack #151: 編集中のファイルがあるディレクトリを開く

問題

Vimの:e:newなどはカレントディレクトリにあるファイルを開きます。また補完対象もカレントディレクトリからのファイルです。

:e a<tab>

このようにするとカレントディレクトリのaからはじまるファイル名を対象にファイル名補完を行ないます。

編集中ファイルと同じディレクトリにある他のファイルを開く機会は多いものの、深いディレクトリに潜っているときは厄介です。 編集中ファイルのディレクトリは%:hで指定でき、なおかつ<tab>キーで展開できるものの、毎回%:h…とくに%という文字を打鍵するのかなかなか腰の折れる作業です。

解決法1

一度カレントディレクトリを編集中ファイルのディレクトリに移動するか、あるいはnetrwで編集中ファイルのディレクトリを開くかが良いでしょう。tabpagecdなどのプラグインを使用している場合、編集中ファイルのディレクトリにカレントディレクトリを移動させるのは副作用が大きすぎるため、後者の方法が好ましいでしょう。

:e %:h

で編集中ファイルのディレクトリをnetrwで開き、ファイル一覧を取得できます。この作業を頻繁に行なうならば、あいているキーにマッピングしましょう。例えば-に割り当てるならば、以下の一行を~/.vimrcに記述します。

nnoremap - :<C-u>e %:h<Cr>

解決法2

あるいは<tab>キーでの展開までを一つのキーに割り当てる方法も考えられます。

nnoremap - :<C-u> %:h<Tab>

このまま<Cr>を打鍵するとnetrwでディレクトリを開くので、こちらの解決法の方がより選択の幅が広がるといえます。

補足

netrwよりもモダンなvimfilerプラグインを用いる、あるいはvimshellに全てを委ねるなど、他にもさまざまなアプローチがあります。

ujihisa

ホーム > Vim Hacks

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

    Return to page top