Mẹo và thủ thuật của Vim và Ctags [đã đóng]


485

Tôi vừa cài đặt Ctags (để giúp phát triển C ++) với Vim của tôi (hay đúng hơn là gVim), và muốn tìm hiểu các lệnh, macro, phím tắt, mẹo ưa thích của bạn đi cùng với nó ...

Chia sẻ kho vũ khí tốt nhất của bạn. Những tiện ích Vim nào khác mà bạn muốn giới thiệu cho C ++ khi phát triển Vim?

EDIT Những tiện ích bổ sung nào khác mà bạn sẽ sử dụng cùng với Ctags?

EDIT2 Phiên bản gVim nào bạn sử dụng với thẻ? Liệu nó có làm cho một sự khác biệt?

EDIT3 Làm thế nào để bạn nâng cao kinh nghiệm lập trình cho cả các dự án lớn và nhỏ?


15
Hãy chắc chắn rằng bạn đang sử dụng ctags (một triển khai hiện đại) để có kết quả tốt nhất: ctags.sourceforge.net
idbrii

17
Có lẽ kev không mang tính xây dựng?
Floyd

27
mặc dù closed as not constructivegần hai năm trước, nó rất mang tính xây dựng đối với tôi
sazary

15
Tôi nghĩ lý do thực sự để đóng câu hỏi này là: "Câu hỏi này, mặc dù rất hữu ích, nhưng không phù hợp với chính sách Hỏi và Đáp của StackOverflow. Hãy để câu hỏi và câu trả lời này chuyển đến Quora và phát triển trang web đó trong khi chúng tôi vẫn kiên trì đóng câu hỏi và trả lời".
Diego Pino

2
Tôi hiểu lý do tại sao câu hỏi này được đóng lại, đưa ra các quy tắc của SO. Nhưng việc gắn cờ một câu hỏi> 400 câu hỏi với câu trả lời> 300 câu hỏi để xóa là một chút về phía khó chịu, phải không?
DevSolar

Câu trả lời:


394

Ctrl+ ]- đi đến định nghĩa
Ctrl+ T- Nhảy trở lại từ định nghĩa.
Ctrl+ W Ctrl+ ]- Mở định nghĩa theo cách chia ngang

Thêm các dòng này trong vimrc
map <C-\> :tab split<CR>:exec("tag ".expand("<cword>"))<CR>
map <A-]> :vsp <CR>:exec("tag ".expand("<cword>"))<CR>

Ctrl+ \- Mở định nghĩa trong tab mới
Alt+ ]- Mở định nghĩa theo phân chia dọc

Sau khi các thẻ được tạo ra. Bạn có thể sử dụng các phím sau để gắn thẻ và gắn thẻ ngoài chức năng:

Ctrl+ Left MouseClick- Chuyển đến định nghĩa
Ctrl+ Right MouseClick- Quay trở lại từ định nghĩa


8
C -] => (phím điều khiển) và] phím C - T => (phím điều khiển) và phím T Chỉ dành cho người mới sử dụng ctags. Cảm ơn về thủ thuật tab mới
kumar

6
Tương tự, sau khi chia cửa sổ với Ctrl-w C-]bạn có thể thực hiện C-w T(còn gọi là Shift-t) để thay đổi phần tách đó thành một tab mới.
dash-tom-bang

1
@ Will Nếu bạn đang sử dụng vim từ thiết bị đầu cuối thì bạn phải thay đổi tùy chọn thiết bị đầu cuối để làm cho phím tùy chọn hoạt động giống như một phím alt. Nếu bạn đang sử dụng MacVim thì hãy thêm dòng này vào vimrc 'set macmeta'. Có tài liệu cho macmeta ,: h macmeta.
Amjith

17
g C-]rất hữu ích Nó mở một hộp thoại nhanh để chọn một trong số nhiều định nghĩa.
Vincenzo Pii

3
g]cũng hữu ích Bạn có thể định vị con trỏ trên tên thẻ và nhấn g]để có danh sách các thẻ phù hợp.
zeekvfu

176

Một dòng luôn đi trong .vimrc của tôi:

set tags=./tags;/

Điều này sẽ tìm trong thư mục hiện tại cho "thẻ", và đưa cây về phía gốc cho đến khi tìm thấy. IOW, bạn có thể ở bất cứ đâu trong cây nguồn của bạn thay vì chỉ là gốc của nó.


37
Đi lên tận gốc là quá mức. Tôi đề nghị chỉ đi lên nhà thay vào đó: tags + = tags; $ HOME
gotgenes

37
Các cây nguồn mà tôi làm việc không phải lúc nào cũng có trong thư mục nhà của tôi ... và vì $ HOME có xu hướng cách hai thư mục gốc ... tốt, tôi có thể đủ khả năng tìm kiếm thêm hai thư mục. :)
uzi

6
Tôi đồng ý với. Nếu cwd của tôi là / home / me / lập trình / foo / bar / baz / bang / bam thì chỉ có 8 tra cứu thư mục. Tôi cho rằng nó phụ thuộc vào khả năng chịu đựng tốc độ của bạn, nhưng thời gian tra cứu thư mục 1 không khác biệt đáng kể so với 8 trên máy của tôi.
Nate Murray

1
Nó phụ thuộc vào kịch bản của bạn, tôi cần sử dụng đề xuất gotgenes trên một trong các máy của mình vì có khoảng 8.000 thư mục trong / nhà và điều đó có xu hướng hơi chậm chạp.
jkerian

1
Có một cái gì đó tương tự cho cscope?
szx

45

Một plugin hữu ích khác để phát triển C là cscope Cũng giống như Ctags cho phép bạn chuyển sang định nghĩa, Cscope nhảy vào cuộc gọi chức năng .

Nếu bạn có cscope trong thư mục ~ / bin / của bạn, hãy thêm đoạn sau vào .vimrc của bạn và sử dụng g ^] để chuyển đến chức năng gọi (xem: help cscope).

if has("cscope")
    set csprg=~/bin/cscope
    set csto=0
    set cst
    set nocsverb
    " add any database in current directory
    if filereadable("cscope.out")
        cs add cscope.out
        " else add database pointed to by environment
    elseif $CSCOPE_DB != ""
        cs add $CSCOPE_DB
    endif
endif

Hầu như quên ... Cũng giống như ctags - bạn phải tạo (và cập nhật định kỳ) cơ sở dữ liệu. Tôi sử dụng đoạn script sau

select_files > cscope.files
ctags -L cscope.files
ctags -e -L cscope.files
cscope -ub -i cscope.files

Trong đó 'select_files' là một tập lệnh khác trích xuất danh sách các tệp C và tiêu đề từ Makefile. Bằng cách này, tôi chỉ lập chỉ mục các tập tin thực sự được sử dụng bởi dự án.


Lợi thế của cscope so với ctags là gì? Họ có khen nhau không?
Whaledawg

4
Họ bổ sung cho nhau. Ctags tìm định nghĩa của ký hiệu hoặc hàm. Cscope có thể tìm thấy tất cả những nơi gọi một chức năng. sử dụng cả hai điều này làm cho việc điều hướng trong các cây nguồn lớn rất dễ dàng.
nimrodm

1
Tuy nhiên, AFAIK cscope có sự hiểu biết hạn chế về C ++.
Luc Hermitte

Nó là hạn chế, và không tốt lắm. Nhưng với những gì nó làm (nhảy sang USAGES), không có sự thay thế nào tốt hơn. Vấn đề chính của nó là khi bạn muốn chuyển sang các lệnh gọi hàm (f), bạn thường cần phải nhảy đến bất kỳ nơi nào mà biểu tượng được sử dụng thay vào đó và lọc kết quả về mặt tinh thần ...
Greg Rogers

2
@Whaledawg Có, khi tôi nhấn CTRL +] card âm thanh của tôi sẽ gửi "clap.wav" trong đầu ra :)
Patrizio Rullo

27

Bạn có thể thêm các thư mục để tra cứu ctags của bạn. Ví dụ: tôi có một chỉ mục ctags được xây dựng cho Qt4 và có cái này trong .vimrc của tôi:

set tags+=/usr/local/share/ctags/qt4


16

Tôi sử dụng ALT-left và ALT-right để bật / đẩy từ / đến ngăn xếp thẻ.

" Alt-right/left to navigate forward/backward in the tags stack
map <M-Left> <C-T>
map <M-Right> <C-]>

Nếu bạn sử dụng hjklcho phong trào, bạn có thể lập bản đồ <M-h><M-l>thay vào đó.


không giống như ctrl -] và ctrl-t - Tôi đoán, đề xuất của bạn sạch hơn một chút.

@Sasha, xin lỗi? Không biết bạn đang nói gì. = X Để lưu ý, điều này cũng hoạt động trong: trợ giúp.
strager

2
Tôi nghĩ rằng điều này là trực quan và sạch sẽ hơn so với mặc định.
Ayman

1
@Ayman Nhưng cũng vi phạm nguyên tắc không phải di chuyển tay khỏi homerow, như sử dụng hjkl vs các phím mũi tên.
TankorSmash

@TankorSmash, nguyên tắc gì?
strager

10

Một số định nghĩa cùng tên

<C-w>g<C-]>mở định nghĩa trong một tách, nhưng cũng làm :tjumptheo định nghĩa hoặc, nếu có một số định nghĩa, trình bày cho bạn một danh sách các định nghĩa để lựa chọn.


2
Tương tự như lệnh đầu tiên, vim có một :ptaglệnh mở định nghĩa trong cửa sổ xem trước.
idbrii

1
Cửa sổ xem trước là tốt vì bạn có thể đóng nó bằng: pc từ bất kỳ cửa sổ nào khác, mà không cần phải di chuyển con trỏ đến cửa sổ xem trước.
Heikki Naski

Ngoài ra còn có một thủ thuật autocmd gọn gàng với ptag :h CursorHold-exampleđể hiển thị thẻ cho mục dưới con trỏ trong cửa sổ xem trước sau khi hết thời gian cấu hình.
dash-tom-bang

+1 cho: tjump tôi đã bị ràng buộc: tjump <Cr> <Cw> <CR> hoạt động tốt hơn <C -]> imho Rất thích kết hợp hành vi này với: ptag
Andreas Fliesberg

:helpđôi khi thật tuyệt vời ... nhìn thấy :help CTRL-W_g}:ptjump
Andreas Fliesberg

8

Lệnh tôi đang sử dụng nhiều nhất là C-] nhảy đến định nghĩa của hàm dưới con trỏ. Bạn có thể sử dụng nó thường xuyên hơn để theo dõi nhiều cuộc gọi hơn. Sau đó, Co sẽ đưa bạn trở lại một cấp, Ci lại tiến sâu hơn.


16
Ct quay trở lại một cấp trong ngăn xếp C-], trong khi Co quay trở lại vị trí con trỏ trước đó sau khi di chuyển. Vì vậy, nếu bạn C-] đến một chức năng rồi trang xuống, Ct sẽ quay lại ngay lập tức trong khi Co sẽ quay trở lại bắt đầu chức năng, sau đó quay lại cuộc gọi.
Greg Hewgill

6

Tôi đã tìm thấy taglist plug-in một cuốn sách phải có. Nó liệt kê tất cả các thẻ mà nó biết về (các tệp mà bạn đã mở) trong một cửa sổ riêng biệt và làm cho nó rất dễ dàng điều hướng các tệp lớn hơn.

Tôi sử dụng nó chủ yếu để phát triển Python, nhưng nó chỉ có thể tốt hơn cho C / C ++.


5

Tôi đã đóng gói các thao tác thẻ trong một plugin thử nghiệm của tôi.

Về phát triển C ++ trong vim, tôi đã trả lời ở đó : Tôi sử dụng bộ riêng của mình và một vài plugin khác.



4

Tôi đặt phần sau vào tệp .gvimrc của mình, tìm kiếm cây từ bất kỳ điểm nào cho tệp thẻ khi gvim bắt đầu:

function SetTags()
    let curdir = getcwd()

    while !filereadable("tags") && getcwd() != "/"
        cd ..
    endwhile

    if filereadable("tags")
        execute "set tags=" . getcwd() . "/tags"
    endif

    execute "cd " . curdir
endfunction

call SetTags()

Sau đó, tôi định kỳ tạo lại một tệp thẻ ở đầu cây nguồn của mình với một tập lệnh trông giống như:

#!/bin/bash

find . -regex ".*\.\(c\|h\|hpp\|cc\|cpp\)" -print | ctags --totals --recurse --extra="+qf" --fields="+i" -L -

7
Bạn chỉ cần phát minh lại tìm kiếm đi lên. Xem: h tìm kiếm tập tin. Xem thêm stackoverflow.com/questions/563616/vimctags-tips-and-tricks/
mẹo

2

Tôi sử dụng vim trong macos và các ctags ban đầu không hoạt động tốt, vì vậy tôi tải xuống mới nhất và cấu hình thực hiện cài đặt. Tôi cài đặt ctgas trong / usr / local / bin / ctags (để giữ bản gốc)

"taglist
let Tlist_Ctags_Cmd = "/usr/local/bin/ctags"
let Tlist_WinWidth = 50
map <leader>ta :TlistToggle<cr>
map <leader>bta :!/usr/local/bin/ctags -R .<CR>
set tags=tags;/
map <M-j> <C-]>
map <M-k> <C-T>

1

Tôi đã điều chỉnh chức năng tìm kiếm SetTags () ở trên (cần được thay thế bằng tương đương set tags+=./tags;/) để hoạt động cho cscope. Có vẻ để làm việc!

"cscope file-searching alternative
function SetCscope()
    let curdir = getcwd()

    while !filereadable("cscope.out") && getcwd() != "/"
            cd ..
                endwhile

    if filereadable("cscope.out")
            execute "cs add " . getcwd() . "/cscope.out"
                endif

    execute "cd " . curdir
    endfunction

call SetCscope()

3
Như gotgenes đã nói, Bạn chỉ cần phát minh lại tìm kiếm hướng lên. Xem: h tìm kiếm tập tin. Xem plugin này cho một ví dụ có liên quan.
idbrii

1

Một lần lặp khác trên hàm SetCscope () ở trên. Điều đó đặt đường dẫn trước của cscope để có được các trận đấu mà không nằm trên đường dẫn trong đó "cscope.out" là:

function s:FindFile(file)
    let curdir = getcwd()
    let found = curdir
    while !filereadable(a:file) && found != "/"
        cd ..
        let found = getcwd()
    endwhile
    execute "cd " . curdir
    return found
endfunction

if has('cscope')    
    let $CSCOPE_DIR=s:FindFile("cscope.out")
    let $CSCOPE_DB=$CSCOPE_DIR."/cscope.out"
    if filereadable($CSCOPE_DB)
        cscope add $CSCOPE_DB $CSCOPE_DIR
    endif

    command -nargs=0 Cscope !cscope -ub -R &
endif

3
Như gotgenes đã nói, Bạn chỉ cần phát minh lại tìm kiếm hướng lên. Xem: h tìm kiếm tập tin. Xem plugin này cho một ví dụ có liên quan.
idbrii
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.