Przełączanie buforów .c / .h

8

Zwykle pracuję z 2 oknami, pionowo podzielonymi.

Problem, który chciałbym rozwiązać, to: łatwe przeskakiwanie do przodu i do tyłu z pliku implementacyjnego nagłówka <->

Badam, bez szczęścia, 2 sposoby na zrobienie tego:

  1. Otwórz alternatywny plik w bieżącym oknie : Istnieje wiele sposobów, aby to zrobić, jednak nie mogę znaleźć sposobu, który zapamięta miejsce, w którym znajdowałem się w poprzednim pliku (tj. Przeskocz do nagłówka, przeskocz do tyłu, ale nie w to samo miejsce, w którym byłem ).
  2. Otwórz alternatywny plik w drugim oknie : Jest to dobrze zdefiniowane, ponieważ zawsze pracuję tylko z 2 oknami, jednak brakuje mi wiedzy na ten temat.
zach
źródło
1
Wskazówka do pierwszego wydania znajduje się na końcu :h line()(ogólne rozwiązanie): „Ta komenda automatyczna przeskakuje do ostatniej znanej pozycji w pliku zaraz po jej otwarciu, jeśli ustawiony jest znak„ ”: au BufReadPost * if line („ ” \ "")> 1 && line ("'\" ") <= line (" $ ") | exe "normal! g` \" "| endif
VanLaser
Nie możesz użyć listy przeskoków i / lub znaczników między plikami?
fruglemonkey
2
być może szukasz A.vima
Christiana Brabandta

Odpowiedzi:

5

Istnieją trzy główne kroki w realizacji tego, o co pytasz:

  • uzyskanie nazwy alternatywnego pliku
  • otwieranie tego pliku w bieżącym oknie lub w innym oknie według potrzeb
  • przywracanie pozycji kursora w tym pliku

Aby znaleźć alternatywną nazwę pliku, należy podzielić bieżącą nazwę pliku na „root” i „rozszerzenie”. Prostym sposobem na to jest:

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

Jeśli wiesz, że zawsze przełączasz się między plikami .hi .cpp, możesz łatwo zmienić rozszerzenie z jednego na drugi:

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

Alternatywnie, utwórz słownik mapujący znane rozszerzenia na potencjalnie ważne alternatywne rozszerzenia. Lub użyj, globpath()aby uzyskać wszystkie możliwe alternatywy dla bieżącego pliku:

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

i wybierz pierwszy, czy cokolwiek innego. Wolę to globpathpodejście, z dodatkowymi sprytami opiszę później. Po wybraniu rozszerzenia docelowego utwórz pełną ścieżkę docelową:

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

Teraz możesz otworzyć alternatywny plik w bieżącym oknie:

execute "edit " . target

Lub użyj, winnr()aby uzyskać numer „innego okna” ( winnr("#")jest to okno, <C-W>pdo którego można by przeskoczyć, lub możesz go na stałe zakodować, jeśli wiesz, że zawsze będzie takie samo dla twojej konfiguracji) i zrobić coś takiego:

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

Daje to naprawdę podstawowe rozwiązanie do otwierania alternatywnych plików. W powyższym podejściu jest kilka niedociągnięć, ponieważ napisałem, że jest to proste i jest trochę nietypowe. Napisałem wtyczkę , która przełącza pliki na przemian „tak, jak chciałem” (przeglądając wszystkie dostępne globpath()wyniki). Rozwiązuje niektóre problemy z prostotą powyższego, możesz sprawdzić jego implementację, jeśli chcesz dowiedzieć się więcej.

Na koniec punkt „przywróć pozycję kursora”. Zapisałem go na koniec, ponieważ jest prostopadły do ​​alternatywnego przełączania (moja wtyczka nie obsługuje tego na przykład), ale możesz wprowadzić go do swojej funkcji, jeśli chcesz rzucić własny. :help line()ma komendę automatyczną, która jest przydatna do przywracania pozycji kursora do miejsca, w którym znajdowała się w momencie ostatniego otwarcia pliku:

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

Po prostu włożyłem to lub coś bardzo podobnego, .vimrcponieważ wolę takie zachowanie przez cały czas. Możesz łatwo po prostu umieścić kod w innym miejscu.


źródło
2

Możesz użyć wtyczki vim-fswitch wraz z następującą konfiguracją w swoim .vimrcpliku:

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>

Jeśli wpiszesz <Leader>(która jest \domyślnie), a następnie sw sposób .hpplub .hpliku, plugin będzie sprawdzić, czy dopasowanie .cpp, .ccczy .cplik istnieje:

  • przez zastąpienie includeprzez srcw ścieżce bieżącego pliku
  • patrząc do srcfolderu nad bieżącym plikiem
  • przeglądając folder bieżącego pliku

Istnieje więcej opcji można użyć, aby dopasować swój projekt lepiej w dokumentacji . Zajmie ci to kilka minut, ale kiedy już to dobrze zrobisz, powinieneś to pokochać. Osobiście uważam, że jest bardzo elastyczny i rozszerzalny, a ponadto działa równie dobrze dla wielu rodzajów plików (.m, .h, .inl itp ...).

XPac27
źródło
1

W Twoim .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>

Umożliwia to szybkie poruszanie się między oknami, po prostu używając klawiszy kierunkowych Ctrl i VIM z wiersza głównego. Niesamowite jest to, że masz jeden wspólny sposób na przeskakiwanie do dowolnego okna, w tym do okna szybkiego dostępu.

Aby szybko przełączać się między nagłówkiem i źródłem, którego używam, można vim-scripts/a.vimznaleźć tutaj: https://github.com/vim-scripts/a.vim , użyj :Apolecenia, aby przełączyć.

Uwaga dodatkowa => Jeśli używasz tmux, możesz użyć https://github.com/christoomey/vim-tmux-navigator, aby płynnie przechodzić między oknami vim lub nvim a terminalem.

użytkownik1135541
źródło
1

Po prostu podzielę się moją super szybką i brudną wersją ...

Skonfiguruj moje mapowania; Alt-O otwiera powiązany plik w tym samym oknie, Alt-Shift-O otwiera się w podziale ...

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

Następnie mam funkcję, która pobiera listę powiązanych plików. Chciałem go ulepszyć, aby posiekać nazwę pliku w pierwszej kropce, a nie w ostatniej, ale to wciąż ćwiczenie dla czytelnika.

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

Moja konfiguracja .vimrc jest czasami wyspecjalizowana dla każdego klienta; niektóre mają źródła i zawierają osobne hierarchie folderów, niektóre mają je razem. Domyślnie zakładam, że wszystkie są w pobliżu, ale jeśli będę musiał polować, zapewnię funkcję zastępczą taką jak ta.

" 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

Następnie przeglądam tę listę plików, aby znaleźć plik bieżącego bufora i przechodzę do następnego na liście. To nie jest często tak proste jak para .cpp / .h, często będę miał inne rzeczy, które należy wziąć pod uwagę.

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

I w końcu dwie funkcje, które albo otwierają się w bieżącym oknie, albo dzielą ...

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

Moja wersja dzielenia zawsze umieszcza pliki .cpp i .c w podziale poniżej, w innym przypadku domyślnym podziale (co w moim przypadku jest powyżej).

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
dash-tom-bang
źródło