Lời khuyên cho việc chơi golf trong vim


32

Gần đây tôi đã nhận ra cách vim hoạt động tuyệt vời cho việc chơi golf, đặc biệt là đối với . Ngoài ra, theo meta vim là một "ngôn ngữ lập trình" hoàn toàn chấp nhận được, ít nhất là đối với phạm vi của trang web này.

Bạn có lời khuyên chung nào cho việc chơi golf ở Vim? Tôi đang tìm kiếm những ý tưởng có thể áp dụng cho các vấn đề về golf-code và ít nhất cũng hơi cụ thể đối với Vim (ví dụ: "xóa bình luận" không phải là một câu trả lời).

Xin vui lòng gửi một lời khuyên cho mỗi câu trả lời.


4
Đây là một câu hỏi mẹo đặc biệt hữu ích vì "Mẹo chơi golf trong vim" và "Mẹo sử dụng vim hiệu quả như một trình soạn thảo văn bản" về cơ bản là giống nhau.
DLosc

Câu trả lời:


15

Hãy nhận biết các biến thể chữ hoa của các lệnh phổ biến. Điều này có thể lưu một cách tầm thường một tổ hợp phím trong rất nhiều bối cảnh. Ví dụ:

A = $a
C = c$
D = d$
I = ^i
S = cc
X = dh
Y = yy

Một cách khác là sử dụng Gthay vì gg, nhưng chỉ khi bạn sử dụng số đếm! Ví dụ, không có số đếm, ggdi chuyển đến đầu và Gdi chuyển đến cuối. Tuy nhiên, với số đếm, cả hai đều di chuyển đến dòng bạn chỉ định, do đó 5Gngắn hơn nhưng tương đương với 5gg .

Một cách khác, là sử dụng Hthay thế gg, nhưng điều quan trọng cần lưu ý là điều này chỉ hoạt động nếu bạn có thể đảm bảo rằng bất kỳ đầu vào nào sẽ không chiếm nhiều hơn số lượng hàng mặc định (tôi tin rằng đây là 24, nhưng nó có thể thay đổi).


1
Nếu một thách thức cụ thể là trình soạn thảo golf (và do đó thường được ghi bằng tổ hợp phím) thì một chữ cái viết hoa cũng là hai tổ hợp phím ( $mặc dù vậy, ít nhất là như vậy CDsẽ tiết kiệm được một cái gì đó).
Martin Ender

1
Một điều tôi không rõ khi ghi điểm trong tổ hợp phím là liệu các chữ cái liên tiếp yêu cầu phím shift chỉ đếm phím shift một lần cho mỗi nhóm, vì bạn có thể (ít nhất là cho các mục đích thực tế) giữ nó trong khi bạn nhấn các phím khác.
Alex A.

6
@AlexA. Cá nhân, tôi nghĩ rằng sửa đổi không nên tính. Có lẽ chúng ta cần một bài đăng meta về điều này ...
DJMcMayhem

Gggkhông tương đương. Cái trước đi đến phần cuối của bộ đệm và cái sau đi đến phần đầu.
Jordan

@Jordan Đó là một điểm tốt. Ý tôi là chúng giống nhau khi được tính, ví dụ như 5Gtương đương với 5gg. Tôi sẽ thêm một số chi tiết về điểm đó.
DJMcMayhem

11

Bất cứ khi nào một lệnh thất bại, nó sẽ tạo ra một tiếng ồn ding, sẽ hủy bỏ macro hiện tại. Bạn có thể (ab) sử dụng điều này để tạo ra một dạng vòng lặp thô. Ví dụ: nếu bạn muốn lặp lại tổ hợp phím <foobar>cho đến khi bộ đệm của bạn có ít hơn 3 dòng trong đó. Bạn có thể làm

qq<foobar>3G``@qq

nghĩa là:

qq                 'Start recording in register q
  <foobar>         'Keystrokes
          3G       'Go to line 3. If line 3 doesn't exist, this is effectively a "break" statement.
            ``     'Jump back to previous cursor location
              @q   'Call macro q
                q  'Stop recording

Điều quan trọng cần lưu ý là nếu bạn đang thử nghiệm điều này trong phiên vim, thì @qcó thể có tác dụng phụ ngoài ý muốn, vì macro được tải từ đó .vim_profile. Bạn có thể nhận được xung quanh điều này một vài cách khác nhau. Có lẽ cách giải quyết tốt nhất là khởi chạy vim với

vim -i NONE

Bạn cũng có thể xóa của bạn .viminfo.

Nếu bạn đã khởi chạy vim, bạn có thể gõ

qqq

ở đầu để không vĩ mô ra.

Các điều kiện khác bạn có thể thay thế 3G bằng

f<char>    'Jump to first occurence of <char>. Also see F, t and T

hoặc là

<number>|  'Go to the <number>'th character on the current line.

8

Có nhiều phiên bản rút gọn của các lệnh ex mà bạn nghĩ. Ví dụ, có lẽ bạn đã biết :globalcó thể rút ngắn :g, nhưng bạn có biết nó :nnoremaptương đương với :nnkhông?

Bạn nên chạy :h :footrên tất cả các lệnh cũ mà bạn đang sử dụng trong câu trả lời của mình để xem có phiên bản ngắn hơn không.


6
:%s/\n//g

luôn luôn tương đương với

:%s/\n//

điều này cũng tương đương với

:%s/\n

đủ đáng ngạc nhiên. (Nói chung, không có bất kỳ cờ nào, dấu gạch chéo cuối cùng trong :sbiểu thức là không bao giờ cần thiết.)


2
Điều này hoạt động cho dòng mới, nhưng không hoạt động cho bất kỳ nhân vật nào có thể xuất hiện nhiều lần trong một dòng. Ví dụ: :%s/xkhông loại bỏ mọi lần xuất hiện của x, chỉ lần đầu tiên trên mỗi dòng.
DJMcMayhem

1
Bạn cũng có thể sử dụng :&&để lặp lại một lệnh thay thế đó là cờ.
DJMcMayhem

6

Giả sử bạn đang ở chế độ chèn và bạn muốn tạo một lệnh chế độ bình thường duy nhất. Bạn có thể viết như thế này:

isome_text<esc><foobar>gisome_more_text

Đừng làm theo cách đó. Thay vào đó, sử dụng <C-o>, thực thi một lệnh bình thường duy nhất sau đó ngay lập tức trở lại chế độ chèn.

isome_text<C-o><foobar>some_more_text

Tôi cũng không nghĩ những chỗ trống đó là cần thiết
Vụ kiện của Quỹ Monica

@QPaysTaxes Bạn nói đúng, họ không. Tôi nghĩ rằng nó sẽ làm cho nó dễ đọc hơn. Tôi sẽ chỉnh sửa nó.
DJMcMayhem

Bạn không cần một <CR>sau <foobar>để gửi lệnh?
Vụ kiện của Quỹ Monica

@QPaysTaxes Chỉ khi đó là lệnh ex hoặc tìm kiếm. (Ví dụ: bất kỳ lệnh bắt đầu với một :, /hoặc ?)
DJMcMayhem

Ôi lỗi của tôi. Tôi nhầm lẫn lệnh và chế độ bình thường. Tuyệt vời: D
Vụ kiện của Quỹ Monica

5

Có ba toán tử "trường hợp thay đổi",

gu    "Convert to lowercase
gU    "Convert to uppercase
g~    "Toggle case

Vì đây là các toán tử, chúng có một chuyển động, vì vậy để chuyển đổi ký tự hiện tại thành chữ thường bạn sẽ sử dụng

gul

Đây là một mẹo thú vị xuất hiện. :) Nếu bạn muốn thay đổi trường hợp của một ký tự đơn hoặc dòng hiện tại, đó là một byte ngắn hơn trong chế độ trực quan. Ví dụ gultương đương với

vu

gu_(_ là dòng hiện tại) tương đương với

Vu

Thủ thuật này không hoạt động để chuyển đổi, vì v?kích hoạt tìm kiếm ngược trong chế độ trực quan, (giống như v/nhưng di chuyển theo hướng ngược lại) nên bạn cần vg?thay thế. Tuy nhiên, đây là nơi bạn có thể sử dụng ~toán tử, để tiết kiệm nhiều byte hơn nữa! (Cảm ơn @Doorknob đã chỉ ra điều này)

Bạn có thể thấy thủ thuật này hoạt động trên câu trả lời vim của tôi ở đây , và trên câu trả lời V tương đương trên và bài.


1
Đừng quên ~, điều này làm thay đổi trường hợp của nhân vật dưới con trỏ và di chuyển sang bên phải!
Doorknob

5

Bảng chữ cái trong 10 tổ hợp phím

Tất cả tín dụng cho kỹ thuật này thuộc về Lynn, người đầu tiên sử dụng nó trong câu trả lời này . Tôi đang viết nó lên đây cho hậu thế.

Sử dụng mười tổ hợp phím sau để kéo bảng chữ cái viết thường:

:h<_␍jjYZZ

(Trường hợp trả lại vận chuyển, tức là phím Enter.)

Giải trình

:h<_␍mở phần trợ giúp v_b_<_example(một ví dụ về lựa chọn khối theo hình ảnh), điều này xảy ra để chứa văn bản abcdefghijklmnopqrstuvwyxz. jjYdi chuyển xuống dòng đó và kéo nó ra, sau đó ZZđóng cửa sổ trợ giúp.


4

Biết đăng ký của bạn

Yanking hoặc xóa văn bản vào một thanh ghi cụ thể (ví dụ "aY) để sử dụng nó sau này không phải lúc nào cũng cần thiết. Vim có một số thanh ghi được tự động điền với các đối tượng của các lệnh khác nhau. Nhập :help registersđể xem tất cả, nhưng đây là một vài lưu ý cụ thể:

  • Thanh ghi không tên: ""- Văn bản cuối cùng được kéo hoặc xóa.

  • Đăng ký đánh số "0- Văn bản cuối cùng được kéo mạnh.

  • Các thanh ghi được đánh số "1- "9- Văn bản cuối cùng đã bị xóa trừ khi nó nhỏ hơn một dòng. Mỗi lần "1được lấp đầy, nội dung trước đó của nó được chuyển sang "2và cứ thế.

  • Thanh ghi xóa nhỏ: "-- Văn bản cuối cùng ngắn hơn một dòng đã bị xóa.

  • Văn bản được chèn lần cuối: ".

Đặc biệt, "-"1thanh ghi có thể ở bên nhau rất hữu ích, cho phép bạn xóa một số văn bản với ví dụ ddvào "1đăng ký và xóa một số văn bản khác với Dvào "-(tất nhiên, ngữ nghĩa là không giống nhau, nhưng thường họ không cần phải ).

Tất cả các thanh ghi có thể hơi khó theo dõi, nhưng bạn có thể xem nội dung của tất cả các thanh ghi của mình bất cứ lúc nào bằng cách gõ :registers.


3

Điều này xuất hiện trong cuộc trò chuyện trước đó, vì vậy tôi nghĩ rằng tôi cũng có thể đăng nó dưới dạng một mẹo đầy đủ.

<C-a><C-x>tăng và giảm số tiếp theo trên dòng. Đây là một tính năng cực kỳ hữu ích cho một số phép toán đơn giản, nhưng nó cũng cho phép hack nhỏ gọn.

Giả sử bạn cần chuyển sang số tiếp theo. Ví dụ, chúng ta cần thay đổi

I need 2 spell better

đến

I need to spell better

Cách rõ ràng là nhảy sang 2, sau đó làm:

sto                "Synonymous with 'clto'

Vì cái này ngắn hơn

:s/2/to<cr>

Có nhiều cách khác nhau để chuyển sang 2. Ví dụ:

/2<cr>
ww 
2w
ee
2e
8|
f2

Cũng như nhiều cách khác.

Đây là tất cả 2 (hoặc nhiều hơn) tổ hợp phím. Tuy nhiên, vì <C-a><C-x>không chỉ các số tăng / giảm, mà còn chuyển sang số tiếp theo, chúng ta có thể tắt một byte với

<C-a>sto

3

Phong trào chơi gôn

Thường xuyên nếu bạn đang làm việc với một khối văn bản (đặc biệt là trong thử thách ), bạn sẽ cần chuyển sang ký tự đầu tiên hoặc cuối cùng trong bộ đệm. Ggglà khá tốt, nhưng có một số điều gây phiền nhiễu. Ví dụ: để có được ký tự cuối cùng, bạn cần G$ggkhông nhất thiết phải đưa bạn lên cột đầu tiên nếu có khoảng trắng hàng đầu. Dưới đây là một số chuyển động đẹp hơn, mặc dù lưu ý rằng chúng chỉ hoạt động nếu văn bản của bạn không có dòng trống ở giữa:

  • Ký tự đầu tiên của bộ đệm: {tốt hơn gg0. Nếu có các dòng trống ở giữa văn bản, bạn cũng có thể sử dụng gonó đưa bạn đến ký tự đầu tiên trong bộ đệm bất kể điều gì.

  • Last character of the buffer: } is better than G$

These also work as an argument to an operator, but note that they are character-wise movements, not line-wise movements!


H is golfier than gg
Kritixi Lithos

@KritixiLithos except that H is not reliable. It's behavior depends on the size of the visible window and where you are in the buffer. (It's remapped in V to avoid this confusion)
DJMcMayhem

2

Do calculations with the expression register

You can do calculations in both normal mode and insert mode.

Normal mode

In normal mode, if you type @= your cursor will move to the command line, where you can enter any expression. When you press enter, the result of the expression will be executed as normal mode commands.

For example, suppose you want to go to the middle column of the current line. The function call col('$') returns the number of columns in the line, so we can accomplish what by typing the following:

@=col('$')/2<CR>|

When you press enter, the cursor returns to the buffer and vim waits for an operator (like |) as though you had just entered a number. Alternatively, you could have entered this:

@=col('$')/2.'|'

...but of course that's more bytes.

Insert mode

You can use the expression register in insert mode, too, by pressing <Ctrl-r>= instead of @=. It works the same in normal mode, except the result of the expression you enter will be executed in insert mode. For example, if you typed <Ctrl-r>=col('$')<CR>, the number of columns in the current line would be inserted at the cursor as though you had typed it.

For more information on the expression register, type :help "=.

Reusing expressions

The last expression you used is stored in the expression register, "=. Typing @=<CR> in normal mode or <Ctrl-r>=<CR> in insert mode will evaluate the expression again, allowing you to use them much like macros.

Do calculations in substitutions

You can evaluate expressions when doing regular expression substitutions, too. All you have to do is begin your substitution with \=. For example, suppose you wanted to number the lines in this file:

foo
bar
baz

The function call line('.') returns the current line number, so the job is easy. Entering this:

:s/^/\=line('.').' '/g<CR>

...yields the desired result:

1 foo
2 bar
3 baz

To use captured groups in such an expression you can use the submatch() function, where e.g. submatch(0) is equivalent to \0 in an ordinary substitution, submatch(1) is equivalent to \1, etc. This eats up a lot of keystrokes, unfortunately.

For more information on expression substitution, type :help sub-replace-expression.


For your last example there are shorter ways. For example i1 <esc>bqqywjPb<C-a>@qq@q is a pure normal mode solution that is 5 bytes shorter. And if you're on unix, you could even do :%!nl. Still good tips though!
DJMcMayhem

1
My goal was to demonstrate how to use the feature, not how to number lines in the fewest keystrokes.
Jordan

1

You can directly modify the text of a macro, which can be significantly shorter than a convoluted conditional. For example, let's say you want to paste something n times, where n is user input. I first tried to do this:

qq/[1-9]<enter><c-x>``p@qq@q

Explanation:

qq                             #Start Recording
  /[1-9]<enter>                #Search for a number that isn't 0.
                <c-x>          #Decrement that number
                     ``p       #jump back to your previous location and paste.
                        @q     #Recursive call to macro 'q'
                          q@q  #Stop recording, and run the macro

This is 18 keystrokes, and a really ugly way to do it. Instead, go to the location of that number, and do this:

Ap<esc>"qdd@q

Explanation:

Ap<esc>                 #Append a 'p' to the end of the current line.
       "qdd             #Delete the current line into register q
           @q           #Run macro q.

This is 9 keystrokes, a huge improvement.

Edit:

Even shorter is to run the macro for your number, and then type your command. For example:

"qdd@qp

Explanation:

"qdd         #Delete the current line into register q
    @q       #Run register q
      p      #Paste

7 keytstrokes.


1
1. Use D, not dd. 2. If the command doesn't involve registers, you can make it even shorter. For example, if you want to repeat the character x as many times as the number under the cursor, instead of "qD@qix<esc>, use D@"ix<esc>.
Doorknob
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.