Mengganti buffer .c / .h


8

Saya biasanya bekerja dengan 2 jendela, terbagi secara vertikal.

Masalah yang ingin saya pecahkan, adalah: dengan mudah melompat-lompat dari header file implementasi <->

Saya sedang menyelidiki, tanpa hasil, 2 cara untuk melakukan ini:

  1. Buka file alternatif di jendela saat ini : Ada banyak cara untuk melakukan ini, namun, saya tidak dapat menemukan cara yang mengingat di mana saya berada di file sebelumnya (yaitu melompat ke header, melompat kembali, tetapi tidak ke tempat yang sama dengan saya sebelumnya) ).
  2. Buka file alternatif di jendela lain : Ini didefinisikan dengan baik, karena saya hanya pernah bekerja dengan 2 jendela, namun saya tidak memiliki pengetahuan vim untuk melakukan ini.

1
Untuk petunjuk tentang masalah pertama, lihat bagian akhir :h line()(solusi umum): "Perintah otomatis ini melompat ke posisi terakhir yang diketahui dalam sebuah file tepat setelah membukanya, jika tanda" "diset:: au BufReadPost * if line (" ' \ "")> 1 && baris ("'\" ") <= baris (" $ ") | exe "normal! g` \" "| endif
VanLaser

Tidak bisakah Anda menggunakan daftar lompat dan / atau tanda lintas file?
fruglemonkey


2
mungkin Anda mencari A.vim
Christian Brabandt

Jawaban:


5

Ada tiga langkah utama dalam mencapai apa yang Anda tanyakan:

  • mendapatkan nama file alternatif
  • membuka file itu di jendela saat ini atau di jendela lain seperti yang diinginkan
  • mengembalikan posisi kursor dalam file itu

Untuk menemukan nama file alternatif, Anda ingin memecah nama file saat ini menjadi "root" dan "ekstensi." Cara sederhana untuk melakukan ini adalah:

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

Jika Anda tahu Anda hanya pernah beralih antara .hdan .cppfile, Anda dapat mengubah ekstensi dari satu ke yang lain dengan mudah:

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

Atau, buat kamus yang memetakan ekstensi yang dikenal ke ekstensi alternatif yang berpotensi valid. Atau gunakan globpath()untuk mendapatkan semua alternatif yang memungkinkan untuk file saat ini:

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

dan pilih yang pertama, atau apa pun. Saya lebih suka globpathpendekatannya, dengan beberapa kecerdasan ekstra yang akan saya jelaskan nanti. Setelah Anda memilih ekstensi target, bentuk jalur target lengkap:

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

Sekarang Anda dapat membuka file alternatif di jendela saat ini:

execute "edit " . target

Atau gunakan winnr()untuk mendapatkan nomor "jendela lain" ( winnr("#")adalah jendela yang <C-W>pakan melompat ke, atau Anda dapat membuat kode-keras jika Anda tahu itu akan selalu sama untuk pengaturan Anda) dan melakukan sesuatu seperti:

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

Ini memberi Anda solusi yang sangat mendasar untuk membuka file alternatif. Ada beberapa kekurangan dengan pendekatan di atas, karena saya menulisnya dengan terus terang dan itu agak tidak jelas. Saya telah menulis sebuah plugin yang melakukan penggantian file alternatif "seperti yang saya inginkan," (bersepeda melalui semua globpath()hasil yang tersedia ). Ini mengatasi beberapa masalah dengan kesederhanaan di atas, Anda dapat memeriksa implementasinya jika Anda tertarik untuk mengeksplorasi lebih lanjut.

Akhirnya, titik "kembalikan posisi kursor". Saya menyimpannya untuk yang terakhir karena itu ortogonal ke hal switching alternatif (plugin saya tidak menanganinya misalnya), tetapi Anda bisa memasukkannya ke dalam fungsi Anda jika Anda ingin menggulirkannya sendiri. :help line()memiliki perintah otomatis yang berguna untuk mengembalikan posisi kursor ke posisi saat file dibuka terakhir:

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

Saya hanya menempatkan itu, atau sesuatu yang sangat mirip, di saya .vimrckarena saya lebih suka perilaku sepanjang waktu. Anda dapat dengan mudah menaruh kode di tempat lain.


2

Anda dapat menggunakan plugin vim-fswitch bersama dengan konfigurasi berikut di .vimrcfile Anda :

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>

Jika Anda mengetik <Leader>(yang secara \default) diikuti oleh sdalam .hppatau .hfile, plugin akan memeriksa apakah ada yang cocok .cpp, .ccatau .cada file:

  • dengan mengganti includedengan srcdi jalur file saat ini
  • dengan melihat srcfolder di atas file saat ini
  • dengan melihat di folder file saat ini

Ada lebih banyak opsi yang dapat Anda gunakan agar sesuai dengan proyek Anda lebih baik dalam dokumentasi . Ini akan memakan waktu beberapa menit, tetapi begitu Anda bisa melakukannya dengan benar, Anda harus menyukainya. Saya pribadi merasa sangat fleksibel dan dapat dikembangkan, ditambah lagi berfungsi dengan baik untuk berbagai jenis file (.m, .h, .inl dll ...).


1

Di Anda .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>

Ini memungkinkan Anda untuk berpindah antar windows dengan cepat, hanya dengan menggunakan tombol arah Ctrl dan VIM dari baris home. Kehebatan ini, adalah Anda memiliki satu cara umum untuk melompat ke jendela mana pun, termasuk jendela perbaikan cepat.

Untuk beralih dengan cepat antara header dan sumber yang saya gunakan vim-scripts/a.vimditemukan di sini: https://github.com/vim-scripts/a.vim , gunakan :Aperintah untuk beralih.

Catatan Samping => Jika Anda menggunakan tmux, Anda dapat menggunakan https://github.com/christoomey/vim-tmux-navigator untuk melompat di antara jendela vim atau nvim dan terminal dengan mulus.


1

Saya hanya akan membagikan versi super cepat & kotor saya ...

Siapkan pemetaan saya; alt-o membuka file terkait di jendela yang sama, alt-shift-o terbuka dalam ...

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

Kemudian saya memiliki fungsi yang mendapat daftar file terkait. Saya bermaksud men-tweak untuk memotong nama file pada titik pertama dan bukan yang terakhir tapi itu masih merupakan latihan bagi pembaca.

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

Setup .vimrc saya terkadang khusus untuk setiap klien; beberapa memiliki sumber dan termasuk dalam hierarki folder yang terpisah, beberapa memilikinya bersama-sama. Secara default saya menganggap mereka semua dekat tetapi jika saya perlu berburu saya akan memberikan fungsi pengganti seperti ini.

" 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

Kemudian saya melihat daftar file untuk menemukan file buffer saat ini dan pergi ke yang berikutnya dalam daftar. Ini tidak sesederhana pasangan .cpp / .h, sering kali saya memiliki hal lain yang perlu dipertimbangkan.

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

Dan akhirnya dua fungsi yang terbuka di jendela saat ini atau melakukan pemisahan ...

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

Versi pemisahan saya selalu menempatkan file .cpp dan .c di dalam split di bawah, jika tidak default dibagi (dalam kasus saya di atas).

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.