Commutazione dei buffer .c / .h


8

Normalmente lavoro con 2 finestre, divise verticalmente.

Il problema che vorrei risolvere è: saltare facilmente avanti e indietro dal file di implementazione header <->

Sto studiando, senza fortuna, 2 modi per farlo:

  1. Apri il file alternativo nella finestra corrente : ci sono molti modi per farlo, tuttavia, non riesco a trovare un modo che ricordi dove ero nel file precedente (es. Vai all'intestazione, salta indietro, ma non nello stesso posto in cui ero ).
  2. Apri il file alternativo nell'altra finestra : è ben definito, dato che lavoro sempre solo con 2 finestre, tuttavia non ho le conoscenze di VIM per farlo.

1
Per un suggerimento sul primo problema, vedere end :h line()(soluzione generica): "Questo comando automatico passa all'ultima posizione nota in un file subito dopo averlo aperto, se il segno" "è impostato:: au BufReadPost * if line (" ' \ "")> 1 && line ("'\" ") <= line (" $ ") | exe "normal! g` \" "| endif
VanLaser

Non puoi usare una jump list e / o segni incrociati?
fruglemonkey,


2
forse stai cercando A.vim
Christian

Risposte:


5

Ci sono tre passaggi principali per realizzare ciò che stai chiedendo:

  • ottenere il nome del file alternativo
  • aprendo quel file nella finestra corrente o in un'altra finestra come desiderato
  • ripristinare la posizione del cursore all'interno di quel file

Per trovare il nome del file alternativo che si desidera suddividere il nome del file corrente in "root" e "estensione". Un modo semplice per farlo è:

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

Se sai che stai sempre passando da .he a .cppfile, puoi facilmente modificare l'estensione da uno all'altro:

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

In alternativa, creare un dizionario che associa estensioni conosciute a estensioni alternative potenzialmente valide. Oppure usa globpath()per ottenere tutte le alternative possibili per il file corrente:

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

e scegli il primo, o qualsiasi altra cosa. Preferisco l' globpathapproccio, con qualche intelligenza in più che descriverò più avanti. Dopo aver selezionato l'estensione di destinazione, formare il percorso target completo:

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

Ora puoi aprire il file alternativo nella finestra corrente:

execute "edit " . target

Oppure usa winnr()per ottenere il numero "altra finestra" ( winnr("#")è la finestra su cui <C-W>psaltare, oppure puoi codificarlo se sai che sarà sempre lo stesso per la tua configurazione) e fare qualcosa del tipo:

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

Questo ti offre una soluzione davvero basilare per l'apertura di file alternativi. Ci sono alcune carenze con l'approccio sopra, dal momento che l'ho scritto per essere semplice ed è un po 'fuori dal comune. Ho scritto un plug-in che alterna i file cambiando "come volevo" (scorrendo tutti i globpath()risultati disponibili ). Risolve alcuni dei problemi con la semplicità di quanto sopra, puoi verificarne l'implementazione se sei interessato a esplorare di più.

Infine, il punto "ripristina posizione cursore". L'ho salvato per ultimo poiché è ortogonale alla cosa di commutazione alternativa (il mio plug-in non lo gestisce ad esempio), ma potresti metterlo nella tua funzione se vuoi lanciare il tuo. :help line()ha un autocommand utile per ripristinare la posizione del cursore nella posizione in cui era stato aperto l'ultima volta il file:

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

L'ho appena inserito, o qualcosa di molto simile, .vimrcperché preferisco il comportamento in ogni momento. Tuttavia, potresti semplicemente inserire il codice altrove.


2

È possibile utilizzare il plug -in vim-fswitch insieme alla seguente configurazione nel .vimrcfile:

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>

Se si digita <Leader>(che è \di default) seguita da suna .hppo .hfile, il plugin controllare se una corrispondenza .cpp, .cco di .cfile esiste:

  • sostituendo includecon srcnel percorso del file corrente
  • guardando nella srccartella sopra il file corrente
  • guardando nella cartella del file corrente

Ci sono più opzioni che potresti usare per adattare meglio il tuo progetto alla documentazione . Ti ci vorranno alcuni minuti ma una volta capito bene dovresti amarlo. Personalmente lo trovo molto flessibile ed estensibile, inoltre funziona altrettanto bene per molti tipi di file (.m, .h, .inl ecc ...).


1

Nella tua .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>

Ciò consente di spostarsi rapidamente da una finestra all'altra, semplicemente usando i tasti di direzione Ctrl e VIM dalla riga principale. La bellezza di questo è che hai un modo comune per passare a qualsiasi finestra, inclusa la finestra di correzione rapida.

Per passare rapidamente da intestazione a sorgente, utilizzo vim-scripts/a.vimqui: https://github.com/vim-scripts/a.vim , utilizzare il :Acomando per attivare / disattivare.

Nota a margine => Se usi tmux, puoi usare https://github.com/christoomey/vim-tmux-navigator per saltare tra le finestre vim o nvim e un terminale senza soluzione di continuità.


1

Condividerò solo la mia versione super veloce e sporca ...

Imposta i miei mapping; alt-o apre il file correlato nella stessa finestra, alt-shift-o si apre in una divisione ...

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

Quindi ho una funzione che ottiene l'elenco dei file correlati. Ho intenzione di modificarlo per tagliare il nome del file nel primo punto anziché nell'ultimo ma è comunque un esercizio per il lettore.

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

La mia configurazione .vimrc è talvolta specializzata per client; alcuni hanno origine e includono gerarchie di cartelle separate, altri li hanno insieme. Per impostazione predefinita presumo che siano tutti nelle vicinanze, ma se devo cacciare fornirò una funzione di sostituzione come questa.

" 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

Quindi guardo attraverso quell'elenco di file per trovare il file del buffer corrente e passare a quello successivo nell'elenco. Spesso non è semplice come una coppia .cpp / .h, spesso avrò altre cose che devono essere considerate.

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

E infine le due funzioni che si aprono nella finestra corrente o fanno una divisione ...

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

La mia versione di divisione mette sempre i file .cpp e .c in una suddivisione di seguito, altrimenti dividi l'impostazione predefinita (che nel mio caso è sopra).

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.