เคล็ดลับสำหรับการเล่นกอล์ฟในกลุ่ม


32

ฉันได้ตระหนักถึงเมื่อเร็ว ๆ นี้ว่าเป็นกลุ่มทำงานที่ดีสำหรับการเล่นกอล์ฟโดยเฉพาะอย่างยิ่งสำหรับKolmogorovนอกจากนี้ตามmeta vim เป็น 'ภาษาการเขียนโปรแกรม' ที่ยอมรับได้อย่างสมบูรณ์สำหรับขอบเขตของเว็บไซต์นี้นั่นคือ

คุณมีเคล็ดลับอะไรบ้างสำหรับการเล่นกอล์ฟใน Vim? ฉันกำลังมองหาความคิดเห็นที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟและอย่างน้อยก็ค่อนข้างเฉพาะกับ Vim (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ)

กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ


4
นี่เป็นคำถามเคล็ดลับที่มีประโยชน์โดยเฉพาะอย่างยิ่งเพราะ "เคล็ดลับสำหรับการเล่นกอล์ฟเป็นกลุ่ม" และ "เคล็ดลับสำหรับการใช้เสียงเรียกเข้าอย่างมีประสิทธิภาพในฐานะเครื่องมือแก้ไขข้อความ" นั้นเป็นสิ่งเดียวกัน
DLosc

คำตอบ:


15

ระวังตัวแปรที่เป็นตัวพิมพ์ใหญ่ของคำสั่งทั่วไป วิธีนี้สามารถประหยัดการกดแป้นพิมพ์เพียงครั้งเดียวในบริบทจำนวนมาก ตัวอย่างเช่น:

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

อีกอันหนึ่งคือการใช้Gแทนggแต่ถ้าคุณใช้การนับ! ตัวอย่างเช่นไม่มีการนับggย้ายไปที่จุดเริ่มต้นและGย้ายไปยังจุดสิ้นสุด แต่ด้วยการนับพวกเขาทั้งสองย้ายไปยังบรรทัดที่คุณระบุเพื่อให้5Gสั้นกว่า 5gg แต่เทียบเท่ากับ

อีกสิ่งหนึ่งคือใช้Hแทนggแต่เป็นสิ่งสำคัญที่จะต้องทราบว่าวิธีนี้ใช้ได้เฉพาะในกรณีที่คุณสามารถรับประกันได้ว่าอินพุตใด ๆ จะไม่ใช้เวลาเกินจำนวนแถวเริ่มต้น (ฉันเชื่อว่านี่คือ 24 แต่อาจแตกต่างกัน)


1
หากความท้าทายโดยเฉพาะการแก้ไขกอล์ฟ (และโดยปกติแล้วจะได้คะแนนจากการกดแป้นพิมพ์) ตัวอักษรตัวพิมพ์ใหญ่คือการกดแป้นสองครั้งเช่นกัน (เช่น$กันดังนั้นอย่างน้อยCและDจะบันทึกบางอย่าง)
Martin Ender

1
สิ่งที่ฉันยังไม่ชัดเจนเกี่ยวกับการให้คะแนนในการกดแป้นเป็นตัวอักษรต่อเนื่องที่ต้องใช้ปุ่ม Shift จะนับเฉพาะปุ่ม Shift หนึ่งครั้งต่อหนึ่งกลุ่มเนื่องจากคุณสามารถ (อย่างน้อยก็เพื่อจุดประสงค์ในทางปฏิบัติ) ค้างไว้ในขณะที่คุณกดปุ่มอื่น ๆ
Alex A.

6
@AlexA. Personallly, I think modifiers shouldn't count. Maybe we need a meta post on this...
DJMcMayhem

G and gg are not equivalent. The former goes to the end of the buffer and the latter goes to the beginning.
Jordan

@Jordan That's a good point. I meant they're the same when given a count, e.g. 5G is equivalent to 5gg. I'll add some more details about that point.
DJMcMayhem

11

Anytime a command fails, it will make a ding noise, which will cancel the current macro. You can (ab)use this to create a crude form of loop. For example, if you want to repeat the keystrokes <foobar> until your buffer has less than 3 lines in it. You can do

qq<foobar>3G``@qq

which means:

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

It's important to note that if you are testing this in a vim session, the @q might have unintended side effects, since macros are loaded from .vim_profile. You can get around this a couple different ways. Probably the best workaround is to launch vim with

vim -i NONE

You could also delete your .viminfo.

If you have already launched vim, you can type

qqq

at the beginning to zero the macro out.

Other conditions you can replace the 3G with are

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

or

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

8

There are more shortened versions of ex commands that you think. For example, you probably already knew that :global can be shortened to :g, but did you know that :nnoremap is equivalent to :nn?

It's a good idea to run :h :foo on all the ex commands you're using in your answer to see if there's a shorter version.


6
:%s/\n//g

is always equivalent to

:%s/\n//

which happens to also be equivalent to

:%s/\n

surprisingly enough. (In general, without any flags, the last slash in a :s expression is never necessary.)


2
This works for newline, but doesn't work for any character that could appear more than once in a line. For example :%s/x doesn't remove every occurrence of x, just the first one on each line.
DJMcMayhem

1
You can also use :&& to repeat a substitute command and it's flags.
DJMcMayhem

6

Let's say you're in insert mode, and you want to make a single normal mode command. You might write that like this:

isome_text<esc><foobar>gisome_more_text

Don't do it that way. Instead, use <C-o>, which executes a single normal command then immediately returns to insert mode.

isome_text<C-o><foobar>some_more_text

I don't think those spaces are necessary either
Fund Monica's Lawsuit

@QPaysTaxes You're right, they aren't. I thought it would make it more readable. I'll edit that.
DJMcMayhem

You don't need a <CR> after <foobar> to send the command?
Fund Monica's Lawsuit

@QPaysTaxes Only if it's an ex command or a search. (E.g. any command starting with a :, /, or ?)
DJMcMayhem

Oh, my bad. I confused command and normal modes. Cool :D
Fund Monica's Lawsuit

5

There are three "change case" operators,

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

Since these are operators, they take a motion, so to convert the current character to lowercase you would use

gul

Here's where the fun trick comes in. :) If you want to change the case of a single character or the current line, it's a byte shorter in visual mode. For example gul is equivalent to

vu

And gu_ (_ is current line) is equivalent to

Vu

This trick does not work for toggling, because v? triggers a backwards search in visual mode, (just like v/ but moving in the opposite direction) so you need vg? instead. However, here's where you can use the ~ operator, to save even more bytes! (Thanks @Doorknob for pointing this out)

You can see this trick in action on my vim answer here, and on the equivalent V answer on the and post.


1
Don't forget ~, which toggles the case of the character under the cursor and moves one to the right!
Doorknob

5

The alphabet in 10 keystrokes

All credit for this technique goes to Lynn, who first used it in this answer. I'm writing it up here for posterity.

Use the following ten keystrokes to yank the lowercase alphabet:

:h<_␍jjYZZ

(Where is a carriage return, i.e. the Enter key.)

Explanation

:h<_␍ opens the help section v_b_<_example (an example of visual blockwise selection), which happens to contain the text abcdefghijklmnopqrstuvwyxz. jjY moves down to that line and yanks it, then ZZ closes the help window.


4

Know your registers

Yanking or deleting text into a specific register (e.g. "aY) to use it later isn't always necessary. Vim has several registers that are automatically populated with the subjects of various commands. Type :help registers to see them all, but here's a few of particular note:

  • Unnamed register: "" - The last text that was yanked or deleted.

  • Numbered register "0 - The last text that was yanked.

  • Numbered registers "1"9 - The last text that was deleted unless it was less than one line. Each time "1 is filled its previous contents are shifted to "2 and so on.

  • Small delete register: "- - The last text shorter than one line that was deleted.

  • Last inserted text: ".

In particular, the "- and "1 registers can be useful together, enabling you to delete some text with e.g. dd into the "1 register and delete some other text with D into the "- (of course, the semantics aren't identical, but often they don't need to be).

All of the registers can be a little tough to keep track of, but you can see the contents of all of your registers at any time by typing :registers.


3

This came up in chat earlier, so I thought I might as well post it as a full tip.

<C-a> and <C-x> increment and decrement the next number on the line. This is an extremely useful feature for some simple math, but it also allows for a neat little hack.

Let's say you need to jump to the next number. For example, we need to change

I need 2 spell better

to

I need to spell better

The obvious way is to jump to the 2, then do:

sto                "Synonymous with 'clto'

Since this is shorter than

:s/2/to<cr>

There are many different ways to jump to the 2. For example,

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

As well as many other ways.

These are all 2 (or more) keystrokes. However, since <C-a> and <C-x> not only increment/decrement numbers, but also jump to the next number, we can take a byte off with

<C-a>sto

3

Golfier movements

Frequently if you're working with a block of text (especially in challenges), you'll need to move to the first or last character in the buffer. G and gg are pretty good, but there are some annoying things. For example, to get the last character, you need G$ and gg will not necessarily put you on the first column if there's leading whitespace. Here are some nicer movements, although note that they only work if your text doesn't have empty lines in the middle of it:

  • First character of the buffer: { is better than gg0. If there are empty lines in the middle of the text, you can also use go which brings you to the first character in the buffer no matter what.

  • 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.