切换.c / .h缓冲区


8

我通常使用2个垂直分割的窗口。

我想解决的问题是:轻松地从标题<->实现文件中来回跳转

我正在调查两种方法,但没有运气:

  1. 当前窗口中打开备用文件:有很多方法可以执行此操作,但是,我找不到一种方法可以记住我在上一个文件中的位置(即,跳转到标头,跳回,但不回到原先的位置) )。
  2. 另一个窗口中打开备用文件:这是明确定义的,因为我只使用2个窗口,但是我缺乏vim知识来做到这一点。

1
有关第一个问题的提示,请参见:h line()(通用解决方案)的结尾:“如果设置了'“标记,则此自动命令将在打开后立即跳至文件中的最后一个已知位置::au BufReadPost * if line(”' \“”)> 1 && line(“'\”“)<= line(” $“)| exe“ normal!g` \”“ | endif
VanLaser

您不能使用跳转列表和/或跨文件标记吗?
fruglemonkey '16


2
也许您正在寻找A.vim
Christian Brabandt

Answers:


5

完成您的要求需要三个主要步骤:

  • 获取备用文件的名称
  • 根据需要在当前窗口或另一个窗口中打开该文件
  • 恢复该文件中的光标位置

要查找备用文件名,您想将当前文件名分为“ root”和“ extension”。一种简单的方法是:

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文件存在:

  • 通过在当前文件的路径中替换includesrc
  • 通过在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窗口。

要在标题和源之间快速切换,请使用vim-scripts/a.vim以下网址https : //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

然后最后是在当前窗口中打开或进行拆分的两个函数...

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.