Cách đơn giản là tháo niềng răng


8

Một người bạn của tôi nói với tôi rằng tôi có thể sử dụng mẹo dưới đây để xóa một cặp dấu ngoặc nhọn.

Đặt con trỏ bên trong cặp ngoặc nhọn mà bạn muốn loại bỏ.

y i {để kéo văn bản trong dấu ngoặc nhọn, sau v a {đó dán p.

Nó hoạt động tốt như:

for(int i = 0; i < s.length(); i++) {
        int index = s[i] - c;
        if(root->next[index] == NULL)
            root->next[index] = new TrieNode;
        root = root->next[index];
}

Sau khi thực hiện lệnh:

for(int i = 0; i < s.length(); i++)
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];

cho đến khi tôi gặp tình huống này (Không gian trước dấu ngoặc nhọn đầu tiên bị thiếu).

for(int i = 0; i < s.length(); i++){
        int index = s[i] - c;
        if(root->next[index] == NULL)
            root->next[index] = new TrieNode;
        root = root->next[index];
}

Sau khi thực hiện các lệnh đó, khối văn bản trở thành

for(int i = 0; i < s.length(); i++
        int index = s[i] - c;
        if(root->next[index] == NULL)
            root->next[index] = new TrieNode;
        root = root->next[index];
)

Khu vực tôi chọn trong chế độ trực quan có vẻ tốt, nhưng tại sao dấu ngoặc đơn đi xuống?


Bạn có chắc chắn về mẫu mã bạn đã đăng? Tôi không hiểu làm thế nào return -1;đến từ. Bạn cũng có thể chính xác nơi bạn đặt con trỏ trước khi thực hiện từng chuỗi khóa không?
statox

@statox Xin lỗi về điều đó ... Tôi đã sửa khối sau và thêm một mô tả về nơi tôi đã đặt con trỏ. Cảm ơn lời đề nghị của bạn :-)
MrDwZ

Tôi không thể sao chép này. yi{yanks giữa dấu ngoặc nhọn và vaptrực quan chọn đoạn văn (toàn bộ văn bản trong trường hợp này) nhưng tôi không thấy cách này thay đổi văn bản cả. Bạn có chắc là bạn không làm yi{+ va{+ p?
jjaderberg

2
Tôi vừa thử yi{+ va{+ ptrên văn bản của bạn trong một phiên sạch (không có vimrc, -u NONE) và điều đó tái tạo kết quả của bạn. Tôi không chắc tại sao, ví dụ pPcả hai đều cho kết quả này, mặc dù i{a{di chuyển một cách đặc trưng. Sẽ có ích nếu bạn có thể a) đưa ra một văn bản ví dụ về việc kỹ thuật của bạn hoạt động và b) xác nhận nơi 'kỹ thuật' của bạn xảy ra. @Ben chỉ ra cách giải quyết tốt trong câu trả lời của anh ấy (tôi sử dụng plugin đó) nhưng tôi không ngại tìm hiểu lý do tại sao điều này xảy ra ngay từ đầu.
jjaderberg

Tôi giống như @jjaderberg Tôi không thể tái tạo hành vi mà bạn mô tả. Đưa ra các chi tiết được hỏi trong ý kiến ​​của mình sẽ là một ý tưởng thực sự tốt.
statox

Câu trả lời:


6

Cài đặt plugin "vòm" . Sau đó, bạn có thể làm d s B .

Từ trang dự án:

Surround.vim là tất cả về "môi trường xung quanh": dấu ngoặc đơn, ngoặc vuông, dấu ngoặc kép, thẻ XML và hơn thế nữa. Plugin cung cấp ánh xạ để dễ dàng xóa, thay đổi và thêm các môi trường xung quanh theo cặp.

Lệnh được dstheo sau bởi bất kỳ đối tượng văn bản nào ( Btrong trường hợp này, đối với "Chặn", như trong đối tượng aBhoặc iBvăn bản) sẽ xóa các ký tự xung quanh xác định đối tượng văn bản. Vì vậy, d s B trong trường hợp của bạn hoàn thành những gì bạn muốn.

Các lệnh khác bao gồm c s B b, nếu bạn muốn thay đổi xung quanh {...}thành (...), hoặc y s {bất kỳ chuyển động con trỏ hoặc đối tượng văn bản} B để thêm xung quanh {...}vào văn bản được chọn bởi con trỏ.

Xem trang plugin và tài liệu để biết thêm chi tiết.


Đây là một cách giải quyết tốt. Bạn sẽ xem xét thêm một hoặc hai câu giải thích cách plugin này hoạt động và tại sao ánh xạ cụ thể hoàn thành nhiệm vụ?
jjaderberg

Có cách nào thanh lịch để loại bỏ những niềng răng mà không cần một plugin? : (
MrDwZ

Có lẽ. Nhưng vòm thực sự rất nhẹ và là một trong những plugin "thiết yếu". Vì vậy, cũng có thể cài đặt nó ...
Ben

6

Tóm lược

Đó là một lỗi và có một bản vá (743). Lỗi này ảnh hưởng đến cả hai ví dụ của bạn, nhưng bạn không thấy nó trong một trường hợp vì ký tự được chuyển xuống là (khoảng trắng). Giải pháp là cài đặt bản vá, nhưng cũng có nhiều cách giải quyết hoặc phương pháp thay thế, không bị ảnh hưởng bởi lỗi.

NB : {, }Btất cả các tham chiếu đến các đối tượng văn bản giống nhau: Block ( :help aB, :help iB). Nếu câu trả lời này hoặc câu trả lời khác sử dụng một dấu hiệu khác với câu được sử dụng trong câu hỏi, đó có thể là lý do.

Con bọ

Tôi không hiểu nó hoàn toàn, nhưng đây là hướng tới một lời giải thích, nếu ai đó quan tâm.

Hành vi bạn thấy là do một lỗi được đề cập bởi Yukihiro Nakadaira trên vim_dev và bản vá của anh ta được phát hành là 7.4.743: "p" trong chế độ Visual gây ra sự phân tách dòng bất ngờ .

Chế độ trực quan put ( :help v_p) được cho là để thay thế văn bản được chọn trực quan bằng văn bản từ một thanh ghi. Lỗi xảy ra khi a) thanh ghi thuộc loại đường thẳng ( :help linewise-register) nhưng lựa chọn trực quan là loại đặc trưng b) lựa chọn trực quan kết thúc ở cột cuối cùng của dòng. Trong trường hợp của bạn, nếu bạn kéo Khối bên trong và sau đó chọn một cách trực quan một Khối và dán, thanh ghi được kéo dài sẽ theo chiều dọc và lựa chọn trực quan sẽ đặc trưng. Chúng ta có thể kéo cả Khối bên trong và Khối sang các thanh ghi có tên và kiểm tra:

Trên

for(int i = 0; i < s.length(); i++){  
    int index = s[i] - c;  
    if(root->next[index] == NULL)  
        root->next[index] = new TrieNode;  
    root = root->next[index];  
}

chúng tôi làm

"ayi{
"bya{
:registers ab

cho thấy

--- Registers ---
"a       int index = s[i] - c;^J    if(root->next[index] == NULL)^J        root->next[index] = new TrieNode;^J    root = root->next[index];^J
"b   {^J    int index = s[i] - c;^J    if(root->next[index] == NULL)^J        root->next[index] = new TrieNode;^J    root = root->next[index];^J}

:echo getregtype('a') " displays 'V' for linewise
:echo getregtype('b') " displays 'v' for characterwise

Để thay thế một lựa chọn trực quan đặc trưng bằng một thanh ghi theo dòng, các dòng giữ đầu và cuối của lựa chọn trực quan phải được chia làm hai, để văn bản có thể được chèn vào giữa. Điều này thường hoạt động tốt:

Chạy vim như vim -u NONE -U NONEvà gõ
( a )

iaaa
bbb
ccc
ddd<Esc>ggYjlvp

kết quả trong

aaa
b
aaa
b
ccc

và ( b )

iaaa
bbb
ccc
ddd<Esc>ggYjvjp

trong

aaa

aaa
cc
ddd

Nhưng khi lựa chọn trực quan đặc trưng kết thúc ở cột cuối cùng của một dòng (và không bao gồm dòng mới /n/ ^J) thì có gì đó không ổn. Nó phải làm với vị trí con trỏ, đột nhiên tắt -1 và phải được tăng đặc biệt, đó là những gì bản vá thực hiện. So sánh ( a ) với lệnh <Esc>ggYjllvp, nghĩa là cùng một lệnh ngoại trừ di chuyển thêm một cột sang bên phải để con trỏ nằm trên "b" cuối cùng trên dòng. Kết quả vẫn như trước!

Bây giờ lấy văn bản sau:

if (TIRED){
    goto bed;
} else {
    goto work;
}

Với con trỏ trên dòng thứ hai, yi{va{pcông việc của bạn sẽ ổn và cho

if (TIRED)
    goto bed;
 else {
    goto work;
}

Thanh ghi yank vẫn thẳng hàng và lựa chọn trực quan một cách đặc trưng, ​​nhưng lựa chọn trực quan không kết thúc ở cột cuối cùng nữa, và mọi thứ đều ổn.

Ví dụ văn bản từ câu hỏi

Đối với hai văn bản mẫu, trong đó điểm khác biệt duy nhất là khoảng trắng giữa đóng ngoặc đơn và mở dấu ngoặc nhọn ở dòng đầu tiên, có vẻ như lệnh của bạn hoạt động khác nhau, nhưng thực sự không phải vậy. Trong trường hợp đầu tiên, cái nào trông có vẻ thành công, phải có một khoảng trắng ở cuối dòng đầu tiên sau khi dấu ngoặc được loại bỏ. Thay vào đó, khoảng trắng ở cuối dòng. Vớiyi{va{p

for(int i = 0; i < s.length(); i++) {
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
}

trở thành

for(int i = 0; i < s.length(); i++)
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
␣

giống như

for(int i = 0; i < s.length(); i++){
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
}

trở thành

for(int i = 0; i < s.length(); i++
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
)

Các giải pháp

Giải pháp sẽ là cài đặt bản vá, nhưng có nhiều cách khác để loại bỏ các dấu ngoặc xung quanh không bị lỗi. Cách giải quyết tốt nhất là câu trả lời @Gilles nhưng dễ nhất có thể là chọn trực quan trước khi bạn kéo, để giữ cho thanh ghi đặc trưng.

Plugin Surround của Tim Pope rất tuyệt vời, nhưng (ít nhất là đối với tôi) nó không chỉ xóa dấu ngoặc: nó nối dòng thứ hai với dòng thứ nhất, nó loại bỏ vết lõm và nó di chuyển con trỏ đến đầu dòng đầu tiên. Điều này để lại một số dọn dẹp không tầm thường để làm. Ingo Karkat và Luc Hermitte có các plugin liên quan đến đăng ký và dán (tôi chắc chắn có nhiều người khác) và điều đó sẽ có thể làm điều này. Tôi không quen thuộc lắm với chúng, nhưng tôi tin rằng với lh-ngoặc bạn có thể làm <M-b>xđể xóa các dấu ngoặc xung quanh và để đặt mạnh hơn (đặc biệt là ở chế độ trực quan), bạn có thể xem Thay thếWithRegisterUnconditablePaste .

Cách tốt nhất là đưa ra trong câu trả lời @Gilles , [{x]}x. Nó nhanh, xử lý các khối lồng nhau tốt và không nối các dòng không phù hợp hoặc lộn xộn với vết lõm. Nếu có một khoảng trắng trước dấu ngoặc mở, bạn có thể dễ dàng thêm một xlệnh vào để loại bỏ nó:[{xx]}x

Các lệnh vanilla khác

Một lần nữa, lệnh thích hợp nhất mà tôi có thể nghĩ đến là câu lệnh trong câu trả lời của @Gilles, [{x]}xhoặc [{xx]}x, nhưng đây là hai lựa chọn thay thế cụ thể cho thấy lỗi này.

Yank đặc trưng

Vì lỗi chỉ xảy ra đối với trực quan, hãy đăng ký theo chiều dọc trên lựa chọn theo đặc tính và vì nó chỉ là ngẫu nhiên đối với Khối bên trong của bạn mà nó là đường thẳng, thay vào đó, bạn có thể chọn cách kéo nó theo cách đặc biệt. Một cách dễ dàng là chọn trực quan Khối bên trong trước khi kéo nó và để đảm bảo rằng lựa chọn trực quan là đặc trưng (nghĩa là vkhông sử dụng V) : vi{yva{p. Đây có thể là cách dễ nhất vì nó rất giống với cách bạn hiện đang thực hiện thao tác.

Đừng sử dụng trực quan

Các lệnh khác, như thay đổi và xóa, không bị ảnh hưởng bởi lỗi này. Bạn có thể kéo dài như trước, nhưng sau đó xóa một Khối vào thanh ghi lỗ đen ( :help quote_) và đặt hoặc xóa một Khối và đặt từ thanh ghi 0 ( :help quote0): yi{"_da{phoặcyi{da{"0p

Tổng quát

Cuối cùng, có những cách tương tự như @Gilles trả lời, hãy chuyển sang bắt đầu một Khối, xóa ký tự, di chuyển đến cuối một Khối, xóa ký tự nhưng đó là chung chung hơn. Lý do duy nhất để sử dụng chúng là nếu "khối" bạn đang xóa xung quanh là lệch tâm và không có các chuyển động liên quan hoạt động cũng như [{đối với một khối được phân định bằng dấu ngoặc nhọn. Có khả năng plugin vim-Surround có thể xử lý tốt các khối lập dị này, nhưng hai cách vanilla sẽ là

  1. Trực quan chọn khối lập dị và để chế độ trực quan. Con trỏ nằm trên ký tự cuối cùng của vùng chọn. Xóa nó, sau đó đi đến phần đầu của lựa chọn cuối cùng ( :help `<) và xóa ký tự.va{<Esc>x`<x
  2. Tìm kiếm ngược về đầu khối lập dị và xóa ký tự, sau đó tìm về phía trước khối kết thúc và xóa ký tự. ?{<CR>x/}<CR>xĐiều này có thể không hoạt động tốt với các khối lồng nhau.

Số lượng nhân vật

+----+------------------------+----------------------------+------------+
|    | method                 |          command           | characters |
+----+------------------------+----------------------------+------------+
| 1. | vim-surround           | ds{                        |          3 |
| 2. | @Gilles answer         | [{x]}x                     |          6 |
| 3. | Characterwise yank     | vi{yva{p                   |          8 |
| 4. | Delete, not visual put | yi{"_da{p or yi{da{"0p     |          9 |
| 5. | Visual mark            | va{<Esc>x`<x               |          8 |
| 6. | Search                 | ?{<CR>x/}<CR>x             |          8 |
+----+------------------------+----------------------------+------------+

5

Vì bạn không yêu cầu con trỏ trở về vị trí ban đầu, nên [{x]}xthực hiện công việc. Nó dài 6 ký tự với hai lần nhấn Shiftnhưng nguyên tắc thì đơn giản nên dễ nhớ.

Nếu bạn muốn quay lại vị trí ban đầu, bạn có thể sử dụng [{x``]}x``

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.