我通常使用2个垂直分割的窗口。
我想解决的问题是:轻松地从标题<->实现文件中来回跳转
我正在调查两种方法,但没有运气:
- 在当前窗口中打开备用文件:有很多方法可以执行此操作,但是,我找不到一种方法可以记住我在上一个文件中的位置(即,跳转到标头,跳回,但不回到原先的位置) )。
- 在另一个窗口中打开备用文件:这是明确定义的,因为我只使用2个窗口,但是我缺乏vim知识来做到这一点。
我通常使用2个垂直分割的窗口。
我想解决的问题是:轻松地从标题<->实现文件中来回跳转
我正在调查两种方法,但没有运气:
Answers:
完成您的要求需要三个主要步骤:
要查找备用文件名,您想将当前文件名分为“ 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
因为我一直都喜欢这种行为,所以我只是把它或类似的东西放在我的身上。您可以轻松地将代码放在其他位置。
您可以在文件中使用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等)也同样有效。
在你的 .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窗口与终端之间无缝切换。
我只分享我的超级快速和肮脏的版本...
设置我的映射;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
:h line()
(通用解决方案)的结尾:“如果设置了'“标记,则此自动命令将在打开后立即跳至文件中的最后一个已知位置::au BufReadPost * if line(”' \“”)> 1 && line(“'\”“)<= line(” $“)| exe“ normal!g` \”“ | endif