การสลับบัฟเฟอร์. c / .h


8

ปกติฉันทำงานกับ 2 windows แยกในแนวตั้ง

ปัญหาที่ฉันต้องการแก้ไขคือ: ข้ามไปมาอย่างง่ายดายจากส่วนหัวของไฟล์การใช้งาน <->

ฉันกำลังตรวจสอบโดยไม่มีโชค 2 วิธีในการทำสิ่งนี้:

  1. เปิดไฟล์สำรองในหน้าต่างปัจจุบัน : มีหลายวิธีในการทำเช่นนี้อย่างไรก็ตามฉันไม่สามารถหาวิธีที่จำตำแหน่งที่ฉันอยู่ในไฟล์ก่อนหน้าได้ (เช่นข้ามไปที่ส่วนหัวข้ามกลับ แต่ไม่ใช่ตำแหน่งเดียวกับที่ฉันเป็น )
  2. เปิดไฟล์ทางเลือกในหน้าต่างอื่น : นี่เป็นคำจำกัดความที่ดีเนื่องจากฉันใช้งานได้เพียง 2 windows เท่านั้น แต่ฉันไม่มีความรู้เรื่องการทำสิ่งนี้

1
สำหรับคำแนะนำเกี่ยวกับปัญหาที่ 1 ให้ดูที่จุดสิ้นสุดของ:h line()(โซลูชันทั่วไป): "การทำสำเนาอัตโนมัตินี้ข้ามไปยังตำแหน่งสุดท้ายที่รู้จักในไฟล์หลังจากเปิดมันถ้าตั้งค่าเครื่องหมาย" ": au BufReadPost * if line (" ' \ "")> 1 && line ("'\" ") <= บรรทัด (" $ ") | exe "normal! g` \" "| endif
VanLaser

คุณไม่สามารถใช้รายการข้ามและ / หรือเครื่องหมายข้ามไฟล์ได้หรือไม่?
fruglemonkey


2
บางทีคุณอาจกำลังมองหาA.vim
Christian Brabandt

คำตอบ:


5

มีสามขั้นตอนหลักในการบรรลุสิ่งที่คุณขอ:

  • รับชื่อไฟล์สำรอง
  • เปิดไฟล์นั้นในหน้าต่างปัจจุบันหรือในหน้าต่างอื่นตามต้องการ
  • คืนค่าตำแหน่งเคอร์เซอร์ภายในไฟล์นั้น

หากต้องการค้นหาชื่อไฟล์อื่นคุณต้องการแบ่งชื่อไฟล์ปัจจุบันเป็น "root" และ "นามสกุล" วิธีง่ายๆในการทำเช่นนี้คือ:

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

หากคุณรู้ว่าคุณสลับไปมาระหว่าง.hและ.cppไฟล์คุณสามารถเปลี่ยนนามสกุลจากที่หนึ่งไปยังอีกที่หนึ่งได้อย่างง่ายดาย:

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

อีกทางหนึ่งคือสร้างการแมปส่วนขยายที่รู้จักในพจนานุกรมเพื่อส่วนขยายอื่นที่ถูกต้อง หรือใช้globpath()เพื่อรับตัวเลือกที่เป็นไปได้ทั้งหมดสำหรับไฟล์ปัจจุบัน:

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

และเลือกคนแรกหรืออะไรก็ตาม ฉันชอบglobpathวิธีนี้มากขึ้นด้วยสมาร์ทพิเศษที่ฉันจะอธิบายในภายหลัง เมื่อคุณเลือกส่วนขยายเป้าหมายแล้วให้สร้างเส้นทางเป้าหมายแบบเต็ม:

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

ตอนนี้คุณสามารถเปิดไฟล์ทางเลือกในหน้าต่างปัจจุบัน:

execute "edit " . target

หรือใช้winnr()เพื่อรับหมายเลข "หน้าต่างอื่น" ( winnr("#")เป็นหน้าต่างที่<C-W>pจะข้ามไปหรือคุณสามารถกำหนดรหัสได้ยากหากคุณรู้ว่ามันจะเหมือนกันสำหรับการตั้งค่าของคุณ) และทำสิ่งที่ชอบ:

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

นี่เป็นวิธีแก้ปัญหาพื้นฐานสำหรับเปิดไฟล์ทางเลือก มีข้อบกพร่องบางประการเกี่ยวกับวิธีการข้างต้นเนื่องจากฉันเขียนมันให้ตรงไปตรงมาและมันเป็นบิตนอกข้อมือ ฉันเขียนปลั๊กอินที่สลับไฟล์ "ในแบบที่ฉันต้องการ" (หมุนเวียนไปตามglobpath()ผลลัพธ์ทั้งหมดที่มี) มันแก้ไขปัญหาบางอย่างด้วยความเรียบง่ายข้างต้นคุณสามารถตรวจสอบการใช้งานหากคุณสนใจที่จะสำรวจเพิ่มเติม

ในที่สุดจุด "กู้คืนตำแหน่งเคอร์เซอร์" ฉันบันทึกไว้เป็นครั้งสุดท้ายเพราะมันเป็นมุมฉากกับสิ่งที่สลับกัน (ปลั๊กอินของฉันไม่ได้จัดการตัวอย่าง) แต่คุณสามารถใส่มันลงไปในฟังก์ชั่นของคุณถ้าคุณจะม้วนตัวเอง :help line()มีข้อความอัตโนมัติที่มีประโยชน์สำหรับการกู้คืนตำแหน่งเคอร์เซอร์ไปยังตำแหน่งที่เคยเป็นเมื่อไฟล์ถูกเปิดครั้งล่าสุด:

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

ฉันแค่ใส่มันหรือสิ่งที่คล้ายกันมากในของฉัน.vimrcตั้งแต่ฉันชอบพฤติกรรมตลอดเวลา คุณสามารถใส่รหัสที่อื่นได้อย่างง่ายดาย


2

คุณสามารถใช้ปลั๊กอินvim-fswitchพร้อมกับการกำหนดค่าต่อไปนี้ใน.vimrcไฟล์ของคุณ:

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>

ถ้าคุณพิมพ์<Leader>(ซึ่งเป็น\ค่าเริ่มต้น) ตามมาด้วยsใน.hppหรือ.hไฟล์ปลั๊กอินจะตรวจสอบว่าการจับคู่.cpp, .ccหรือ.cไฟล์ที่มีอยู่:

  • โดยแทนที่includeด้วยsrcในเส้นทางของไฟล์ปัจจุบัน
  • โดยดูในsrcโฟลเดอร์ด้านบนไฟล์ปัจจุบัน
  • โดยดูในโฟลเดอร์ของไฟล์ปัจจุบัน

มีตัวเลือกอื่น ๆ ที่คุณสามารถใช้เพื่อให้พอดีกับโครงการของคุณดีขึ้นในที่มีเอกสาร มันจะพาคุณไปไม่กี่นาที แต่เมื่อคุณทำให้ถูกต้องคุณควรจะรักมัน โดยส่วนตัวแล้วฉันพบว่ามันมีความยืดหยุ่นและสามารถขยายได้รวมถึงมันใช้งานได้ดีกับไฟล์หลายชนิด (.m, .h, .inl ฯลฯ ... )


1

ในตัวคุณ .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>

สิ่งนี้ช่วยให้คุณย้ายระหว่างหน้าต่างได้อย่างรวดเร็วเพียงแค่ใช้ปุ่มทิศทาง Ctrl และ VIM จากแถวบ้าน ความสุดยอดของสิ่งนี้คือคุณมีวิธีทั่วไปอย่างหนึ่งในการข้ามไปที่หน้าต่างใด ๆ รวมถึงหน้าต่าง Quickfix

หากต้องการสลับระหว่างส่วนหัวและแหล่งที่มาอย่างรวดเร็วฉันvim-scripts/a.vimพบได้ที่นี่: https://github.com/vim-scripts/a.vimใช้:Aคำสั่งเพื่อสลับ

หมายเหตุด้านข้าง => หากคุณใช้ tmux คุณสามารถใช้https://github.com/christoomey/vim-tmux-navigatorเพื่อข้ามระหว่างหน้าต่าง vim หรือ nvim และเทอร์มินัลอย่างราบรื่น


1

ฉันจะแบ่งปันเวอร์ชันที่รวดเร็วและสกปรกเป็นพิเศษ ...

ตั้งค่าการแมปของฉัน alt-o เปิดไฟล์ที่เกี่ยวข้องในหน้าต่างเดียวกัน alt-shift-o เปิดในแยก ...

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

จากนั้นฉันก็มีฟังก์ชั่นที่รับรายชื่อไฟล์ที่เกี่ยวข้อง ฉันตั้งใจจะบิดมันเพื่อตัดชื่อไฟล์ที่จุดแรกแทนที่จะเป็นจุดสุดท้าย แต่นั่นก็ยังเป็นการออกกำลังกายสำหรับผู้อ่าน

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

บางครั้งการติดตั้ง. vimrc ของฉันมีความเชี่ยวชาญต่อลูกค้า บางคนมีแหล่งที่มาและรวมอยู่ในลำดับชั้นของโฟลเดอร์ที่แยกจากกันบางคนมีพวกเขาอยู่ด้วยกัน โดยปกติฉันถือว่าพวกมันอยู่ใกล้ ๆ แต่ถ้าฉันต้องตามล่าฉันจะจัดหาฟังก์ชั่นทดแทนเช่นนี้

" 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

จากนั้นฉันจะดูรายการไฟล์นั้นเพื่อค้นหาไฟล์บัฟเฟอร์ปัจจุบันและไปที่ไฟล์ถัดไปในรายการ มันไม่ง่ายเหมือนคู่. cpp / .h บ่อยครั้งที่ฉันจะมีสิ่งอื่นที่ต้องพิจารณา

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

และในที่สุดทั้งสองฟังก์ชั่นที่เปิดในหน้าต่างปัจจุบันหรือแยก ...

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

เวอร์ชันการแยกของฉันมักจะใส่ไฟล์. cpp และ. c ไว้ในการแบ่งด้านล่างมิฉะนั้นค่าเริ่มต้นการแยก (ซึ่งในกรณีของฉันคือด้านบน)

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.