การใส่เครื่องหมายความคิดเห็นของโค้ดหลายบรรทัดโดยระบุโดยหมายเลขบรรทัดโดยใช้ vi หรือ vim


20

ฉันได้เรียนรู้จากคำถาม Stack Overflowที่เป็นไปได้ที่จะใช้vi/ vimเพื่อแสดงความคิดเห็นในช่วงหมายเลขบรรทัดที่ระบุ ตัวอย่างเช่นสมมติว่าฉันมีสคริปต์ทุบตีต่อไปนี้:

#!/bin/bash

This
is
my
very
very
great
script

ตอนนี้สมมติว่าผมต้องการที่จะแสดงความคิดเห็นออกหมายเลขบรรทัดที่ 6 ถึง 8 (ซึ่งมีคำvery, veryและgreat) การใช้#ความคิดเห็นของตัวละคร ในvi/ vimฉันสามารถพิมพ์:6,8s/^/#เพื่อรับสิ่งต่อไปนี้:

#!/bin/bash

This
is
my
#very
#very
#great
script

ซึ่งคอมเม้นท์บรรทัดที่ 6 ถึง 8

คำถามของฉันคือมันเป็นไปได้ที่จะพิมพ์หนึ่งที่คล้ายกันซับที่จะลบ#คิดเห็นอักขระจากสายที่ 6 ถึง 8 ( แต่ไม่ใช่สายการแสดงความคิดเห็นใด ๆ ในไฟล์)?

มีกล่าวนี้ฉันตระหนักดีว่ามีการอภิปรายเกี่ยวกับว่าฉันกำลังใช้จริงบางส่วนหรือvi vimในทางปฏิบัติผมเปิดไฟล์ที่มีคำสั่งscript.sh vi script.shนอกจากนี้เมื่อฉันพิมพ์คำสั่งผมได้รับwhich vi /usr/bin/viอย่างไรก็ตามเมื่อฉันพิมพ์viและกดEnterฉันได้รับสิ่งนี้:

~                              VIM - Vi IMproved
~
~                               version 7.2.330
~                           by Bram Moolenaar et al.
~                 Vim is open source and freely distributable
~
~                           Sponsor Vim development!
~                type  :help sponsor<Enter>    for information
~
~                type  :q<Enter>               to exit
~                type  :help<Enter>  or  <F1>  for on-line help
~                type  :help version7<Enter>   for version info

vimซึ่งดูเหมือนว่าจะชี้ให้เห็นว่าฉันใช้จริง ฉันกำลังเข้าถึงคลัสเตอร์ Ubuntu Linux ระยะไกลโดยใช้ SSH จากพีซีของฉัน ฉันไม่ได้ใช้ Ubuntu Linux GUI

คำตอบ:


22

คุณสามารถใช้ได้:

:6,8s/^#//

แต่ง่ายมากคือการใช้บล็อกโหมดการเลือกภาพ: ไปที่จุดเริ่มต้นของสาย 6 กดCtrl-vลงไปกับสาย 8 xและกด

นอกจากนี้ยังมีปลั๊กอิน"The NERD Commenter"


2
NERD Commenterเป็นวิธีที่จะไปที่นี่ในความคิดของฉัน! +1 สำหรับสิ่งนั้น
user1146332

7

ฉันรู้ว่าคำถามของคุณระบุการใช้viหรือvimแต่นี่คือตัวเลือกอื่น ๆ สำหรับการทำเช่นนี้โดยไม่ต้องเปิดไฟล์ด้วยตนเอง:

  • Perl

    perl -ne 'if($. <=8 && $. >= 6){s/^\s*#//;}print' foo.sh 
    
  • รุ่น Perl> = 5.10

    perl -ne '$. ~~ [6..8] && s/^\s*#//;print' foo.sh 
    

    สิ่งนี้จะพิมพ์เนื้อหาของไฟล์คุณสามารถเปลี่ยนเส้นทางไปยังไฟล์อื่น ( > new_file.sh) หรือใช้iเพื่อแก้ไขไฟล์ในตำแหน่ง:

    perl -i -ne '$. ~~ [6..8] && s/^\s*#//;print' foo.sh 
    
  • sed

    sed '6,8 s/^ *#//' foo.sh
    

    อีกครั้งในการแก้ไขไฟล์เดิมให้ใช้i:

    sed -i '6,8 s/^ *#//' foo.sh
    
  • awk/ gawketc:

    gawk '(NR<=8 && NR>= 6){sub("^ *#","")}{print}' foo.sh
    
  • บริสุทธิ์bash:

    c=1; while read line; do 
      if [ $c -ge 6 ] && [ $c -le 8 ]; then 
         echo "${line/\#/}"
      else 
         echo $line 
      fi
      let c++; done < foo.sh
    

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

2
@PauloAlmeida คุณถูกต้องแน่นอน ฉันแค่คิดว่ามันจะมีประโยชน์เนื่องจาก OP ทราบหมายเลขบรรทัดแล้ว (เนื่องจากคำสั่งแรกที่ใช้ในการคอมเม้นท์) และในกรณีใด ๆ เครื่องมือที่ฉันแสดงสามารถนำไปใช้กับปัญหาที่หลากหลาย
terdon

4

viเป็น symbolic link ไปvimในการกระจาย GNU / Linux มากที่สุดเพื่อให้คุณแน่นอนใช้เมื่อคุณพิมพ์vimvi

ในการลบความคิดเห็นคุณสามารถพิมพ์: :6,8s/^#//หรือ:6,8s/^\s*#//เพื่อละทิ้งพื้นที่นำหน้าบางส่วนก่อน# สัญลักษณ์


1
ขอบคุณมาก. ดูเหมือนว่าอาจมีการพิมพ์ผิด บางทีมันควรจะเป็น:6,8s/^#//และ6,8s/^\s*#//?
แอนดรู

3

vim.tinyคุณอาจใช้ ไม่ว่าในกรณีใดคุณสามารถลบความคิดเห็นเริ่มต้นด้วย:

:6,8s/^#//

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


3

ส่วนตัววิธีที่ฉันชอบคือใช้โหมดบล็อกภาพ

ctrl+ vเพื่อเข้าสู่โหมดบล็อกภาพใช้ปุ่มลูกศรหรือ hjkl เพื่อเลือกเส้นและการกดหรือxdel

ต้องการให้พวกเขากลับมา?

ctrl+ vทำการเลือกจากนั้นI(เมืองหลวง i)#Esc


3

AFAIK, vi มักเป็น symlink ของกลุ่มในปัจจุบัน (ลองwhich viหรือtype viจากนั้นทำตามลิงก์) บางทีแม้/usr/bin/vi-> ->/etc/alternatives/vi/usr/bin/vim.basic

โดยส่วนตัวแล้วในการลบบรรทัดความคิดเห็นหลายบรรทัดฉันชอบการเลือกบล็อกแนวตั้งผ่านCtrlVและลบ หากคุณจำเป็นต้องเพิ่มความคิดเห็นสัญลักษณ์หลายบรรทัดคุณสามารถCtrlVแล้วShiftIพิมพ์#และEscและความคิดเห็นจะถูกเพิ่มไปหลายบรรทัด


2

คำตอบข้างต้นโดยใช้

:6,8s/^#//

เป็นโซลูชั่นที่สมบูรณ์แบบ แต่ยุ่งยากในการพิมพ์ ~/.vimrcนี้ได้ง่ายด้วยการกำหนดคำสั่งใหม่

command -range=% C :<line1>,<line2>s/^/#/
command -range=% D :<line1>,<line2>s/^#//

และคุณสามารถพิมพ์ได้

:6,8C
:6,8D

เพื่อวาง / ลบคำสั่ง

ถ้าคุณชอบโหมดภาพคุณสามารถกำหนดแผนที่

map <F7> :s/^/#/<CR>
map <F8> :s/^#//<CR>

เช่นที่คุณต้องเลือกช่วงของเส้นในโหมดภาพและกดF7และF8เพื่อใส่และลบความคิดเห็นตามลำดับ


1

มีชีวิตนี้เปลี่ยนปลั๊กอินโดยtpopeเรียกว่าvim-commentary

https://github.com/tpope/vim-commentary

ปลั๊กอินนี้ให้ :

  • ความปกติทางจิตใจ
  • เยื้องความคิดเห็นอย่างเหมาะสม
  • ห้ามคอมเม้นต์บรรทัดว่าง / ไม่จำเป็น

การใช้งาน :

  • ติดตั้งผ่าน Vundle (หรือเชื้อโรคฉันเดา)
  • เน้นข้อความของคุณและกด:ซึ่งจะแสดงเป็น:<,'>
  • พิมพ์คำอธิบายที่นี่:<,'>Commentaryแล้วกด Enter
  • Bom ตาของคุณเสร็จแล้ว

1

คำตอบนี้อยู่ที่นี่เพื่อ 1) แสดงรหัสที่ถูกต้องเพื่อวางลงใน a .vimrcเพื่อvim 7.4+ทำการบล็อคความคิดเห็น / ไม่แสดงความคิดเห็นในขณะที่รักษาระดับการเยื้องด้วย 1 ทางลัดในโหมดภาพและ 2) เพื่ออธิบาย

นี่คือรหัส:

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>

มันทำงานอย่างไร:

  • let b:commentChar='//': สิ่งนี้สร้างตัวแปรเป็นกลุ่ม bที่นี่หมายถึงขอบเขตซึ่งในกรณีนี้มีการบัฟเฟอร์หมายถึงไฟล์ที่เปิดอยู่ในปัจจุบัน อักขระความคิดเห็นของคุณเป็นสตริงและจำเป็นต้องใส่ในเครื่องหมายคำพูดเครื่องหมายคำพูดไม่ได้เป็นส่วนหนึ่งของสิ่งที่จะถูกแทนที่เมื่อสลับความคิดเห็น

  • autocmd BufNewFile,BufReadPost *...: ทริกเกอร์คำสั่งอัตโนมัติในสิ่งต่าง ๆ ในกรณีนี้สิ่งเหล่านี้จะทริกเกอร์เมื่อไฟล์ใหม่หรือไฟล์อ่านจบลงด้วยนามสกุลที่แน่นอน เมื่อมีการเรียกใช้คำสั่ง execute ต่อไปนี้ซึ่งทำให้เราสามารถเปลี่ยนcommentCharชนิดไฟล์ที่ขึ้นอยู่กับ มีวิธีอื่นในการทำเช่นนี้ แต่พวกเขาสับสนกับมือใหม่ (เช่นฉัน) มากกว่า

  • function! Docomment(): ฟังก์ชั่นมีการประกาศโดยเริ่มต้นด้วยและลงท้ายด้วยfunction endfunctionฟังก์ชั่นจะต้องเริ่มต้นด้วยทุน !เพื่อให้แน่ใจว่าฟังก์ชั่นนี้จะเขียนทับฟังก์ชั่นใด ๆ ก่อนกำหนดเป็นกับรุ่นนี้Docomment() Docomment()ถ้าไม่มี!ฉันก็มีข้อผิดพลาด แต่นั่นอาจเป็นเพราะฉันกำหนดฟังก์ชั่นใหม่ผ่านทางบรรทัดคำสั่ง vim

  • execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e': เรียกใช้คำสั่ง ในกรณีนี้เรากำลังดำเนินการsubstituteซึ่งสามารถใช้ช่วง (โดยค่าเริ่มต้นนี่คือบรรทัดปัจจุบัน) เช่น%สำหรับบัฟเฟอร์ทั้งหมดหรือ'<,'>สำหรับส่วนที่ไฮไลต์ ^\s*คือ regex เพื่อให้ตรงกับจุดเริ่มต้นของบรรทัดแล้วตามด้วยช่องว่างจำนวนใด ๆ ซึ่งต่อท้ายไปแล้ว (เนื่องจาก&) .ที่นี่จะใช้สำหรับสตริงเนื่องจากescape()ไม่สามารถห่อในเครื่องหมายคำพูด escape()ช่วยให้คุณสามารถที่จะหลบหนีตัวละครในcommentCharที่ตรงกับข้อโต้แย้ง (ในกรณีนี้\และ/) โดย prepending \พวกเขาด้วย หลังจากนี้เราต่อกันอีกครั้งกับจุดจบของเราsubstituteซึ่งมีeธง. การตั้งค่าสถานะนี้ช่วยให้เราล้มเหลวอย่างเงียบ ๆ ซึ่งหมายความว่าหากเราไม่พบการแข่งขันในบรรทัดที่กำหนดเราจะไม่ตะโกนเกี่ยวกับมัน โดยรวมแล้วบรรทัดนี้ช่วยให้เราใส่อักขระความคิดเห็นตามด้วยช่องว่างหน้าข้อความแรกซึ่งหมายความว่าเรารักษาระดับการเยื้องไว้

  • execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e': นี่คล้ายกับคำสั่งอันยาวนานของเรา ที่ไม่ซ้ำกับคนนี้เรามี\vซึ่งจะทำให้แน่ใจว่าเราไม่ได้มีการหลบหนีของเรา()และซึ่งหมายถึงกลุ่มที่เราทำกับเรา1 ()โดยพื้นฐานแล้วเรากำลังจับคู่บรรทัดที่ขึ้นต้นด้วยช่องว่างจำนวนหนึ่งแล้วตามด้วยอักขระความคิดเห็นของเราตามด้วยช่องว่างใด ๆ และเราจะรักษาช่องว่างชุดแรกเท่านั้น อีกครั้งeให้เราล้มเหลวอย่างเงียบ ๆ หากเราไม่มีตัวอักษรแสดงความคิดเห็นในบรรทัดนั้น

  • let l:line=getpos("'<")[1]: ชุดนี้ตัวแปรเหมือนที่เราทำกับตัวละครความคิดเห็นของเรา แต่lหมายถึงขอบเขตท้องถิ่น (ท้องถิ่นฟังก์ชั่นนี้) getpos()รับตำแหน่งในกรณีนี้จุดเริ่มต้นของการเน้นของเราและ[1]วิธีการที่เราสนใจเฉพาะหมายเลขบรรทัดไม่ใช่สิ่งอื่น ๆ เช่นหมายเลขคอลัมน์

  • if match(getline(l:line), '^\s*'.b:commentChar)>-1: คุณรู้วิธีการifทำงาน match()ตรวจสอบว่าสิ่งแรกมีสิ่งที่สองดังนั้นเราจึงคว้าสายที่เราเริ่มเน้นของเราและตรวจสอบว่ามันเริ่มต้นด้วยช่องว่างตามด้วยตัวละครความคิดเห็นของเรา match()ส่งคืนดัชนีซึ่งเป็นจริงและ-1หากไม่พบการแข่งขัน เนื่องจากifประเมินตัวเลขที่ไม่ใช่ศูนย์ทั้งหมดให้เป็นจริงเราจึงต้องเปรียบเทียบผลลัพธ์ของเราเพื่อดูว่ามันมากกว่า -1 หรือไม่ การเปรียบเทียบvimส่งคืน 0 ถ้าเป็นเท็จและ 1 ถ้าเป็นจริงซึ่งเป็นสิ่งที่ifต้องการดูเพื่อประเมินอย่างถูกต้อง

  • vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>: vnoremapหมายถึงแมปคำสั่งต่อไปนี้ในโหมดภาพ แต่ไม่ต้องแมปคำสั่งซ้ำ (หมายถึงอย่าเปลี่ยนคำสั่งอื่น ๆ ที่อาจใช้ในวิธีอื่น) โดยทั่วไปถ้าคุณเป็นกลุ่มมือใหม่ควรใช้noremapเพื่อให้แน่ใจว่าคุณจะไม่ทำสิ่งต่าง ๆ <silent>หมายถึง "ฉันไม่ต้องการคำพูดของคุณเพียงแค่การกระทำของคุณ" และบอกว่าจะไม่พิมพ์อะไรไปยังบรรทัดคำสั่ง <C-r>เป็นสิ่งที่เรากำลังทำแผนที่ซึ่งเป็น ctrl + r ในกรณีนี้ (โปรดทราบว่าคุณยังคงสามารถใช้ Cr ตามปกติสำหรับ "ทำซ้ำ" ในโหมดปกติด้วยการทำแผนที่นี้) C-uค่อนข้างจะสับสน แต่โดยพื้นฐานแล้วมันทำให้แน่ใจว่าคุณไม่หลงลืมการเน้นภาพของคุณ (ตามคำตอบนี้มันทำให้คำสั่งของคุณเริ่มต้นด้วย'<,'>สิ่งที่เราต้องการ)callที่นี่เพียงแค่บอกเป็นกลุ่มเพื่อดำเนินการฟังก์ชั่นที่เราตั้งชื่อและ<cr>หมายถึงการกดenterปุ่ม เราต้องกดปุ่มหนึ่งครั้งเพื่อเรียกใช้ฟังก์ชั่นจริง ๆ (ไม่อย่างนั้นเราแค่พิมพ์call function()บนบรรทัดคำสั่งและเราต้องกดมันอีกครั้งเพื่อให้ตัวแทนของเราผ่านไปได้ตลอดทาง (ไม่แน่ใจจริงๆว่าทำไม

อย่างไรก็ตามหวังว่านี่จะช่วยได้ นี้จะเอาอะไรกับไฮไลต์v, VหรือC-vตรวจสอบว่าสายแรกคือการให้ความเห็นว่าถ้าใช่ลอง uncomment เส้นไฮไลต์ทั้งหมดและหากไม่ได้เพิ่มชั้นพิเศษของตัวละครความคิดเห็นที่แต่ละบรรทัด นี่คือพฤติกรรมที่ฉันต้องการ ฉันไม่ได้แค่อยากจะสลับว่าแต่ละบรรทัดในบล็อกถูกคอมเม้นต์หรือไม่ดังนั้นมันจึงทำงานได้อย่างสมบูรณ์แบบสำหรับฉันหลังจากถาม คำถามหลาย ๆเรื่อง

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