Tự động tạo dấu ngoặc phù hợp trong vim


17

Làm cách nào để tự động tạo dấu ngoặc phù hợp trong vim?

Nó sẽ hoạt động như sau: Nếu tôi nhập một dấu ngoặc mở, đóng sẽ xuất hiện tự động và con trỏ sẽ được đặt ở giữa. Để nhảy ra khỏi cặp nẹp, sự kết hợp Ctrl-jđược sử dụng.

Có rất nhiều plugin cung cấp chèn nẹp tự động. Nhưng họ

  • hoặc sử dụng một tổ hợp phím khác hơn là Ctrl-jnhảy ra khỏi cặp nẹp hoặc
  • can thiệp vào các ràng buộc chính của UltiSnips .

Các công việc sau đây như mong đợi

:inoremap ( ()<Esc>:let leavechar=")"<CR>i
:imap <C-j> <Esc>:exec "normal f" . leavechar<CR>a

Nhưng với các cài đặt này, đoạn trích UltiSnips không hoạt động nữa. Vì vậy, tôi đã sử dụng UltiSnips để chèn dấu ngoặc nhọn:

inoremap ( (<C-R>=UltiSnips_Anon('($1)$0', '(')<CR>

Điều này gần như hoạt động. Niềng răng phù hợp được chèn và tôi có thể bỏ qua việc đóng lại với Ctrl-j. Điều này, tuy nhiên, chỉ hoạt động nếu có một khoảng trống ở phía trước của nẹp mở.

main () // works, the closing parentheses is added
main(   // fails without a space

Các giải pháp của tôi hoặc yêu cầu một ràng buộc khóa khác để nhảy qua nẹp đóng hoặc yêu cầu một khoảng trống ở phía trước của mở. Làm thế nào để khắc phục điều này?

Lưu ý: Tôi đã sử dụng dấu ngoặc đơn làm ví dụ. Nó nên hoạt động với dấu ngoặc đơn, dấu ngoặc nhọn, dấu ngoặc và dấu nhỏ hơn và không can thiệp vào plugin UltiSnips.


1
Bạn đã thử tự động tiết lộ ? Bạn có thể nhảy ra khỏi cặp với ), ánh xạ lại c-jđể có thể làm việc.
Kevin

Câu trả lời:


4

Làm cách nào để tự động tạo dấu ngoặc phù hợp trong vim?

Vấn đề này là không tầm thường, như bạn sẽ thấy. Câu trả lời đơn giản là: Sử dụng một plugin, như Tự động đóng hoặc smartinput . Chỉ cần ánh xạ lại một cách ngây thơ ([.. các phím sẽ hiển thị cho bạn các edgecase trong một vài dòng, đó là lý do tại sao các plugin này được tạo ra và tại sao chúng thường khá phức tạp (nếu chúng tốt).

Vì vậy, tôi đã sử dụng UltiSnips để chèn nẹp đóng

Bạn có thể thử điều này thay vào đó (khác với đề xuất ban đầu của tôi):

inoremap ( ()<CR>=UltiSnips_Anon('$1)$0', ')')<CR>

Trường hợp UltiSnips sẽ phân chia dòng trên (thay vì bao gồm maintrong trận đấu. Vấn đề với việc sử dụng plugin đoạn trích cho việc này là chúng (thường) không hỗ trợ lồng nhau, vì vậy chúng sẽ quên bất kỳ vị trí nhảy nào khi đoạn mã tiếp theo (lồng nhau) được chèn.

Để nhảy ra khỏi cặp nẹp, sự kết hợp Ctrl-jđược sử dụng.

Bạn có Ctrl-jthể ánh xạ lại cho UltiSnips hoặc plugin xung đột. Nếu ánh xạ không được liệt kê trong tài liệu, bạn có thể sử dụng :map/imap/nmap <key>để hiển thị ánh xạ. Nếu bạn muốn Ctrl-jchọn và chọn và thực hiện công việc của cả hai plugin, bạn đang yêu cầu:

  1. một cái gì đó cao cấp hơn nhiều so với tôi nghĩ bạn có thể nghĩ
  2. một cái gì đó tôi nghi ngờ bạn không thực sự muốn

Hãy xem xét vòng lặp bash này:

while (( ${arr1[i]} < ${arr2[i<CURSOR>]} )); do
  [next_snippet_position_marker]
done

Trong trường hợp này, bạn sẽ cần nhấn Ctrl-j5 lần để đến thân vòng lặp. Sử dụng dấu ngoặc nhọn để nhảy ra khỏi một cặp tương ứng giúp bạn kiểm soát nhiều hơn nơi bạn thực sự muốn con trỏ di chuyển. Bạn có thể triển khai một ngăn xếp để theo dõi các cặp được chèn và sử dụng Ctrl-jđể bật và di chuyển, nhưng sau đó bạn sẽ gặp vấn đề nếu bạn bắt đầu xóa dấu ngoặc bằng tay mà không xóa chúng khỏi ngăn xếp. Vì vậy, bạn sẽ bắt đầu giải quyết các vấn đề mà các phần bổ trợ đang cố gắng giải quyết. Đây là một bánh xe cứng để phát minh lại.

Mở rộng về điều này, bạn có thể nhận được những gì ban đầu bạn yêu cầu, sử dụng Ctrl-jđể nhảy ra khỏi niềng răng đoạn trích. Nếu bạn sử dụng một số giá trị giả để thể hiện các vị trí đoạn trích và đẩy chúng lên ngăn xếp ngoài dấu ngoặc nhọn, với ánh xạ lại động Ctrl-jđể tương ứng với việc đưa đoạn mã hoặc dấu ngoặc nhọn. Nhưng sau đó, bạn sẽ cần triển khai một số phương pháp phỏng đoán khá tiên tiến để tìm ra điều kỳ diệu nào sẽ xảy ra, vì về cơ bản bạn đang gặp phải hai vấn đề, hiện đang được giải quyết bởi những người tạo ra các plugin chèn đoạn trích và các phần bổ trợ khớp nối riêng biệt, và giải quyết lại các vấn đề này một lần nữa, trên các giải pháp của họ , để đạt được sự thuận tiện và, tốt, ma thuật.

Nó đi xuống để kiểm soát vs thuận tiện. Tôi nghĩ rằng kiểm soát sẽ phục vụ bạn tốt hơn trong trường hợp này, có nghĩa là bạn nên giữ những vấn đề này và các plugin và keymappings liên quan của chúng riêng biệt. Nếu bạn vẫn muốn sự thuận tiện, điều đó là có thể, nhưng thật khó.


1

Tôi nghĩ delimitMate làm những gì bạn cần.

Nó tự động đóng dấu ngoặc đơn hoặc dấu ngoặc kép và đặt con trỏ của bạn ở giữa. Để nhảy ra khỏi cặp dấu ngoặc đơn (trong khi đang ở chế độ chèn) bạn sẽ làm Ctrl-g+ gnhưng bạn có thể ánh xạ lại điều này Ctrl-jbằng cách thêm nó vào vimrc:

% Jump out of a block of parentheses (uses delimitMate)
imap <C-j> <C-g>g

Tốt hơn là cung cấp thêm chi tiết ở đây và sử dụng liên kết làm tài liệu tham khảo để đọc thêm. Bằng cách đó, câu trả lời của bạn không mất đi tất cả giá trị của nó khi liên kết trở nên không hợp lệ.
Anthon

1

Tôi đã tìm thấy tự động tiết lộ thêm một chút độ trễ và cũng can thiệp vào thiết lập của tôi (Ultisnips và Supertab), nhưng tôi thích cách tiếp cận mô phỏng CDT của Eclipse.

Tôi sử dụng delimitMate với các bản đồ sau để giúp điều hướng và thụt lề, cố gắng để có được kết quả tương tự:

imap <C-F> <C-G>g           " To jump out brackets in same line.
inoremap <C-K> <ESC>ki<TAB> " To move and insert an indent on the line before the current cursor (assuming empty line)

Tôi sử dụng nó theo cách này: chèn mở { <CR><CR><C-K>và bắt đầu viết trong dòng bên trong thụt vào.


Tôi thấy delimitMate cũng bị thêm một chút độ trễ
icc97

1

Cá nhân tôi sử dụng smartinput để tự động chèn dấu ngoặc và dấu ngoặc kép. Ví dụ, gõ {bất cứ nơi nào sẽ tạo ra {}với con trỏ của bạn ở giữa. Để rời khỏi {nhóm khung, bạn chỉ cần nhập }khi bên cạnh chèn }.

Tuy nhiên, điều này không hỗ trợ yêu cầu của bạn về các tabstops và nhảy ra ngoài khung. Nó cũng không tạo ra một điểm mới giữa các dấu ngoặc của bạn, nhưng bạn chỉ cần thêm một khóa cho điều đó - <CR>.

Bạn có thể ánh xạ <C-J>để nhảy xuống dòng tiếp theo:

:inoremap <C-J> <C-O>j

hoặc nếu bạn muốn di chuyển đến đầu dòng tiếp theo:

:inoremap <C-J> <C-O>+

0

Một cái gì đó như thế này có thể làm việc cho bạn.

inoremap {      {}<Left>
inoremap {<CR>  {<CR>}<Esc>O
inoremap {{     {
inoremap {}     {}

Những gì bạn đề xuất là một ánh xạ đơn giản không cho phép nhảy qua cú đúp kết thúc.
Marco

0

Trên thực tế, Ultisnips có thể làm điều đó gần như hoàn hảo (điều này có thể là mới). Sửa đổi một chút câu trả lời ở trên, tôi có thành công tốt với

inoremap () ()<C-R>=UltiSnips#Anon('($1)$0', '()', 'double parentheses', 'i')<CR>

Người ta phải gõ ()cái nào tốt hơn nhưng cũng có thể thay đổi (. Sau đó, các đối số tùy chọn bổ sung UltiSnips#Anonlà một mô tả và công cụ sửa đổi icho phép mở rộng bằng từ.

Nhảy ra khỏi dấu ngoặc đơn với <c-j>các tác phẩm, cũng được lồng trong các đoạn khác. Tuy nhiên, việc gọi ()dấu ngoặc đơn lồng nhau dường như phá vỡ tính năng này, đây không phải là vấn đề lớn.

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.