rcmdnk's blog

20140725_ide_200_200

Vimでプログラムを書く時の環境設定について。

IDEっぽくと書いてますが、基本 GNU screen を開いた上でウィンドウを分割して作業を行うので、 別のファイルを開きたいとかgrepしたいとか言った場合には Vimを開いているウィンドウとは別のウィンドウで普通にコマンドラインから行います。

なので主に重要なのはシンタックスチェックtagsファイルの取り扱いです。 ファイルリストとかタグリストとかの表示は基本的にはOFFにしておいて、 たまに気が向いたら使う感じ。 (なんとなくやってみたかった感が強い。。。)

Syntax check

SyntasticはVimでコードの文法チェックを行えるようにするプラグイン。 設定はこんな感じ。

.vimrc
1
2
3
4
5
6
7
8
9
10
11
12
13
NeoBundle "scrooloose/syntastic"
if ! empty(neobundle#get("syntastic"))
  " Disable automatic check at file open/close
  let g:syntastic_check_on_open=0
  let g:syntastic_check_on_wq=0
  " C
  let g:syntastic_c_check_header = 1
  " C++
  let g:syntastic_cpp_check_header = 1
  " Java
  let g:syntastic_java_javac_config_file_enabled = 1
  let g:syntastic_java_javac_config_file = "$HOME/.syntastic_javac_config"
endif
  • :SyntasticCheckで文法チェック。
  • チェックを行った後に:Errorsとするとquick fixでエラー一覧表示が出来る。
  • g:syntastic_check_on_open = 0/g:syntastic_check_on_wq = 0:ファイルを開いた時にはチェックしない。終了時にもチェックしない。 (:wとかで保存するだけならチェックされる。)
  • c/c++はデフォルトではgccでチェックする。
  • g:syntastic_c_check_header/g:syntastic_cpp_check_header =1でc/c++でheaderファイルもチェックする。
  • c/c++ではconfigファイルがデフォルトで読み込まれる。 (.syntastic_c_config/.syntastic_cpp_config)
    • これらは現ディレクトリに無いと 上のディレクトリを探しに行って最初にあった所でそれを読み込む。
    • なのでプロジェクトの一番上においておくだけでOK。
    • 中身には

      -I/path/to/include
      

      みたいなチェッカーに渡すための headerファイルの場所などを示すオプションなどを 1行に一オプションずつ書いておく。

    • configファイルの中で$HOMEみたいな環境変数が使えない。
    • ただし、configファイルの中に相対パスを書けば configファイルがある位置からのパス、になるので、 インクルードディレクトリの指定など書きたいときは プロジェクトのトップにconfigファイルがあるならならそこから -I./.../include/と書いておけば良い。
  • Javaの方はデフォルトではjavacがチェッカーとして使われる。
  • Javaの方はconfigファイルを使いたいときは明示的に enabledにしないといけない。
    • Java: javac · scrooloose/syntastic Wiki
    • Javaの方はカレントディレクトリにあるファイルか、 明示的に指定したものしか使えない。(C++の様に親ディレクトリに置いておいても読んでくれない。)
    • 面倒なので、HOMEに色々含めた全部入れを作っておいて、それを読み込む。
    • Javaのconfigファイルでは、上のWikiにあるvim内の変数を与える外部vim設定ファイルみたいなもの。
    • クラスパス(g:syntastic_java_javac_classpath)はjavac-classpathオプションに渡される値。
      • 相対パスだとカレントディレクトリからになるので絶対パスで書いておく必要がある。
      • 環境変数は普通に使える
        • let g:syntastic_java_javac_classpath = '$PROJECT/src:$PROJECT2/jars/*.jar
      • --sourcepathオプションは使われないので
        • *jarファイル
        • classesファイルがあるディレクトリ
        • ソース(src)ディレクトリ をどれでも設定できる(複数の場合はLinux/Macなどでは:で区切る。 Windows(CygwinとかでなくWndowsのVim)では;で区切る)。
    • :SyntasticJavacEditClasspathコマンドを使うと、 クラスパスを分けて1行ずつにして追加したり編集したりできるので ちょっと便利。(勝手にlet g:syntastic_java_javac_classpath = … の形にしてconfigファイルへ書き出してくれる。)
    • :SyntasticJavacEditConfigコマンドの方は単に configファイルを開いて編集するだけ。 ただし、これらのコマンドは一度:SyntasticCheck を呼んだりしてチェックを動かさないと使えない模様。

vim-rooter

プロジェクトのrootディレクトリを見つけて移動するコマンドを実装するプラグイン。 設定はこんな感じ。

.vimrc
1
2
3
4
5
6
7
8
9
NeoBundle "airblade/vim-rooter"
if ! empty(neobundle#get("vim-rooter"))
  " Change only current window's directory
  let g:rooter_use_lcd = 1
  " files/directories for the root directory
  let g:rooter_patterns = ['tags', '.git', '.git/', '_darcs/', '.hg/', '.bzr/', 'Makefile', 'GNUMakefile', 'GNUmakefile', '.svn/']
  " Automatically change the directory
  "autocmd! BufEnter *.c,*.cc,*.cxx,*.cpp,*.h,*.hh,*.java,*.py,*.sh,*.rb,*.html,*.css,*.js :Rooter
endif
  • デフォルトで<Leader>cdでrootディレクトリに移動できる。
  • :Rooterでも行ける。
  • g:rooter_use_lcd = 1で、通常<Leader>cdでは :cdコマンドを使って移動するところを :lcdコマンド(:local cd、現ウィンドウのディレクトリのみ変更)に変更。
  • rootディレクトリは、g:rooter_patternsで定められた ファイルやディレクトリがある一番近い親ディレクトリになる。 複数patternが指定されてる時は、左から優先される。
    • e.g. もし一つ上に.git/があっても、 その上のディレクトリにtagsがあればtagsがある ディレクトリがrootディレクトリになるになる。
    • ディレクトリには/を最後に付けないといけない。
    • git submoduleなんかでsubmoduleとして登録してある レポジトリのなかでは、そのサブモジュールレポジトリを rootにしたい場合は.git.git/よりも左に書く必要がある。
    • .svn/に関しては.git/等と違ってサブディレクトリにも出来るので tagsMakefileなんかを先にしておかないとあまり意味が無い。
  • 最後にコメントアウトしてある部分のようにBufEnterでのautocomdで、 指定の拡張子のファイルを開いた時には自動的に移動、 みたいなこともできるが、取り敢えず今のところ使わない。

タグジャンプ

プラグインではなく最初からVimに付いてるタグジャンプ機能について。

タグファイルの用意

ctagsコマンドを使ってコードがあるディレクトリで

$ ctags --sort=foldcase -R .

とすれば関数やクラスの定義がリストされたtagsと言うファイルが出来ます 1

ただし、ちなみにGNUバージョンとBSDバージョンには違いが合って、 Macに入ってるBSDバージョンだと-Rが使えません。 色々使えないので、MacではHomebrewなんかで

$ brew install ctags

とするとGNUバージョンが入れられるので入れておきます。

このファイルを読み込んでおくことで、Vimの中で関数の定義が 他のファイルにある場合なんかでも簡単にその箇所にジャンプ出来ます。

Vimではtagsファイルはデフォルトでは

tags=./tags,tags

と定義されていて、最初の./tagsは開いているファイルと 同じディレクトリにあるtags、 2番めのはvim内でのカレントディレクトリにあるtags 2になっています。

さらにpath_extraオプションつきでコンパイルしていると 3tags;のような;付きが使えて、 これを使用すると、指定のディレクトリからさかのぼってすべてを検索します。 相対パスならカレントディレクトリから。

tags=/usr/local/share/tags;

とかなら、

  • /usr/local/share/tags
  • /usr/local/tags
  • /usr/tags
  • /tags

を検索。 /usr/local/share 内でファイルを開くなりしてカレントディレクトリがそこの場合に、

tags=tags;

としても同じ事。

pathの値等も同じように設定できて、こちらはディレクトリ指定なので ;を使うとそれ以上のディレクトリを順次探すことに。 この場合には

path=/usr/local/share;/usr

の様に後ろに途中のディレクトリ名を挟むと、そこまで (/usr/まで、/は探さない)を探して止まる様になります。 この途中まで、の機能はどうもtagsの方では使えない感じでした。

tags=./tags;../

みたいにしてもずっと上の方まで探すし、 絶対パスを指定しても上までずっと探してました。

editing - vimdoc-ja

path_extraが入ってれば上のディレクトリを再帰的に探してくれると便利なので (プロジェクトのルートディレクトリにtagsファイルを置いておけばどこでも参照できる)、

.vimrc
1
2
3
if has("path_extra")
  set tags+=tags;
endif

こんな感じでtags;を追加しておきます。

ジャンプの仕方

  • tagsが有効な関数名などの上でCtrl-] を押せば定義されてる所一覧が出てくるのでそこに飛べる。
  • Ctrl-tで戻る。

とりあえずこれだけ覚えておけばOK。

タグのリスト表示

画面の横にウィンドウを作ってそこに現在開いているファイル内にある タグ一覧を表示してくれるプラグイン。 (つまり変数/関数/クラス一覧的な物を表示してくれる。) 選択して移動することも出来る。

設定:

.vimrc
1
2
3
4
5
6
7
8
NeoBundleLazy "majutsushi/tagbar", {
      \ "autoload": { "commands": ["TagbarToggle"] }}
if ! empty(neobundle#get("tagbar"))
   " Width (default 40)
  let g:tagbar_width = 20
  " Map for toggle
  nn <silent> <leader>t :TagbarToggle<CR>
endif
  • :TagbarToggleでタグリストを新しいウィンドウで表示/非表示。
  • :TagbarOpen/:TagbarCloseと言った表示/非表示専用コマンドもあるが、 トグルだけで十分なのでNeoBundleLazyを使って :TagbarToggleが使われた時にロードする様に(Open/Closeコマンドもいれておいても特に問題はありませんが)。
  • デフォルトのwidth=40は大きいので小さく。
    • Tagbarのウィンドウでxを押すと幅を拡大出来る。
  • ショートカットキーとして<Leader>t:TagbarToggleに割り当て。

同じ様な物に、 taglist 4 というものも有りますが、 アップデートがよりアクティブなのと、 taglistで起きる色々な不具合がtagabarでは起きない、などがあるみたいなので tagbarのが良さ気。

taglist vs tagbar? Question directed to people that were using both of those…

関数等の定義場所のソース表示

tagsファイルを利用してカーソル下の関数などを定義されているところを 画面下に表示してくれる 5

設定:

.vimrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
NeoBundleLazy "wesleyche/SrcExpl", {
      \ "autoload" : { "commands": ["SrcExplToggle"]}}
if ! empty(neobundle#get("SrcExpl"))
  " Set refresh time in ms
  let g:SrcExpl_RefreshTime = 1000
  " Is update tags when SrcExpl is opened
  let g:SrcExpl_isUpdateTags = 0
  " Tag update command
  let g:SrcExpl_updateTagsCmd = 'ctags --sort=foldcase %'
  " Update all tags
  function! g:SrcExpl_UpdateAllTags()
    let g:SrcExpl_updateTagsCmd = 'ctags --sort=foldcase -R .'
    call g:SrcExpl_UpdateTags()
    let g:SrcExpl_updateTagsCmd = 'ctags --sort=foldcase %'
  endfunction
  " Source Explorer Window Height
  let g:SrcExpl_winHeight = 14
  " Mappings
  nn [srce] <Nop>
  nm <Leader>E [srce]
  nn <silent> [srce]<CR> :SrcExplToggle<CR>
  nn <silent> [srce]u :call g:SrcExpl_UpdateTags()<CR>
  nn <silent> [srce]a :call g:SrcExpl_UpdateAllTags()<CR>
  nn <silent> [srce]n :call g:SrcExpl_NextDef()<CR>
  nn <silent> [srce]p :call g:SrcExpl_PrevDef()<CR>
endif
  • :ScrExplToggleで表示/非表示をトグル。
    • :ScrExpl/:ScrExplCloseで表示/非表示もできるがトグルだけで十分なので NeoBundleLazyでも:SrcExplToggleだけを指定。
  • RefreshTime:カーソルを移動した際の更新時間を1秒に(デフォルト値は100ms)。
  • isUpdateTags:自動的にタグをアップデートしない。
  • updateTagsCmd:タグのアップデートコマンド。
    • デフォルトでは

      let g:SrcExpl_updateTagsCmd = "ctags --sort=foldcase -R ."
      

      となっています。

    • このコマンドはtagsファイルがあるディレクトリで実行されるので、 デフォルトだとtagsファイルのあるディレクトリ以下全てのファイルをチェックし直します。
    • これだと大きいプロジェクトとかだと大変なので、%(今開いてるファイル)だけを見てアップデートする様に。
    • 全てをアップデートしたい時もあるので、関数を作って一時的に コマンドを入れ替えて実行出来る様にも。
    • 出力先のtagsファイルはその時使っているtagsファイルになります。
  • winHeight:デフォルトだと8行の表示で少し小さすぎるので14行表示に。
  • トグル用のショートカットは<Leader>E<CR>に。
  • <Leader>Euで現ファイルのタグをアップデート。
  • <Leader>Eaで全てのファイルのタグをアップデート。
  • <Leader>En/pはその関数が複数の場所で定義されてる時などに 次の候補や前の候補への移動。

ファイルエクスプローラー

ファイルエクスプローラーを表示できる様になる。

設定:

.vimrc
1
2
3
4
5
NeoBundleLazy "scrooloose/nerdtree", {
      \ "autoload" : { "commands": ["NERDTreeToggle"] }}
if ! empty(neobundle#get("nerdtree"))
  nn <Leader>N :NERDTreeToggle<CR>
endif
  • :NERDTreeToggleで表示/非表示。
    • こちらも:NERDTree/:NERDTreeCloseという表示/非表示コマンドもあり。
  • ショートカットは<Leader>Nに。

Tagbar, SrcExpl, NERDTreeを全て表示する

上のTagbar, SrcExpl, NERDTreeを全てトグルする ショートカットも作っておきます。

.vimrc
1
2
3
4
5
if ! empty(neobundle#get("nerdtree")) &&
    \! empty(neobundle#get("SrcExpl")) &&
    \! empty(neobundle#get("tagbar"))
  nn <silent> <Leader>A :SrcExplToggle<CR>:NERDTreeToggle<CR>:TagbarToggle<CR>
endif

<Leader>Aで全てをトグル。 それぞれの位置はデフォルトのママ

  • Tagbar: 右
  • SrcExpl: 下
  • NERDTree: 左

に表示されて、SrcExplと他の2つは開く順番によってかぶる領域が変わるので注意。

SrcExplを先に開くとその後Tagbar等はその右全体に開かれます。 逆にTagbarを開いた後にSrcExplを開くとTagbarの下にもSrcExplが侵食します。

メインのウィンドウとSrcExplの幅を同じにしたいので最初にSrcExplを開いています。

こんな感じ (ちょっと見やすいように小さいウィンドウで取ったのでメインの画面(真ん中上)が 小さいですが)。

ide.jpg

Unite

ファイルとかその他いろいろ検索。

色々設定してありますが、いまいち使いこなせてないので とりあえず設定だけ。。。

.vimrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
" Asynchronous execution library: need for vimshell, Gmail, unite, etc...
NeoBundle "Shougo/vimproc", {
      \"build" : {
      \"windows" : "make -f make_mingw32.mak",
      \"cygwin" : "make -f make_cygwin.mak",
      \"mac" : "make -f make_mac.mak",
      \"unix" : "make -f make_unix.mak"}}

""" Unlike "fuzzyfinder" or "ku", it doesn't use the built-in completion of vim {{{
""" Searches and display information->:help Unite
NeoBundleLazy "Shougo/unite.vim" , {
      \ "autoload" : { "commands" : [ "Unite" ] }}

" Source for unite: mark
NeoBundle "tacroe/unite-mark"

" Source for unite: outline
NeoBundle "h1mesuke/unite-outline"

" Source for unite: help
NeoBundle "tsukkee/unite-help"

" Source for unite: history/command, history/search
NeoBundle "thinca/vim-unite-history"

" Source for unite: fold
NeoBundle "osyo-manga/unite-fold"

" Source for unite: locate
NeoBundle "ujihisa/unite-locate"

if ! empty(neobundle#get("unite.vim"))
  autocmd FileType unite call s:unite_my_settings()
  function! s:unite_my_settings()
    nm <buffer><Esc> <Plug>(unite_exit)
    im <buffer> jj      <Plug>(unite_insert_leave)
    "imap <buffer> <C-w>     <Plug>(unite_delete_backward_path)

    im <buffer><expr> j unite#smart_map('j', '')
    im <buffer> <TAB>   <Plug>(unite_select_next_line)
    im <buffer> <C-w>     <Plug>(unite_delete_backward_path)
    im <buffer> '     <Plug>(unite_quick_match_default_action)
    nm <buffer> '     <Plug>(unite_quick_match_default_action)
    im <buffer><expr> x
          \ unite#smart_map('x', "\<Plug>(unite_quick_match_choose_action)")
    nm <buffer> x     <Plug>(unite_quick_match_choose_action)
    nm <buffer> <C-z>     <Plug>(unite_toggle_transpose_window)
    im <buffer> <C-z>     <Plug>(unite_toggle_transpose_window)
    im <buffer> <C-y>     <Plug>(unite_narrowing_path)
    nm <buffer> <C-y>     <Plug>(unite_narrowing_path)
    nm <buffer> <C-j>     <Plug>(unite_toggle_auto_preview)
    nm <buffer> <C-r>     <Plug>(unite_narrowing_input_history)
    im <buffer> <C-r>     <Plug>(unite_narrowing_input_history)
    nn <silent><buffer><expr> l
          \ unite#smart_map('l', unite#do_action('default'))

    let unite = unite#get_current_unite()
    if unite.buffer_name =~# '^search'
      nn <silent><buffer><expr> r     unite#do_action('replace')
    else
      nn <silent><buffer><expr> r     unite#do_action('rename')
    endif

    nn <silent><buffer><expr> cd     unite#do_action('lcd')
    nn <buffer><expr> S      unite#mappings#set_current_filters(
          \ empty(unite#mappings#get_current_filters()) ?
          \ ['sorter_reverse'] : [])

    " Runs "split" action by <C-s>.
    im <silent><buffer><expr> <C-s>     unite#do_action('split')
  endfunction
  " start with insert mode (can start narrow result in no time)
  let g:unite_enable_start_insert=1
  " window
  "let g:unite_enable_split_vertically=1
  let g:unite_split_rule="botright" " default topleft
  let g:unite_winheight=10          " default 20
  let g:unite_winwidth=60           " default 90

  " Unite prefix
  nn [unite] <Nop>
  nm <Leader>u [unite]

  " show buffer
  nn <silent> [unite]b :Unite buffer<CR>
  " show files/directories with full path
  nn <silent> [unite]f :Unite -buffer-name=files file<CR>
  " show frecursive file search
  "nn <silent> [unite]f :<C-u>Unite file_rec/async:!<CR>
  " show register
  nn <silent> [unite]r :Unite -buffer-name=register register<CR>
  " show opened file history including current buffers
  "nn <silent> [unite]m :UniteWithBufferDir -buffer-name=files buffer file_mru<CR>
  nn <silent> [unite]m :Unite file_mru<CR>
  " show lines of current file
  nn <silent> [unite]l :Unite line<CR>
  " search (like ack.vim/ag.vim)
  nn <silent> [unite]/ :Unite grep:.<CR>
  " Yank (like yankring/yankstack)
  let g:unite_source_history_yank_enable = 1
  nn <silent> [unite]y :Unite history/yank<CR>

  " sources outside of unite
  nn <silent> [unite]M :Unite mark<CR>
  nn <silent> [unite]c :Unite history/command<CR>
  nn <silent> [unite]s :Unite history/search<CR>
  nn <silent> [unite]F :Unite fold<CR>
  nn <silent> [unite]L :Unite locate<CR>
  nn <silent> [unite]C :Unite colorscheme<CR>
endif

その他

以下は昔使ってた/今は使わないけど一応見てみたもの。

ctags関連

SrcExplでtagsのアップデートが出来るのですが、 ファイル保存時等に自動的にtagsをアップデートしたり出来る プラグインについて。

ファイル検索

  • kien/ctrlp.vim
    • Ctrl-pでファイルの検索的な事が出来る。

ファイルツリー表示等

  • shemerey/vim-project
    • 古い?使い方よく分からない。。。
    • \c(プロジェクトファイルの生成)しても上手く自動生成されない。
    • 単に左側にファイル一覧のツリーを表示してすぐに そこに移動できるようにするだけ?
  • amiorin/vim-project
    • こちらは派生版?

C/C++用

  • vim-scripts/c.vim
    • 色々出来そうだけど試してない。そのうち試したい。

その他参考

  • Recommended Vim plugins for C coding? - Stack Overflow: http://stackoverflow.com/questions/149558/recommended-vim-plugins-for-c-coding
Sponsored Links
    • --sort=foldcaseでソートの仕方を指定。ソートする(yes)、しない(no)、 または大文字小文字区別せずソートする(foldcase)。
    • -Rはディレクトリを再帰的に検索。
    • 最後にパスやファイル指定。
  1. 通常移動してなければ前者と同じ。 上で出したvim-rooterでルートディレクトリに常に移動するようにしておけば ルートディレクトリに置いておけばこの設定だけでも常に参照出来る様になります。

  2. 通常は入ってるはず。:echo has('path_extra')でチェック(1なら入ってる、0なら入ってない)。

  3. 一応taglist様の設定としては、

    NeoBundle "taglist.vim"
    if ! empty(neobundle#get("taglist.vim"))
      set tags=tags
      "let Tlist_Ctags_Cmd = "/usr/bin/ctags"
      let Tlist_Show_One_File = 1
      let Tlist_Use_Right_Window = 1
      let Tlist_Exit_OnlyWindow = 1
      nn <silent> <leader>t :TlistToggle<CR>
    endif
    

    こんな感じ。

  4. もともと、 Source-Explorer-srcexpl.vim という名前だったもの。

    さらに vim-scripts/SrcExpl にもありますが、こちらはアップデートされてなく、 上のwesleyche自身のレポジトリに移行した模様。

Sponsored Links

« Mac(Mavericks)でのユーザーアイコンの変更方法 Octopressでgenerate前にポストをチェックする »

}