Commutation des tampons .c / .h

8

Je travaille normalement avec 2 fenêtres, divisées verticalement.

Le problème que je voudrais résoudre est: sauter facilement d'avant en arrière à partir du fichier d'implémentation de l'en-tête <->

J'étudie, sans chance, 2 façons de procéder:

  1. Ouvrir un autre fichier dans la fenêtre actuelle : il existe de nombreuses façons de le faire, cependant, je ne trouve pas un moyen qui se souvienne où j'étais dans le fichier précédent (c'est-à-dire passer à l'en-tête, revenir en arrière, mais pas au même endroit où j'étais) ).
  2. Ouvrir un fichier alternatif dans l' autre fenêtre : C'est bien défini, car je ne travaille qu'avec 2 fenêtres, mais je n'ai pas les connaissances nécessaires pour le faire.
zach
la source
1
Pour un indice sur le 1er problème, voir fin de :h line()(solution générique): "Cette autocommande saute à la dernière position connue dans un fichier juste après son ouverture, si la marque" "est définie:: au BufReadPost * if line (" ' \ "")> 1 && ligne ("'\" ") <= ligne (" $ ") | exe "normal! g` \" "| endif
VanLaser
Vous ne pouvez pas utiliser une liste de raccourcis et / ou des marques de fichiers croisés?
fruglemonkey
2
vous cherchez peut-être A.vim
Christian Brabandt

Réponses:

5

Il y a trois étapes principales pour accomplir ce que vous demandez:

  • obtenir le nom du fichier alternatif
  • ouvrir ce fichier dans la fenêtre actuelle ou dans une autre fenêtre comme vous le souhaitez
  • restauration de la position du curseur dans ce fichier

Pour trouver le nom de fichier alternatif, vous souhaitez décomposer le nom de fichier actuel en «racine» et «extension». Un moyen simple de le faire est:

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

Si vous savez que vous ne faites que basculer entre les fichiers .het .cpp, vous pouvez facilement changer l'extension de l'un à l'autre:

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

Vous pouvez également créer un dictionnaire mappant les extensions connues à des extensions alternatives potentiellement valides. Ou utilisez globpath()pour obtenir toutes les alternatives possibles pour le fichier actuel:

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

et choisissez le premier, ou autre chose. Je préfère l' globpathapproche, avec quelques astuces supplémentaires que je décrirai plus tard. Une fois que vous avez choisi l'extension cible, formez le chemin cible complet:

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

Vous pouvez maintenant ouvrir le fichier alternatif dans la fenêtre actuelle:

execute "edit " . target

Ou utilisez winnr()pour obtenir le numéro de "l'autre fenêtre" ( winnr("#")c'est la fenêtre vers laquelle <C-W>psauter, ou vous pouvez la coder en dur si vous savez qu'elle sera toujours la même pour votre configuration) et faites quelque chose comme:

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

Cela vous donne une solution vraiment basique pour ouvrir des fichiers alternatifs. Il y a quelques lacunes avec l'approche ci-dessus, car je l'ai écrite pour être simple et c'est un peu à l'improviste. J'ai écrit un plugin qui alterne le changement de fichier "comme je le voulais" (en parcourant tous les globpath()résultats disponibles ). Il résout certains des problèmes liés à la simplicité de ce qui précède, vous pouvez vérifier sa mise en œuvre si vous souhaitez en savoir plus.

Enfin, le point "restaurer la position du curseur". Je l'ai gardé pour la dernière fois car il est orthogonal à la chose de commutation alternative (mon plugin ne le gère pas par exemple), mais vous pouvez le mettre dans votre fonction si vous voulez rouler le vôtre. :help line()a une autocommande qui est utile pour restaurer la position du curseur à l'endroit où il était lors de la dernière ouverture du fichier:

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

Je mets juste ça, ou quelque chose de très similaire, dans mon .vimrcpuisque je préfère le comportement tout le temps. Cependant, vous pouvez facilement mettre le code ailleurs.


la source
2

Vous pouvez utiliser le plugin vim-fswitch avec la configuration suivante dans votre .vimrcfichier:

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>

Si vous tapez <Leader>(qui est \par défaut) , suivie par sun .hppou .hfichier, le plugin vérifie si une correspondance .cpp, .ccou le .cfichier existe:

  • en remplaçant includepar srcdans le chemin du fichier courant
  • en regardant dans le srcdossier au dessus du fichier courant
  • en regardant dans le dossier du fichier courant

Il y a plus d'options que vous pouvez utiliser pour mieux adapter votre projet dans la documentation . Cela vous prendra quelques minutes, mais une fois que vous aurez bien compris, vous devriez l'aimer. Personnellement, je le trouve très flexible et extensible, en plus il fonctionne aussi bien pour de nombreux types de fichiers (.m, .h, .inl etc ...).

XPac27
la source
1

Dans ton .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>

Cela vous permet de vous déplacer rapidement entre les fenêtres, en utilisant simplement les touches de direction Ctrl et VIM de la ligne d'accueil. Ce qui est génial, c'est que vous avez une façon courante de passer à n'importe quelle fenêtre, y compris la fenêtre de correction rapide.

Pour basculer rapidement entre l'en-tête et la source que j'utilise, vim-scripts/a.vimtrouvée ici: https://github.com/vim-scripts/a.vim , utilisez la :Acommande pour basculer.

Note latérale => Si vous utilisez tmux, vous pouvez utiliser https://github.com/christoomey/vim-tmux-navigator pour basculer entre les fenêtres vim ou nvim et un terminal de manière transparente.

user1135541
la source
1

Je vais juste partager ma version super rapide et sale ...

Configurer mes mappages; alt-o ouvre le fichier associé dans la même fenêtre, alt-shift-o s'ouvre dans un split ...

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

Ensuite, j'ai une fonction qui obtient la liste des fichiers associés. J'ai voulu le modifier pour couper le nom de fichier au premier point plutôt qu'au dernier, mais c'est toujours un exercice pour le lecteur.

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

Ma configuration .vimrc est parfois spécialisée par client; certains ont la source et les incluent dans des hiérarchies de dossiers séparées, certains les ont ensemble. Par défaut, je suppose qu'ils sont tous à proximité, mais si je dois chasser, je fournirai une fonction de remplacement comme celle-ci.

" 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

Ensuite, je regarde cette liste de fichiers pour trouver le fichier du tampon actuel et je passe au suivant dans la liste. Ce n'est pas souvent aussi simple qu'une paire .cpp / .h, souvent j'ai d'autres choses à considérer.

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

Et puis enfin les deux fonctions qui s'ouvrent soit dans la fenêtre courante soit font un split ...

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

Ma version de fractionnement place toujours les fichiers .cpp et .c dans un fractionnement inférieur, sinon fractionné par défaut (qui dans mon cas est supérieur).

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
la source