.c / .hバッファーの切り替え


8

私は通常、垂直に分割された2つのウィンドウで作業します。

私が解決したい問題は、ヘッダー<->実装ファイルから簡単に前後にジャンプすることです

私は運がなければ、これを行う2つの方法を調査しています:

  1. 現在のウィンドウで別のファイルを開く:これを行う方法はたくさんありますが、前のファイルのどこにいたかを覚えておく方法が見つかりません(つまり、ヘッダーにジャンプしたり、戻ったりしますが、以前と同じ場所にジャンプすることはできません) )。
  2. ウィンドウで別のファイルを開く:これは明確に定義されています。これは、2つのウィンドウでしか作業しないためですが、これを行うためのvim-knowledgeが不足しています。

1
1番目の問題のヒントについては、:h line()(一般的な解決策)の終わりを参照してください:「このオートコマンドは、 '"マークが設定されている場合、ファイルを開いた直後に、ファイル内の最後の既知の位置にジャンプします。:au BufReadPost * if line("' \ "")> 1 && line( "'\" ")<= line(" $ ")| exe "normal!g` \" "| endif
VanLaser

ジャンプリストやクロスファイルマークは使用できませんか?
fruglemonkey 2016


2
たぶん、あなたはA.vim
Christian Brabandt

回答:


5

あなたが求めていることを成し遂げるには3つの主要なステップがあります:

  • 代替ファイルの名前を取得する
  • 必要に応じて、現在のウィンドウまたは別のウィンドウでそのファイルを開く
  • そのファイル内のカーソル位置を復元する

代替ファイル名を見つけるには、現在のファイル名を「ルート」と「拡張子」に分割します。これを行う簡単な方法は次のとおりです。

let parts = split(expand("%:p"), "[.]");
let root = parts[0]
let extension = parts[1]

ファイル.h.cppファイルを切り替えるだけであることがわかっている場合は、拡張子を簡単に変更できます。

if extension == "h"
  let extension = "cpp"
else
  let extension = "h"
endif

または、既知の拡張子を有効な代替拡張子にマッピングする辞書を作成します。または、現在のファイルのすべての可能な代替globpath()を取得するために使用します。

let alternates = globpath(expand("%:h"), root . ".*")

そして最初のものを選ぶか、何でも。私はこのglobpathアプローチを好みますが、後で説明するいくつかの追加のスマートがあります。ターゲット拡張機能を選択したら、完全なターゲットパスを作成します。

let target = root . "." . alternates[whicheverAlternateExtensionYouWant]

これで、現在のウィンドウで代替ファイルを開くことができます。

execute "edit " . target

またはwinnr()、「他のウィンドウ」の番号(ジャンプ先winnr("#")のウィンドウ<C-W>p、またはセットアップで常に同じであることがわかっている場合はハードコードできます)を取得して、次のようにします。

let window = winnr("#")
execute window . "wincmd w"
execute "edit " . target

これにより、代替ファイルを開くための本当に基本的な解決策が得られます。上記のアプローチにはいくつかの欠点があります。それは、私がそれを単純明快に書くように書いたからです。「希望どおり」に代替ファイルの切り替えを行うプラグインを作成しました(利用可能なすべてのglobpath()結果を循環します)。上記のシンプルさでいくつかの問題に対処します。詳細を調べたい場合は、その実装を確認できます。

最後に、「カーソル位置の復元」ポイント。代替の切り替えと直交するため、最後に保存しました(たとえば、私のプラグインでは処理しません)が、独自にロールバックする場合は、関数に入れることができます。:help line()ファイルが最後に開かれたときの位置にカーソル位置を復元するのに役立つオートコマンドがあります:

:au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\"" | endif

私はいつも.vimrcそれを好むので、私はそれに、またはそれに非常によく似た何かを入れました。ただし、コードを別の場所に置くだけでも簡単にできます。


2

ファイルで次の設定と一緒にvim-fswitchプラグインを使用でき.vimrcます。

au! BufEnter *.cpp,*.cc,*.c let b:fswitchdst = 'h,hpp'    | let b:fswitchlocs = 'reg:/src/include/,../include,./'
au! BufEnter *.h,*.hpp      let b:fswitchdst = 'cpp,cc,c' | let b:fswitchlocs = 'reg:/include/src/,../src,./'

nmap <silent> <Leader>s :FSHere<cr>

あなたが入力した場合<Leader>(これ\に続いて、デフォルトでは)s.hppまたは.hファイルの整合場合、プラグインがチェックする.cpp.ccまたは.cファイルが存在します:

  • 交換することによりincludeによりsrc、現在のファイルのパスに
  • src現在のファイルの上のフォルダーを調べる
  • 現在のファイルのフォルダーを調べる

ドキュメントにプロジェクトをうまく合わせるために使用できるオプションは他にもあります。それはあなたに数分かかりますが、一度それが正しくなると、あなたはそれを気に入るはずです。私は個人的にそれが非常に柔軟で拡張可能であることに加えて、それは多くの種類のファイル(.m、.h、.inlなど...)でも同様に機能します。


1

あなたの .vimrc

" =====[ Remap to change windows quickly ]=============================
:nnoremap <silent> <C-H> :wincmd h<CR>
:nnoremap <silent> <C-J> :wincmd j<CR>
:nnoremap <silent> <C-K> :wincmd k<CR>
:nnoremap <silent> <C-L> :wincmd l<CR>

これにより、ホーム行からCtrlキーとVIM方向キーを使用するだけで、ウィンドウ間をすばやく移動できます。これの素晴らしさは、quickfixウィンドウを含む任意のウィンドウにジャンプする1つの一般的な方法があることです。

私が使用するヘッダーとソースをすばやく切り替えるには、httpsvim-scripts/a.vim//github.com/vim-scripts/a.vimにあり:Aコマンドを使用して切り替えます。

サイドノート=> tmuxを使用している場合、https://github.com/christoomey/vim-tmux-navigatorを使用して、vimまたはnvimウィンドウと端末の間をシームレスに移動できます。


1

私は私の超迅速で汚いバージョンを共有します...

マッピングを設定します。alt-oは同じウィンドウで関連ファイルを開き、alt-shift-oは分割して開きます...

nnoremap <A-o> :call EditRelatedFile()<CR>
nnoremap <A-O> :call SplitRelatedFile()<CR>

次に、関連ファイルのリストを取得する関数があります。私はそれを微調整して、最後ではなく最初のドットでファイル名を切り取るつもりでしたが、それはまだ読者のための練習です。

function! GetRelatedFileList()
    " This function may be overloaded in a site-specific vimrc.
    let l:thisPath = expand("%:p:r") . '.*'
    let l:files = glob(l:thisPath)

    return split(l:files, '[\r\n]\+')
endfunction

私の.vimrcセットアップは、クライアントごとに特化されていることがあります。ソースがあり、別のフォルダー階層に含まれているものもあれば、一緒に持っているものもあります。デフォルトでは、それらはすべて近くにあると想定していますが、狩りが必要な場合は、このような代替機能を提供します。

" Override the basic GetRelatedFileList coming from vimrc.
function! GetRelatedFileList()
    let l:thisDir = expand("%:p:h:t")
    if (l:thisDir ==? "src") || (l:thisDir ==? "include")
        let l:thisPath = expand("%:p:h:h")
        let l:searchPaths = l:thisPath.'/include,' . l:thisPath.'/src'
        let l:thisBase = expand("%:t:r") . '.*'
        let l:files = globpath(l:searchPaths, l:thisBase)
    else
        let l:thisPath = expand("%:p:r") . '.*'
        let l:files = glob(l:thisPath)
    endif

    return split(l:files, '[\r\n]\+')
endfunction

次に、そのファイルのリストを調べて、現在のバッファのファイルを見つけ、リストの次のファイルに移動します。.cpp / .hのペアほど単純ではないことがよくありますが、他にも検討する必要があることがよくあります。

function! GetNextRelatedFile()
    let l:fileList = GetRelatedFileList()

    let l:thisFile = expand("%:p")
    let l:index = index(l:fileList, l:thisFile) + 1

    if l:index >= len(l:fileList)
        let l:index = 0
    endif

    return l:fileList[l:index]
endfunction

そして最後に、現在のウィンドウで開くか、分割する2つの関数...

function! EditRelatedFile()
    let l:file = GetNextRelatedFile()
    execute "edit" l:file
endfunction

私の分割バージョンでは常に.cppファイルと.cファイルを下の分割に配置します。それ以外の場合は分割のデフォルト(私の場合は上)に分割します。

function! SplitRelatedFile()
    let l:file = GetNextRelatedFile()
    let l:ext = fnamemodify(l:file, ":e")
    if (l:ext ==? "cpp") || (l:ext ==? "c")
        execute "below split" l:file
    else
        execute "split" l:file
    endif
endfunction
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.