Umschalten der .c / .h-Puffer

8

Normalerweise arbeite ich mit 2 Fenstern, die vertikal geteilt sind.

Das Problem, das ich lösen möchte, ist: leichtes Hin- und Herspringen von der Header <-> Implementierungsdatei

Ich untersuche ohne Glück zwei Möglichkeiten, dies zu tun:

  1. Alternative Datei im aktuellen Fenster öffnen : Es gibt viele Möglichkeiten, dies zu tun. Ich kann jedoch keine Möglichkeit finden, sich daran zu erinnern, wo ich mich in der vorherigen Datei befunden habe (dh zum Header springen, zurückspringen, aber nicht an die gleiche Stelle, an der ich mich befand ).
  2. Alternative Datei im anderen Fenster öffnen : Dies ist genau definiert, da ich immer nur mit 2 Fenstern arbeite, mir jedoch die vim-Kenntnisse fehlen, um dies zu tun.
zach
quelle
1
Einen Hinweis auf das erste Problem finden Sie unter Ende von :h line()(generische Lösung): "Dieser automatische Befehl springt direkt nach dem Öffnen zur letzten bekannten Position in einer Datei, wenn die Markierung '" gesetzt ist :: au BufReadPost * if line ("' "")> 1 && Zeile ("'") <= Zeile ("$") | exe "normal! g` \" | endif
VanLaser
Können Sie keine Sprungliste und / oder dateiübergreifende Markierungen verwenden?
Fruglemonkey
2
Vielleicht suchen Sie nach A.vim
Christian Brabandt

Antworten:

5

Es gibt drei Hauptschritte, um das zu erreichen, was Sie verlangen:

  • Abrufen des Namens der alternativen Datei
  • Öffnen dieser Datei im aktuellen Fenster oder in einem anderen Fenster nach Wunsch
  • Wiederherstellen der Cursorposition in dieser Datei

Um den alternativen Dateinamen zu finden, möchten Sie den aktuellen Dateinamen in "root" und "extension" aufteilen. Ein einfacher Weg, dies zu tun, ist:

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

Wenn Sie wissen, dass Sie immer nur zwischen .hund .cppDateien wechseln, können Sie die Erweiterung einfach von einer zur anderen ändern:

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

Alternativ können Sie ein Wörterbuch erstellen, das bekannte Erweiterungen potenziell gültigen alternativen Erweiterungen zuordnet. Oder verwenden Sie globpath(), um alle möglichen Alternativen für die aktuelle Datei abzurufen:

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

und wähle den ersten oder was auch immer. Ich bevorzuge den globpathAnsatz, mit einigen zusätzlichen Intelligenz, die ich später beschreiben werde. Nachdem Sie die Zielerweiterung ausgewählt haben, bilden Sie den vollständigen Zielpfad:

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

Jetzt können Sie die alternative Datei im aktuellen Fenster öffnen:

execute "edit " . target

Oder verwenden Sie winnr(), um die Nummer des "anderen Fensters" abzurufen ( winnr("#")ist das Fenster, <C-W>pzu dem gesprungen wird, oder Sie können es hart codieren, wenn Sie wissen, dass es für Ihr Setup immer gleich ist) und tun Sie etwas wie:

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

Dies gibt Ihnen eine wirklich einfache Lösung zum Öffnen alternativer Dateien. Es gibt ein paar Mängel bei dem obigen Ansatz, da ich ihn so geschrieben habe, dass er unkompliziert ist und ein bisschen von der Stange ist. Ich habe ein Plugin geschrieben , das das alternative Wechseln von Dateien "nach meinen Wünschen" durchführt (durch alle verfügbaren globpath()Ergebnisse blättern). Es behebt einige der Probleme mit der Einfachheit des oben genannten. Sie können die Implementierung überprüfen, wenn Sie mehr erfahren möchten.

Schließlich der Punkt "Cursorposition wiederherstellen". Ich habe es zum letzten Mal gespeichert, da es orthogonal zum alternativen Schaltobjekt ist (mein Plugin behandelt es zum Beispiel nicht), aber Sie könnten es in Ihre Funktion einfügen, wenn Sie Ihr eigenes rollen wollen. :help line()hat einen automatischen Befehl, der nützlich ist, um die Cursorposition an der Stelle wiederherzustellen, an der sie sich befand, als die Datei zuletzt geöffnet wurde:

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

Ich habe das oder etwas sehr Ähnliches einfach in meine aufgenommen, .vimrcda ich das Verhalten die ganze Zeit bevorzuge. Sie können den Code aber auch einfach woanders platzieren.


quelle
2

Sie können das vim-fswitch- Plugin zusammen mit der folgenden Konfiguration in Ihrer .vimrcDatei verwenden:

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>

Wenn Sie eingeben <Leader>(die \Standardeinstellung) , gefolgt von sin einer .hppoder .hDatei, wird das Plugin prüfen , ob eine passende .cpp, .ccoder .cDatei vorhanden ist :

  • durch Ersetzen includedurch srcim Pfad der aktuellen Datei
  • indem Sie in den srcOrdner über der aktuellen Datei schauen
  • indem Sie im Ordner der aktuellen Datei suchen

Es gibt mehr Optionen, mit denen Sie Ihr Projekt besser in die Dokumentation integrieren können . Es wird ein paar Minuten dauern, aber sobald Sie es richtig verstanden haben, sollten Sie es lieben. Ich persönlich finde es sehr flexibel und erweiterbar, und es funktioniert genauso gut für viele Arten von Dateien (.m, .h, .inl usw.).

XPac27
quelle
1

In deinem .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>

Auf diese Weise können Sie schnell zwischen Fenstern wechseln, indem Sie einfach die Richtungstasten Strg und VIM in der Startzeile verwenden. Das Besondere daran ist, dass Sie auf eine übliche Weise zu jedem Fenster springen können, einschließlich des Quickfix-Fensters.

Um schnell zwischen Header und Quelle zu wechseln, verwenden vim-scripts/a.vimSie hier: https://github.com/vim-scripts/a.vim , verwenden Sie den :ABefehl zum Umschalten.

Randnotiz => Wenn Sie tmux verwenden, können Sie mit https://github.com/christoomey/vim-tmux-navigator nahtlos zwischen vim- oder nvim-Fenstern und einem Terminal wechseln.

user1135541
quelle
1

Ich werde nur meine superschnelle und schmutzige Version teilen ...

Richten Sie meine Zuordnungen ein. alt-o öffnet die zugehörige Datei im selben Fenster, alt-shift-o öffnet in einem Split ...

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

Dann habe ich eine Funktion, die die Liste der zugehörigen Dateien abruft. Ich wollte es optimieren, um den Dateinamen am ersten und nicht am letzten Punkt zu entfernen, aber das ist immer noch eine Übung für den Leser.

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

Mein .vimrc-Setup ist manchmal auf jeden Client spezialisiert. Einige haben Quellcode und enthalten separate Ordnerhierarchien, andere haben sie zusammen. Standardmäßig gehe ich davon aus, dass sie alle in der Nähe sind, aber wenn ich jagen muss, werde ich eine Ersatzfunktion wie diese bereitstellen.

" 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

Dann schaue ich durch diese Liste von Dateien, um die Datei des aktuellen Puffers zu finden und gehe zur nächsten in der Liste. Es ist nicht oft so einfach wie ein .cpp / .h-Paar, oft habe ich andere Dinge, die berücksichtigt werden müssen.

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

Und schließlich die beiden Funktionen, die entweder im aktuellen Fenster geöffnet werden oder eine Teilung durchführen ...

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

In meiner Aufteilungsversion werden .cpp- und .c-Dateien immer in eine untergeordnete Aufteilung verschoben, andernfalls wird die Aufteilung standardmäßig (in meinem Fall über) geteilt.

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
quelle