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 : {, }và 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 và 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}
và
: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 NONE
và 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{p
cô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ếWithRegister và UnconditablePaste .
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 x
lệ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]}x
hoặ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à v
khô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{p
hoặ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à
- 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
- 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 |
+----+------------------------+----------------------------+------------+
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?