ฉันจะย้ายในแนวตั้งจนกว่าจะถึงตัวละครที่ไม่ใช่ช่องว่างได้อย่างไร


27

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

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

นี่คือตัวอย่างโดยที่เคอร์เซอร์ทำเครื่องหมายขีดล่าง_(ที่คอลัมน์อักขระที่สองระหว่างคำจำกัดความของclass Bazzและclass Qux) แต่ลองจินตนาการว่าจำนวนย่อหน้าหรือบรรทัดภายในmodules ไม่เป็นที่รู้จักหรือตัวแปร:

module Foo
  # lots of code...
end

module Bar
  class Baz
    # ...
  end

  class Bazz
    # lots of code...
  end
 _
  class Qux
    # ...
  end

  class Quux
    # lots of code...
  end
end

... วิธีสามารถฉันได้อย่างรวดเร็วไปที่oการmodule Barดังกล่าวข้างต้นเคอร์เซอร์หรือnของendด้านล่างเคอร์เซอร์ที่บรรทัดสุดท้ายมาก? โปรดทราบว่าคอลัมน์แนวตั้งมีช่องว่าง แต่ยังไม่มีอักขระที่คอลัมน์ที่สองระหว่างclassคำจำกัดความ


2
ที่เกี่ยวข้อง: "เลื่อนไปยังบรรทัดถัดไป / ก่อนหน้าโดยมีการเยื้องเดียวกัน" บนเคล็ดลับ Vim Wiki vim.wikia.com/wiki/Move_to_next/ ......
alxndr

กด g และปุ่มทิศทางอาจหลีกเลี่ยงแท็บและย้ายข้ามเส้น
SibiCoder

1
โซลูชันในลิงก์ของ @ alxndr ทำงานได้ดียกเว้นในกรณีที่ช่องว่างนั้นได้รับการดูแลไม่ดี (เช่นมีเส้นสุ่มที่มีช่องว่างเท่านั้น) และคุณต้องการละเว้นช่องว่าง วิธีแก้ปัญหาของ superjer ด้านล่างจะดีกว่าถ้ามีใครกังวลเกี่ยวกับกรณีนี้
nukeguy

คำตอบ:


9

ฟังก์ชั่นนี้เกี่ยวกับอะไร?

function FloatUp()
    while line(".") > 1
                \ && (strlen(getline(".")) < col(".")
                \ || getline(".")[col(".") - 1] =~ '\s')
        norm k
    endwhile
endfunction

คุณสามารถnnoremap gU :call FloatUp()<CR>( gUสำหรับ "ไปถึง") gUและจากนั้นเรียกด้วย

นี่คือคำอธิบาย:

  • รหัสเลื่อนเคอร์เซอร์ขึ้น (พร้อมnorm k) ซ้ำ ๆตราบใดที่whileเงื่อนไขยังคงอยู่
  • whileสภาพถือถ้าไม่บรรทัดแรก ( line(".") > 1) และทั้ง
    • บรรทัดนี้สั้นเกินไป (อาจว่างเปล่า); หรือ
    • getline(".")อักขระบรรทัดปัจจุบัน ( ) ของที่คอลัมน์ปัจจุบัน ( [col(".") - 1]) คือช่องว่าง ( =~ '\s'; เช่นตรงกับรูปแบบช่องว่าง)

1
ดูเหมือนว่าจะทำงานได้อย่างสมบูรณ์แบบ (และรวดเร็ว) และปรับเปลี่ยนได้ง่ายในFloatDownฟังก์ชั่นเช่นกัน เป็น. vimrc ของฉันไปแล้วขอบคุณ! github.com/alxndr/dotfiles/commit/0e25a302
alxndr

1
เพิ่งค้นพบว่าโซลูชันนี้ใช้งานไม่ได้ในโหมดภาพ (พฤติกรรมที่แตกต่างกันเล็กน้อยขึ้นอยู่กับโหมดภาพว่ามันจะอยู่ในตำแหน่งเดียวกันหรือเคลื่อนที่เพียงหนึ่งบรรทัด) ตัวชี้ใด ๆ ที่เกิดขึ้นที่นั่น?
alxndr

13

ฉันชอบใช้การค้นหาสิ่งเหล่านี้เนื่องจาก regex ของ Vim มีจำนวนสิ่งที่บ้าคุณสามารถค้นหาเช่นหมายเลขคอลัมน์เสมือนเฉพาะในกรณีนี้:

nnoremap cd /\%<C-R>=virtcol(".")<CR>v\S<CR>

nnoremap cu ?\%<C-R>=virtcol(".")<CR>v\S<CR>

ใช้cdเพื่อลงและcuขึ้นไป ฉันกำลังคิด "คอลัมน์ขึ้น" และ "ลงคอลัมน์" ที่นี่ ฉันเกือบ 100% มั่นใจว่าสิ่งเหล่านี้ไม่มีค่าเริ่มต้น หรือเลือกการจับคู่ของคุณเอง

สิ่งนี้จะทำงานได้ไม่ว่าคุณจะใช้แท็บหรือช่องว่างหรือทั้งสองอย่าง


1
ฉันมีปัญหาในการแยกวิเคราะห์คำสั่งเหล่านั้น คุณจะขยายความสนใจพวกเขาสักเล็กน้อยหรือไม่?
davidlowryduda

1
/ หรือ ? เพื่อค้นหาลงหรือเพิ่มขึ้น \% xv จำกัด การค้นหาหมายเลขคอลัมน์เสมือน 'x', 'x' ในกรณีนี้คือ '<CR> = virtcol (".") <CR>' ซึ่งรันคำสั่งและแทรก virtcol หมายเลขคอลัมน์เสมือนที่เคอร์เซอร์อยู่ที่นิพจน์ \ S หมายถึงอักขระที่ไม่ใช่ช่องว่าง
ชาด

1
ขอบคุณสำหรับการอธิบายชาด ฉันจะเพิ่ม <CR> นั้นในโหมดแทรกหรือโหมดบรรทัดคำสั่งคว้าเนื้อหาของการลงทะเบียน การ=ลงทะเบียนคือการลงทะเบียนการแสดงออกซึ่งประเมินการแสดงออกในสถานที่ มันมีประโยชน์มากถ้าไม่ดูแปลก ๆ
superjer

1
ข้อเสียอย่างหนึ่งของวิธีการนี้คือหากคุณมีการเน้นการค้นหาคุณจะพบว่าอักขระทั้งหมดในคอลัมน์แนวตั้งของเคอร์เซอร์ถูกไฮไลต์หลังจาก "คอลัมน์ขึ้น" หรือ "ลงคอลัมน์"
alxndr

3
หากคุณต้องการที่จะปกป้องค้นหาที่มีอยู่ของคุณคุณสามารถย่อหน้าและผนวก:let searchbak=@/<CR> :let @/=searchbak<CR>แต่ ณ จุดนี้มันยาวและไม่สามารถเข้าถึงได้และอาจเป็นแค่ฟังก์ชั่น
superjer

7

คุณอาจใช้ปลั๊กอินJumpToVerticalOccurrence (แมปที่เป็นค่าเริ่มต้น]|และ[|) มีบางคนที่ชอบ]V{char}ทำงานfแต่แนวตั้ง แน่นอนคุณสามารถทำการแมปใหม่ได้ตามต้องการ


หากคุณไม่ต้องการใช้ปลั๊กอินคุณอาจลองใช้:searchด้วยvirtcol(.)เช่น:

:call search('\%' . virtcol('.') . 'v\S', 'bW')

ที่อยู่:

  • virtcol('.') ให้คอลัมน์ปัจจุบันแก่คุณ
  • \S ย่อมาจากช่องว่างที่ไม่ใช่
  • bW ใช้สำหรับค้นหาย้อนหลัง

ตรวจสอบ:help searchเพื่อเรียนรู้เพิ่มเติม

เพื่อให้ง่ายต่อการใช้งานคุณสามารถแมปได้เช่น:

:map <C-k> :call search('\%' . virtcol('.') . 'v\S', 'bW')<CR>
:map <C-j> :call search('\%' . virtcol('.') . 'v\S', 'W')<CR>

หรือถ้ารหัสของคุณมีวงเล็บใช้%เพื่อข้ามไปมาระหว่างจับคู่พวกเขา (เช่น{, }, [, ]ฯลฯ ) หรือใช้ทั้งย่อหน้ากระโดด ( {, }ด้วยShiftถ้าจำเป็น)


การเชื่อมโยง / แหล่งที่มา:


จาก:h search(): wวิธีการwrap around the end of the fileและวิธีการW don't wrap around the end of the fileแต่ทำไมคุณถึงรวมพวกมันเข้าด้วยกันในวินาที:map?
Jair López

@JairLopez ถูกต้องwไม่ควรอยู่ที่นั่นดังนั้นฉันได้ลบออกแล้วขอบคุณ อาจเป็นเพราะฉันสับสนกับความหมายของปุ่มกด
kenorb

3

ฉันใช้เวอร์ชันที่แก้ไขแล้วของปลั๊กอินvim-indent-objectเพื่อจัดเตรียมลักษณะการทำงานนี้ การปรับเปลี่ยนของฉันสามารถมองเห็นได้ที่นี่

สิ่งนี้ทำให้ฉันแผนที่[iเพื่อไปที่จุดเริ่มต้นของระดับเยื้องปัจจุบันและ]iไปยังจุดสิ้นสุด


2

มันไม่ได้เป็นสิ่งที่คุณถามหาเพราะมันไม่เคลื่อนที่ในแนวดิ่ง แต่บางสิ่งบางอย่างที่คล้ายกันอย่างรวดเร็วและอาจจะดีพอสำหรับคุณที่มีการเคลื่อนไหวย้อนหลัง 2 {{ย่อหน้า: module Barนี้จะพาคุณไปยังเส้นขวาก่อน


2
ลองนึกภาพว่ามีจำนวนบรรทัดและ / หรือย่อหน้าที่ไม่รู้จักระหว่างเคอร์เซอร์และmoduleบรรทัดระดับบนสุด (โดยเฉพาะสถานการณ์นี้เกิดขึ้นเมื่อเร็ว ๆ นี้เมื่อฉันเพิ่งนำทางโค้ดของบุคคลที่สามหลายพันบรรทัดยาวโดยมีการเยื้องที่ถูกต้อง แต่ไม่มีบรรทัดว่างและพยายามค้นหาบริบทด้านนอกของคำจำกัดความของโมดูล)
alxndr

การกระโดดตามย่อหน้าเป็นวิธีที่ฉันชอบในการเคลื่อนไปรอบ ๆ แต่มันก็ไม่ใช่ตัวเลือก: ไฟล์ทั้งหมดเป็นหนึ่ง "ย่อหน้า"
alxndr


1

ฉันใช้ปลั๊กอินของตัวเองmove_until_char_changes.vimสำหรับสิ่งนั้น

ฉันแผนที่ไปและgKgJ

มันจะกระโดดข้ามหลายบรรทัดที่มีตัวอักษรเดียวกันในคอลัมน์ปัจจุบัน (ไม่ใช่แค่ช่องว่าง) ซึ่งอาจเป็นประโยชน์ใน logfiles หรือ SQL dumps ด้วยสตริงซ้ำ

โดยค่าเริ่มต้นมันจะย้ายหนึ่งบรรทัดก่อนที่จะรับตัวอักษร "ค้นหา"

มันใช้งานได้ในโหมด Visual หากคุณไม่ได้ลองใช้สองครั้งและคุณไม่ได้อยู่ในโหมด linewise หรือ blockwise Visual ...


1

เนื่องจากฉันไม่เห็นที่นี่เป็นคำตอบ ( แก้ไขเพิ่งสังเกตเห็นว่าsuperjerพูดถึงสิ่งที่คล้ายกันมาก) คุณสามารถ / หรือ? ค้นหา.

ตัวอย่างเช่นคุณสามารถค้นหาอักขระที่ไม่ใช่ช่องว่างลงในคอลัมน์ที่ 2 ดังนี้:

/\%2v\S

รายละเอียดคือ:

/    "search downward (use ? for upward movement)
\%2v "for the following char in the 2nd virtual column
\S   "any non white space character

จากนั้นคุณสามารถใช้ตัวดำเนินการปกติเพื่อทำการค้นหาซ้ำ

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการดูเรื่องและ:help \%c:help \%v

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