Làm thế nào để tôi di chuyển theo chiều dọc cho đến khi đạt được một ký tự không phải khoảng trắng?


27

Trong một tệp rất dài với mã thụt lề (chính xác-), có thể hữu ích khi di chuyển trực tiếp đến một dòng văn bản ở trên hoặc bên dưới con trỏ để phân định thụt lề.

(Một cách để làm điều này có thể là thông qua foldmethod indent, bằng cách gấp mức thụt lề hiện tại, mà sụp đổ dây chuyền phân chia ranh giới mức thụt lề phải chỉ một jhoặc kxa con trỏ. Trường hợp Tuy nhiên, tôi đã tìm thấy nơi gấp thụt lề có không đã có thể làm việc trên thụt lề mà tôi quan tâm.)

Đây là một ví dụ, với con trỏ được đánh dấu bởi dấu gạch dưới _(ở cột ký tự thứ hai giữa các định nghĩa của class Bazzclass Qux), nhưng hãy tưởng tượng rằng số lượng đoạn văn hoặc dòng trong modules là không xác định hoặc biến:

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

... làm thế nào tôi có thể nhanh chóng điều hướng đến ocủa module Bartrên con trỏ, hoặc ncủa endbên dưới con trỏ ở dòng cuối cùng? Lưu ý rằng cột dọc chứa khoảng trắng, nhưng cũng không có ký tự nào ở cột thứ hai ở giữa các classđịnh nghĩa.


2
có liên quan: "Chuyển đến dòng tiếp theo / trước với cùng một vết lõm" trên Vim Tips Wiki vim.wikia.com/wiki/Move_to_next/ Kẻ
alxndr

Nhấn phím g và sau đó phím điều hướng có thể tránh các tab và di chuyển trên các dòng
SibiCoder

1
Giải pháp trong liên kết của @ alxndr hoạt động tốt trừ trường hợp khoảng trắng được duy trì kém (ví dụ: có những dòng ngẫu nhiên chỉ có khoảng trắng) và bạn muốn bỏ qua khoảng trắng. giải pháp của superjer dưới đây là tốt hơn nếu một người quan tâm đến trường hợp đó.
nukeguy

Câu trả lời:


9

Làm thế nào về chức năng này?

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

Bạn có thể nnoremap gU :call FloatUp()<CR>( gUcho "đi lên"), và sau đó gọi với gU.

Đây là một lời giải thích:

  • Mã liên tục di chuyển lên con trỏ (với norm k) miễn là whileđiều kiện giữ.
  • Điều whilekiện giữ nếu đây không phải là dòng đầu tiên ( line(".") > 1) và
    • dòng này quá ngắn (có thể trống); hoặc là
    • dòng hiện tại ( getline(".")) 's nhân vật ở cột hiện tại ( [col(".") - 1]) là khoảng trắng ( =~ '\s'; tức là, phù hợp với mô hình khoảng trắng).

1
Điều này dường như hoạt động hoàn hảo (và nhanh chóng), và cũng dễ dàng được sửa đổi thành một FloatDownchức năng. Vào .vimrc của tôi nó đi, cảm ơn! github.com/alxndr/dotfiles/commit/0e25a302
alxndr

1
Chỉ cần phát hiện ra rằng giải pháp này không hoạt động hoàn toàn ở chế độ trực quan (hành vi hơi khác nhau tùy thuộc vào chế độ hình ảnh nào, nó sẽ ở cùng một vị trí hoặc chỉ di chuyển bằng một dòng). Bất kỳ con trỏ về những gì đang xảy ra ở đó?
alxndr

13

Tôi thích sử dụng tìm kiếm cho những thứ này, vì regex của Vim có số lượng lớn những thứ bạn có thể tìm kiếm, như số cột ảo cụ thể, trong trường hợp này:

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

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

Sử dụng cdđể đi xuống và cuđi lên. Tôi đang nghĩ "cột lên" và "cột xuống" ở đây. Tôi gần như tự tin 100% rằng đây là những sản phẩm không hoạt động theo mặc định. Hoặc chọn bản đồ của riêng bạn.

Điều này sẽ hoạt động cho dù bạn đang sử dụng tab hoặc dấu cách hoặc cả hai.


1
Tôi gặp khó khăn khi phân tích các lệnh đó. Bạn có phiền mở rộng về họ một chút không?
davidlowryduda

1
/ hoặc là ? để tìm kiếm xuống hoặc lên, \% xv giới hạn tìm kiếm số cột ảo 'x', 'x' trong trường hợp này là '<CR> = virtcol (".") <CR>' chạy lệnh virtcol và chèn số cột ảo mà con trỏ ở trong biểu thức, \ S có nghĩa là bất kỳ ký tự không phải khoảng trắng nào.
Chad

1
Cảm ơn đã giải thích Chad. Tôi sẽ chỉ thêm rằng <CR> trong chế độ Chèn hoặc chế độ Dòng lệnh lấy nội dung của thanh ghi. Thanh =ghi là thanh ghi biểu thức đánh giá một biểu thức tại chỗ. Nó rất tiện dụng, nếu không muốn nói là hơi lạ.
superjer

1
Một nhược điểm của phương pháp này là nếu bạn có tô sáng tìm kiếm, bạn sẽ thấy rằng tất cả các ký tự trong cột dọc của con trỏ hiện được tô sáng sau khi "cột lên" ing hoặc "cột xuống" ing.
alxndr

3
Nếu bạn muốn bảo vệ tìm kiếm hiện tại của mình, bạn có thể thêm :let searchbak=@/<CR>và nối thêm :let @/=searchbak<CR>. Nhưng tại thời điểm này, nó trở nên dài và không thể chấp nhận được và có lẽ chỉ nên là một chức năng.
superjer

7

Bạn có thể sử dụng plugin JumpToV verticalOccurrence (được ánh xạ mặc định ]|[|). Có một vài cái khác giống như ]V{char}hoạt động f, nhưng theo chiều dọc. Tất nhiên bạn có thể sắp xếp lại chúng theo yêu cầu.


Nếu bạn không muốn sử dụng plugin, bạn có thể thử sử dụng :searchvới virtcol(.), ví dụ:

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

Ở đâu:

  • virtcol('.') cung cấp cho bạn cột hiện tại,
  • \S là viết tắt của khoảng trắng
  • bW là để tìm kiếm ngược

Kiểm tra :help searchđể tìm hiểu thêm.

Để dễ sử dụng hơn, bạn có thể ánh xạ nó, ví dụ:

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

Ngoài ra, nếu mã của bạn có chứa dấu ngoặc, sử dụng %để nhảy giữa phù hợp với họ (ví dụ như {, }, [, ], vv) hoặc sử dụng toàn bộ đoạn nhảy ( {, }với Shiftnếu cần).


Liên kết / nguồn:


Từ :h search(): wphương tiện wrap around the end of the fileWphương tiện don't wrap around the end of the file. Nhưng tại sao bạn lại đặt chúng vào thứ hai :map?
Jair López

@JairLopez Đúng, wkhông nên ở đó, vì vậy tôi đã xóa nó, cảm ơn. Có lẽ tôi đã nhầm lẫn bởi các phím chuyển động có nghĩa.
kenorb

3

Tôi sử dụng một phiên bản sửa đổi của plugin vim-indent-object để cung cấp hành vi này. Sửa đổi của tôi có thể được nhìn thấy ở đây .

Điều này cho phép tôi lập bản đồ [iđể đi đến đầu mức thụt lề hiện tại và ]iđi đến cuối.


2

Đó không phải là chính xác những gì bạn yêu cầu bởi vì nó không phải là chuyển động thẳng đứng, nhưng một cái gì đó tương tự, nhanh chóng và có thể đủ tốt cho bạn đang di chuyển ngược 2 đoạn : {{. Điều này sẽ đưa bạn đến dòng ngay trước module Bar.


2
Hãy tưởng tượng có một số dòng và / hoặc đoạn không xác định giữa con trỏ và moduledòng cấp cao nhất của nó . (Cụ thể, tình trạng này nảy sinh khi tôi gần đây đã được điều hướng mã bên thứ ba vài ngàn dòng dài, với thụt đầu dòng chính xác nhưng không có dòng sản phẩm nào, và cố gắng để tìm bối cảnh bên ngoài của định nghĩa của một mô-đun.)
alxndr

Nhảy theo đoạn văn là cách di chuyển ưa thích của tôi, nhưng đó không phải là một lựa chọn: toàn bộ tệp là một "đoạn".
alxndr


1

Tôi sử dụng plugin move_until_char_changes.vim của riêng tôi cho điều đó.

Tôi ánh xạ nó đến gKgJ.

Nó sẽ nhảy qua nhiều dòng có cùng ký tự trong cột hiện tại (không chỉ khoảng trắng), có thể hữu ích trong các tệp logfiles hoặc SQL với các chuỗi lặp lại.

Theo mặc định, đầu tiên nó di chuyển một dòng, trước khi chọn ký tự "tìm kiếm".

Nó hoạt động ở chế độ Trực quan với điều kiện bạn không thử sử dụng hai lần và bạn không ở chế độ Trực quan hoặc theo chiều dọc ... (sửa chữa chào mừng!)


1

Vì tôi không xem nó ở đây như một câu trả lời ( chỉnh sửa chỉ nhận thấy rằng siêu nhân đã đề cập đến một cái gì đó rất giống nhau). Bạn có thể chỉ đơn giản là / hoặc? Tìm kiếm.

Ví dụ: bạn có thể tìm kiếm xuống một ký tự không phải khoảng trắng trong cột thứ 2 như thế này:

/\%2v\S

Sự cố là:

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

Sau đó, bạn có thể sử dụng các toán tử bình thường để lặp lại tìm kiếm.

Để biết thêm thông tin về chủ đề xem :help \%c:help \%v.

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.