在vim中打高尔夫球的技巧


32

最近,我意识到vim如何很好地打高尔夫球,尤其是对于。同样,至少对于本网站而言,根据meta vim,它是一种完全可以接受的“编程语言”。

您在Vim打高尔夫球有哪些一般提示?我正在寻找可以应用于代码高尔夫球问题的想法,并且这些想法至少也特定于Vim(例如,“删除注释”不是答案)。

请为每个答案发布一个提示。


4
这是一个特别有用的提示问题,因为“在vim中打高尔夫球的技巧”和“在文本编辑器中有效使用vim的技巧”基本上是同一回事。
DLosc

Answers:


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
如果具体挑战编辑高尔夫球(因此通常由按键得分)大写字母是两次击键,以及(所以是$的,所以至少CD将保存的东西)。
Martin Ender

1
关于击键的得分,我不清楚的是是否需要换档键的连续字母每组仅对换档键计数一次,因为您可以(至少出于实际目的)在按下其他键时按住该键。
Alex A.

6
@AlexA。就个人而言,我认为修饰符不应该算在内。也许我们需要有关此的元信息...
DJMcMayhem

G并且gg不是等效的。前者转到缓冲区的末尾,后者转到开头。
乔丹

@Jordan很好。我的意思是,当计数时它们是相同的,例如5G等于5gg。我将添加有关该点的更多详细信息。
DJMcMayhem

11

每当命令失败时,都会发出嗡嗡声,这将取消当前宏。您可以(ab)使用它创建循环的粗略形式。例如,如果要重复击键,<foobar>直到缓冲区中的行数少于3行。你可以做

qq<foobar>3G``@qq

意思是:

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

请务必注意,如果您在vim会话中对此进行测试,则@q可能会产生意想不到的副作用,因为宏是从加载的.vim_profile。您可以通过几种不同的方式解决此问题。最好的解决方法可能是启动带有

vim -i NONE

您也可以删除自己的.viminfo

如果您已经启动了vim,则可以键入

qqq

在开始时将宏清零。

可以替换3G的其他条件是

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

要么

<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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.