クイック検索、C ++関数に限定


13

私はかなり大きなC ++プロジェクトに取り組んでいます。その組織のよりイライラする側面の1つは、途方もなく大きなファイル内に配置された非常に大きな関数です。

現在の関数に制限された特定のグローバル変数または関数呼び出しのインスタンスを検索したいことがよくあります。これを達成するための合理的な簡単な公式はありますか?

(私はctagsをインストールしていて、Tagbarを使用しています...これは役に立つかもしれません)

回答:


9

ここに私がそれをする方法があります。これを追加します.vimrc

vnoremap if [[O][

説明:vnoremap は、視覚モードのときにif左側[[mO][を右側にマップすることを意味します。In Functionをif意味しますが、必要に応じて名前を変更できます。関数の先頭にジャンプします。視覚的に選択したテキストのもう一方の端に移動してから、関数の最後に移動します。[[O][

したがって、関数で検索する場合は、で視覚モードに入りv、で関数全体を選択しますif。で視覚モードを終了し<esc>、で検索し/\%Vます。\%V以前に選択したテキストに検索を制限します。ヒット<esc>/\%Vする必要がない場合は、これをに追加することもできます.vimrc

vnoremap / <esc>/\%V

次に、キーストロークのシーケンスは次のようになります。

vif/foo<enter>

これにより、現在の関数でfooがすべて出現します。


このメソッドの唯一の欠点は、開き中括弧と閉じ中括弧の両方にインデントが0あることを期待することです。これを持たないコードを定期的に使用する場合、例えば

int foo() {
    bar()
}

この少し複雑なバージョンが機能します:

vnoremap if ][ma%O'a

これは、右中括弧に0のインデントがあることのみを想定しています。開始ブレースにインデントがある場合、マークは使用しますが、機能します。マーク「a」を定期的に使用する場合は、これを移動できます

vnoremap if ][mb%O'b
vnoremap if ][mc%O'c
...

残念ながら、これはC ++関数ではうまく機能しません。C関数とは異なり、インデントされる可能性があります(クラス定義で定義されたインラインメンバー関数、および名前空間内の関数の既定のインデントの場合)。ただし、ctagsを使用して取得できる関数定義範囲のおかげで、アイデアを構築できます。私は、関数内でそれを行うlh#dev#find_function_boundariesLH-devのから
リュックHermitte

3
いいアプローチ。関数の一番上の行を確実に見つけることができる場合は、に移動して{からを使用%して、一番下の行に到達できます。C ++で関数がどのように開始されるかはわかりませんが、これはJavascriptでは問題なく動作しますvnoremap if <Esc>?^\s*function<CR>v/{<CR>%o
。– joeytwiddle

1
最後の編集について。CTRL-]カーソルの下のタグにジャンプします。現在の機能の開始ではありません。助けにはなりません。
リュックエルミット

新しい編集について。それはそれほど単純ではありません。困難なのは、vimに現在の機能を知らせることです。情報があれば、ctagsのヘルプは必要ありません。(ctagsから)情報を取得する唯一の方法は、ctagsによって生成された宣言へジャンプコマンドを分析することです。これらのコマンドがの場合:linenumber、vimはプラグインで私がしたことを実行できます。しかし、保証はなく、これらのコマンドは代わりに検索することができます-Vimは/patternすべてのパターンをテストして、どれが現在の機能に一致するかを知ることができません.IOW 、私は現在の開始にジャンプするvimアクションを認識していません関数
リュックエルミット

6

DJ McMayhemのソリューションは、関数の境界の適切な分析を行うためにctagsとmatchitに依存する独自のものを書くように私を刺激しました。

難しい部分は、lh-devとlh-tagsによって数年間すでに行われています:

  • 現在のファイルは適切なオプションでctagsを介して解析されます
  • 現在のファイル用に取得されたタグに制限されているタグデータベース内のすべての関数定義を探します
  • DBのおかげで、すべての関数の開始行番号があります(ctagsではtemplateinline一部が欠落している場合があります)
  • 単純な反復検索(バイナリ検索は実行できたかもしれませんが、ファイルは「短い」ことになっています)で、現在の関数の始まりが見つかりました
  • また、matchitプラグインのおかげで、その最終行も見つかりました-汎用ctagsはend、C、C ++、Python、およびVimで使用できるフィールドを提供しており、関数の終わりを見つけるためにも使用できます。

このアルゴリズムのどの部分も、ファイルタイプごとにオーバーライドできることに注意してください。つまり、Python関数の境界検出はdef、インデントを検索および分析できfunction、javascriptで検索できるなどです。つまり、現在のバージョンはJava、Vim、および他の言語でも動作します(まだ作業があります) Pythonで行うこと)

そこで、視覚モードマッピングとオペレーター保留モードマッピングの2つの新しいマッピングを定義します。

onoremap <silent> if :<c-u>call lh#dev#_select_current_function()<cr>
xnoremap <silent> if :<c-u>call lh#dev#_select_current_function()<cr><esc>gv

依存するもの:

function! lh#dev#_select_current_function() abort
  let fn = lh#dev#find_function_boundaries(line('.'))
  exe fn.lines[0]
  normal! v
  exe fn.lines[1]
endfunction

数百行のコードをhundredしまない lh#dev#find_function_boundaries()

そして、DJ McMayhemのマッピングのおかげで

" Note that my vim settings requires two backslashes here instead of one
vnoremap / <esc>/\\%V

現在の関数でvif/pattern検索を行うことができますpattern

で関数をdif削除したりyif、などでヤンクしたりすることもできます。

以下は、現実的な C ++関数に適用された場合の外観です(つまり、0字下げされていません)。スクリーンキャスト:C ++関数の選択


4

特にfunctionキーワードのない言語や、多くの矛盾するインデントスタイルでは、関数の始まりと終わりを見つけるのは困難です。

関数が独自の行に閉じ括弧だけで終了する場合(ここにリストされている 13のスタイルのうち10のように)、次のようなもので視覚的に選択できます。

xnoremap if /^\s*}<CR><Esc>V%

そこからfoo、関数内での検索は次のことのみです。

:'<,'>g/foo/#

すべてをまとめると、かなり良いマッピングを取得できます。

xnoremap if /^\s*}<CR><Esc>V%
nmap <key> vif:g//#<Left><Left>

関数で検索

言った、ビジュアルモードのマッピングは、おそらく簡単にだまされてしまうwhileif、それはおそらく、研磨のビットから恩恵を受けるようにします。また、視覚的な選択を維持することはあまり良い考えではないかもしれません…


これは、見つけることができる次のブロックを選択するだけです。あなたが追加したら、それはすべてでは動作しませんifforwhile、など
DJMcMayhem

3

不完全な解決策は折り畳みを使用することです。すべてを折りたたむ:

set foldmethod=syntax
set foldlevel=0
set foldminlines=0

検索結果のために折り畳まれた領域を開かないようにVimに指示します。

set foldopen-=search

そして、問題の関数のフォールドを開きます(zO)。

これで、折り畳まれた領域で検索されたテキストのすべてのヒットは、Vimが一度折り畳みラインにジャンプし、次のヒットに進むという結果になります。

たとえば、次の場合:

ここに画像の説明を入力してください

折りたたまれた機能は、多くの用途がありsizeますが、n周りのすべての使用方法私をリードしていないだろうsizeという機能では。


3

別の方法:

  • ctagsなどを使用してターゲット関数を見つけ、そこに行きます
  • 関数本体内でカーソルを前方に移動します
  • Osyo Mangaの検索演算子vim-operator-userに依存)を使用して、現在のブロック内のみを検索します。例えば:

    " configure the plugin (once, vimrc):
     map g/ <Plug>(operator-search)
    
    " 1. use ctags etc. to jump to the beginning of the target function;
    " 2. move cursor inside the function definition, then:
    g/i{
    

...これで、指定したプロンプトで検索語を挿入できます。n検索結果が現在提供されているモーション/テキストオブジェクトにどのように制限されるかを確認するためにヒットします。これはVim(つまり構成可能な)演算子であるため、適切な関数text-objectがある場合、検索する前に定義本体内を移動する必要はありませんがg/if、smthing likeなどを直接使用します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.