Перемикання буферів .c / .h


8

Я нормально працюю з 2 вікнами, вертикально розділеними.

Проблему, яку я хотів би вирішити, полягає в тому, щоб: легко перескакувати назад і назад із заголовка <-> файлу реалізації

Я досліджую, без удачі, два способи зробити це:

  1. Відкрити альтернативний файл у поточному вікні : Є багато способів зробити це, однак, я не можу знайти спосіб, який запам'ятає, де я був у попередньому файлі (тобто, перейти до заголовка, перейти назад, але не на те саме місце, де я був ).
  2. Відкрити альтернативний файл у іншому вікні : Це чітко визначено, оскільки я коли-небудь працюю лише з 2 вікнами, однак мені не вистачає знань vim для цього.

1
Підказку до першого випуску див. У кінці :h line()(загальне рішення): "Цей автокоманд переходить на останнє відоме місце у файлі одразу після його відкриття, якщо встановлено позначку" ":: au BufReadPost * if line (" ' \ "")> 1 && рядок ("'\" ") <= рядок (" $ ") | exe "нормально! g` \" "| endif
VanLaser

Ви не можете використовувати перехідний список та / або позначки між файлами?
fruglemonkey


2
можливо ви шукаєте A.vim
Крістіан Брабандт

Відповіді:


5

Існує три основні кроки у виконанні того, що ви просите:

  • отримання альтернативного імені файлу
  • відкривши цей файл у поточному вікні або в іншому вікні за бажанням
  • відновлення позиції курсора у цьому файлі

Щоб знайти альтернативне ім'я файлу, вам потрібно розбити поточне ім'я файлу на "корінь" та "розширення". Простий спосіб зробити це:

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>(який \за замовчуванням), а за ним - sa .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 із головного рядка. Приємність цього - чи є у вас один загальний спосіб перейти до будь-якого вікна, включаючи вікно швидкого виправлення.

Для швидкого переключення між заголовком та джерелом я використовую 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.