Làm thế nào để nhận xét một tập hợp các dòng được chọn trong chế độ trực quan?


35

Làm thế nào để tôi nhận xét nhiều trong chế độ trực quan được chọn dòng? Làm thế nào để tôi làm cho nó ngôn ngữ cụ thể?

Ví dụ: nếu 4 dòng đầu tiên được chọn:

def foo(a,b):
    for each in (a,b):
        print each
    return a+b
print "2"

Hoạt động của một lệnh / macro sẽ dẫn đến điều này (bằng python):

#def foo(a,b):
#    for each in (a,b):
#        print each
#    return a+b
print "2"

Câu trả lời:


31

Nếu bạn muốn bình luận ngôn ngữ cụ thể, bạn sẽ cần một plugin như nerdcommenter .

Ngoài ra, mặc dù nó không trả lời câu hỏi thực tế của bạn, bạn có thể sử dụng các hành động vim dựng sẵn và kiến ​​thức của bạn về từng ký tự nhận xét của ngôn ngữ ...

Tùy chọn # 1: Khối V

  1. :1 Enter (Chuyển đến dòng 1)
  2. Ctrl-V (Chế độ khối V)
  3. jjj (Xuống 3 dòng nữa)
  4. Shift-Tôi (Nhập chế độ chèn trước khối)
  5. # (Chèn một '#')
  6. Esc (Quay lại chế độ bình thường)

Lựa chọn số 2: Thay thế

:1,4s/^/#/

Phá vỡ:

  1. : Lệnh Ex theo sau
  2. 1,4 trên các dòng từ 1 đến 4
  3. s thay thế
  4. /dấu phân cách cho các phần của lệnh thay thế.
    (Bạn cũng có thể sử dụng một ký tự khác, ví dụ :)
  5. ^ đầu dòng
  6. / dải phân cách
  7. # nhân vật bình luận cho python
  8. / dải phân cách cuối cùng

Tùy chọn # 3: Lặp lại ứng dụng của macro ( nguồn )

  1. :1 Enter (Chuyển đến dòng 1)
  2. qa(Bắt đầu ghi vào sổ đăng ký a)
  3. Shift-I (Nhập chế độ chèn ở đầu dòng
  4. # (Thêm một '#' ở đầu dòng)
  5. Esc (Quay lại chế độ bình thường)
  6. q (Dừng ghi âm)

  7. :2,4 normal @a(chạy lại macro được ghi lại để đăng ký atrên các dòng từ 2 đến 4)

    HOẶC LÀ

    bạn có thể chọn các dòng trong chế độ trực quan và nhấn :để tự động điền dòng Ex với :'<,'>(một phạm vi từ đầu đến cuối lựa chọn trực quan) sau đó nhập normal @avà nhấn Enter( nguồn ).

Bây giờ, bất cứ khi nào bạn muốn nhận xét một số dòng, chỉ cần chạy lại macro đã ghi để đăng ký atrên các dòng đó:

:9,22 normal @a (comment out lines 9-22)

1
Tùy chọn 4: Plugin
Thăm dò ý kiến ​​Cody

Tôi không hiểu tại sao bạn sử dụng macro cho một lệnh, khi bạn có thể làm :9,22 normal I#theo câu trả lời của tôi.
Ben

Tại sao bạn nên sử dụng: 1 <enter> khi bạn có thể sử dụng gg?
Tanath

@Tanath Nhận xét từ dòng đầu tiên là cụ thể cho ví dụ này. Nếu tác giả muốn bình luận từ dòng 9 đến 22, họ sẽ không thể sử dụng gg.
bsmith89

@Ben Tôi không biết gì về normallệnh trước khi viết câu trả lời này. Bạn đúng; :9,22 normal I#cũng sẽ làm việc
bsmith89

26

Sử dụng chế độ Visual Block ( CtrlV), chọn đầu dòng. Sau đó nhấn I#(đó là chữ in hoa I) để chèn ký tự băm trên mỗi dòng đó. Sau đó nhấn Escđể trở về từ Chế độ chèn sang Chế độ bình thường.


Nó không làm việc cho tôi. Nó chèn một bình luận chỉ trong dòng đầu tiên.
gon132

Bạn đang đẩy ctrl? Bởi vì ctrl+vlà một điều khác với chỉ v.
Thăm dò ý kiến ​​Cody

@CodyPoll Tôi biết. Tất cả mọi thứ là ok lên đến I. Khi tôi nhấn I, sau đó #sẽ chỉ được đặt ở phía trước của dòng đầu tiên.
gon132

@CodyPoll Ok .. Tôi chỉ là bệnh nhân nội trú. Tôi đã không nhấn Escsau khi các thủ tục được mô tả.
gon132

@ gon1332 theo như tôi biết bạn cần nhấn Escvào cuối.
Gonçalo Ribeiro

18

Nếu bạn chỉ cần một giải pháp nhanh chóng cho bất kỳ ngôn ngữ nào bạn đang sử dụng và bạn đã có văn bản được chọn ở chế độ trực quan, thì

:norm 0i#

Làm công việc. (Đối với mỗi dòng, ở chế độ bình thường, hãy chuyển đến cột đầu tiên và chèn #. Sử dụng :norm I#sẽ chèn nó trước ký tự không phải khoảng trắng đầu tiên, có thể không phải là điều bạn muốn.) Sử dụng :norm i#cũng sẽ hoạt động, vì :normbắt đầu từ đầu nhưng nó ít rõ ràng hơn và ít rõ ràng hơn nếu bạn không biết điều đó.

Tất nhiên, nếu bạn có ý định làm điều này thường xuyên, bạn sẽ muốn thiết lập ánh xạ hoặc tìm kiếm một plugin.


1
Không cần 0 vì theo mặc định, normallệnh được thực thi bằng con trỏ ở đầu dòng.
nitishch

1
Tất nhiên, số dòng,%, nhãn hiệu có thể được bắt đầu bằng lệnh này. Ví dụ :: 1,5norm i # (hoặc): 'a,' bnorm i # (hoặc): 10% định mức i #
SibiCoder

9

Làm điều đó tự động sẽ yêu cầu bạn thêm một cái gì đó như sau vào vimrctệp của bạn ( nguồn ):

au FileType haskell,vhdl,ada let b:comment_leader = '-- '
au FileType vim let b:comment_leader = '" '
au FileType c,cpp,java let b:comment_leader = '// '
au FileType sh,make let b:comment_leader = '# '
au FileType tex let b:comment_leader = '% '
noremap <silent> ,c :<C-B>sil <C-E>s/^/<C-R>=escape(b:comment_leader,'\/')<CR>/<CR>:noh<CR>
noremap <silent> ,u :<C-B>sil <C-E>s/^\V<C-R>=escape(b:comment_leader,'\/')<CR>//e<CR>:noh<CR>

Sử dụng ,cđể bình luận một khu vực và ,ubỏ ghi chú một khu vực. Điều này tự đặt các ký hiệu nhận xét cho các ngôn ngữ khác nhau.

Tùy chọn thứ hai là sử dụng một plugin như tcomment , vim-bình luận hoặc bình luận.vim . Tôi sử dụng tcomment mình. Xin vui lòng, đọc hướng dẫn về cách sử dụng và cài đặt tại trang của họ, vì tôi tin rằng điều đó nằm ngoài chủ đề của câu hỏi.

Tôi khuyên bạn nên sử dụng một plugin (một trong những liên kết ở trên hoặc khác) vì điều đó dễ dàng hơn nhiều so với việc duy trì một đoạn mã trong vimrctệp của bạn .

Chỉnh sửa: Tôi đã xóa cách thủ công khi câu hỏi đã được thay đổi và cũng là cách chính xác được trả lời bởi 200_success.


Một đề xuất bổ sung: Bình luận viên NERD - vim.org/scripts/script.php?script_id=1218
đưa ra

Lưu ý: điều này chỉ hỗ trợ bình luận theo dòng. Ví dụ, ANSI C không nhận ra //(chỉ /* */).
wchargein

Trong khi tôi thích cách tiếp cận này, có cách nào để làm cho nó thay đổi ý kiến ​​không?
ideaman42

1
@ ideaman42 Thay vào đó, bạn phải tạo một hàm và kiểm tra xem dòng hiện tại có bắt đầu bằng một nhận xét hay không và tùy thuộc vào lệnh đó, một trong hai :slệnh được hiển thị trong đoạn trích trong câu trả lời. Việc kiểm tra chính nó sẽ là một cái gì đó như getline('.') =~ "^" . escape(b:comment_leader, '\/'). Nếu đó là sự thiếu sót thực sự, nếu không bình luận. Điều này không được thử nghiệm và chỉ nên phục vụ như một ví dụ.
tokoyami

5

Tôi sử dụng scrooloose / nerdcommenter cho việc này.

Với plugin này, bạn có thể trực quan chọn các dòng của mình và nhấn leader+ cđể chuyển nhận xét. Tùy thuộc vào loại tệp, nó sẽ sử dụng các ký hiệu khác nhau để bình luận.


5

Sau khi bạn đã chọn các dòng, chỉ cần gõ

:norm I#

:sẽ tự động đưa '<,'>vào dòng lệnh của bạn, đó là một phạm vi từ đầu lựa chọn của bạn đến cuối; normthực thi một lệnh chế độ bình thường và sẽ hành động trên phạm vi đó; I#là lệnh chế độ bình thường sẽ chèn '#' ở đầu dòng.


4

Tôi là một fan hâm mộ lớn của TComment cho việc này; Tôi không chỉ có thể thực hiện các kiểu nhận xét cụ thể về kiểu tệp, mà thậm chí chỉ định khối so với mỗi dòng cho các ngôn ngữ hỗ trợ nhận xét khối.

    gc{motion}   :: Toggle comments (for small comments within one line 
                    the &filetype_inline style will be used, if 
                    defined)
    gcc          :: Toggle comment for the current line

Explicit commenting/uncommenting:

    g<{motion}   :: Uncomment region
    g<c          :: Uncomment the current line
    g<b          :: Uncomment the current region as block

    g>{motion}   :: Comment region
    g>c          :: Comment the current line
    g>b          :: Comment the current region as block

In visual mode:

    gc           :: Toggle comments
    gC           :: Comment selected text

Cảm ơn câu trả lời của bạn! Có lẽ bạn có thể mở rộng nó? Cung cấp các câu trả lời cho plugin là tốt, nhưng hiện tại nó chỉ là một liên kết đến một plugin. Ít nhất, một mô tả cơ bản về những gì nó làm và cách sử dụng nó được mong đợi trong câu trả lời. cũng thấy bài meta này .
Martin Tournoij

Có vẻ ngớ ngẩn để sao chép / dán keybinds nhưng bạn đi đó; Tôi đã mô tả những gì nó làm.
Collin Grady

3

Tôi thấy các plugin bình luận vim là cách dễ nhất để làm điều này. Chọn một loạt các dòng, sau đó chỉ cần nhấn gc. Nó sẽ sử dụng một ký tự nhận xét thích hợp cho kiểu tệp bạn đã mở. Thậm chí có thể không có bất kỳ lựa chọn trực quan nào để bỏ qua các dòng nhận xét liền kề với gcuhoặc gcgc.


2

Giả sử bạn muốn thêm tiền tố vào 5 dòng ở đầu dòng, thì bạn có thể sử dụng Tìm kiếm và thay thế :

:.,+5s/^/prefix_/g

hoặc ở cuối dòng:

:.,+5s/$/suffix_/g

Hoặc sử dụng chế độ trực quan ( Ctrl+ v) để chọn khối văn bản dọc, sau đó nhập chế độ chèn ( I) và nhập nội dung nào đó và nhấn Escđể xác nhận và áp dụng các thay đổi cho các dòng khác.

Liên quan:


2

Câu trả lời này là ở đây để 1) hiển thị mã chính xác để dán vào một .vimrcđể có được vim 7.4+để làm khối cho ý kiến / uncommenting trong khi vẫn giữ mức thụt đầu dòng với 1 phím tắt trong chế độ trực quan và 2) để giải thích nó.

Đây là mã:

let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.[ch]    let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.cpp    let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.py    let b:commentChar='#'
autocmd BufNewFile,BufReadPost *.*sh    let b:commentChar='#'
function! Docomment ()
  "make comments on all the lines we've grabbed
  execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e'
endfunction
function! Uncomment ()
  "uncomment on all our lines
  execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e'
endfunction
function! Comment ()
  "does the first line begin with a comment?
  let l:line=getpos("'<")[1]
  "if there's a match
  if match(getline(l:line), '^\s*'.b:commentChar)>-1
    call Uncomment()
  else
    call Docomment()
  endif
endfunction
vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>

Làm thế nào nó hoạt động:

  • let b:commentChar='//': Điều này tạo ra một biến trong vim. các bđây đề cập đến phạm vi, mà trong trường hợp này được chứa vào bộ đệm, có nghĩa là tập tin hiện đang mở. Các ký tự nhận xét của bạn là các chuỗi và cần được gói trong dấu ngoặc kép, các trích dẫn không phải là một phần của những gì sẽ được thay thế khi bật các bình luận.

  • autocmd BufNewFile,BufReadPost *...: Autocommands kích hoạt những thứ khác nhau, trong trường hợp này, đây là những kích hoạt khi một tệp mới hoặc tệp đọc kết thúc với một phần mở rộng nhất định. Sau khi được kích hoạt, thực thi lệnh sau, cho phép chúng ta thay đổi commentChartùy thuộc vào filetype. Có nhiều cách khác để làm điều này, nhưng chúng khó hiểu hơn đối với người mới (như tôi).

  • function! Docomment(): Hàm được khai báo bằng cách bắt đầu bằng functionvà kết thúc bằng endfunction. Chức năng phải bắt đầu bằng một vốn. các !Đảm bảo rằng chức năng này ghi đè bất kỳ chức năng trước đó định nghĩa là Docomment()với phiên bản này của Docomment(). Không có !, tôi có lỗi, nhưng đó có thể là do tôi đang xác định các hàm mới thông qua dòng lệnh vim.

  • execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e': Thực thi cuộc gọi một lệnh. Trong trường hợp này, chúng tôi đang thực thi substitute, có thể lấy một phạm vi (theo mặc định đây là dòng hiện tại) như %cho toàn bộ bộ đệm hoặc '<,'>cho phần được tô sáng. ^\s*là regex để khớp với bắt đầu của một dòng theo sau bởi bất kỳ khoảng trắng nào, sau đó được thêm vào (do &). Ở .đây được sử dụng để nối chuỗi, vì escape()không thể được gói trong dấu ngoặc kép. escape()cho phép bạn thoát ký tự commentCharphù hợp với các đối số (trong trường hợp này \/) bằng cách thêm chúng vào a \. Sau đó, chúng tôi nối lại một lần nữa với phần cuối của substitutechuỗi, trong đó cóecờ. Cờ này cho phép chúng tôi thất bại trong âm thầm, có nghĩa là nếu chúng tôi không tìm thấy kết quả khớp trên một dòng nhất định, chúng tôi sẽ không hét lên về nó. Nhìn chung, dòng này cho phép chúng ta đặt một ký tự nhận xét theo sau là khoảng trắng ngay trước văn bản đầu tiên, nghĩa là chúng ta giữ mức thụt lề.

  • execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e': Điều này tương tự như lệnh dài lớn cuối cùng của chúng tôi. Duy nhất với cái này, chúng tôi có \v, đảm bảo rằng chúng tôi không phải trốn thoát (), và 1, đề cập đến nhóm chúng tôi đã thực hiện với chúng tôi (). Về cơ bản, chúng tôi khớp với một dòng bắt đầu với bất kỳ khoảng trắng nào và sau đó là ký tự nhận xét của chúng tôi theo sau bởi bất kỳ khoảng trắng nào và chúng tôi chỉ giữ bộ khoảng trắng đầu tiên. Một lần nữa, echúng ta hãy âm thầm thất bại nếu chúng ta không có một nhân vật bình luận trên dòng đó.

  • let l:line=getpos("'<")[1]: điều này đặt một biến giống như chúng ta đã làm với ký tự nhận xét của mình, nhưng lđề cập đến phạm vi cục bộ (cục bộ cho hàm này). getpos()trong trường hợp này, bắt đầu đánh dấu của chúng tôi và [1]có nghĩa là chúng tôi chỉ quan tâm đến số dòng, không phải những thứ khác như số cột.

  • if match(getline(l:line), '^\s*'.b:commentChar)>-1: bạn biết cách làm ifviệc match()kiểm tra xem thứ đầu tiên có chứa thứ thứ hai không, vì vậy chúng tôi lấy dòng mà chúng tôi đã bắt đầu tô sáng và kiểm tra xem nó có bắt đầu bằng khoảng trắng theo sau là ký tự nhận xét của chúng tôi không. match()trả về chỉ mục nơi điều này là đúng và -1nếu không tìm thấy kết quả khớp nào. Vì ifđánh giá tất cả các số khác không là đúng, chúng tôi phải so sánh đầu ra của chúng tôi để xem nó có lớn hơn -1 không. So sánh vimtrả về 0 nếu sai và 1 nếu đúng, đó là điều ifmuốn xem để đánh giá chính xác.

  • vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>: vnoremapcó nghĩa là ánh xạ lệnh sau trong chế độ trực quan, nhưng không ánh xạ đệ quy (có nghĩa là không thay đổi bất kỳ lệnh nào khác có thể sử dụng theo các cách khác). Về cơ bản, nếu bạn là người mới làm quen với vim, hãy luôn sử dụng noremapđể đảm bảo bạn không phá vỡ mọi thứ. <silent>có nghĩa là "Tôi không muốn lời nói của bạn, chỉ là hành động của bạn" và bảo nó không được in bất cứ điều gì lên dòng lệnh. <C-r>là thứ chúng tôi lập bản đồ, đó là ctrl + r trong trường hợp này (lưu ý rằng bạn vẫn có thể sử dụng Cr bình thường để "làm lại" trong chế độ bình thường với ánh xạ này). C-uhơi khó hiểu, nhưng về cơ bản, nó đảm bảo bạn không bị mất dấu của việc làm nổi bật hình ảnh của bạn (theo câu trả lời này, nó làm cho lệnh của bạn bắt đầu với '<,'>đó là những gì chúng ta muốn).callỞ đây chỉ nói với vim để thực thi chức năng mà chúng ta đã đặt tên và <cr>đề cập đến việc nhấn enternút. Chúng ta phải nhấn nó một lần để thực sự gọi hàm (nếu không chúng ta vừa gõ call function()vào dòng lệnh, và chúng ta phải nhấn nó một lần nữa để thay thế chúng ta đi suốt (không thực sự chắc chắn tại sao, nhưng bất cứ điều gì).

Dù sao, hy vọng điều này sẽ giúp. Điều này sẽ lấy bất cứ điều gì được tô sáng bằng v, Vhoặc C-v, kiểm tra xem dòng đầu tiên có được nhận xét hay không, nếu có, cố gắng bỏ ghi chú tất cả các dòng được tô sáng và nếu không, hãy thêm một lớp ký tự nhận xét cho mỗi dòng. Đây là hành vi mong muốn của tôi; Tôi không chỉ muốn nó chuyển đổi xem mỗi dòng trong khối có được nhận xét hay không, vì vậy nó hoạt động hoàn hảo với tôi sau khi hỏi nhiều câu hỏi về chủ đề này.

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.