Советы по игре в гольф в vim

32

Я недавно понял, как vim отлично для игры в гольф, особенно для . Кроме того, в соответствии с мета vim, по крайней мере, является вполне приемлемым «языком программирования», то есть для сферы действия этого сайта.

Какие общие советы у вас есть для игры в гольф в Vim? Я ищу идеи, которые могут быть применены к задачам кода-гольфа и которые, по крайней мере, несколько специфичны для Vim (например, «удалить комментарии» - это не ответ).

Пожалуйста, оставьте один совет за ответ.

DJMcMayhem
источник
4
Это особенно полезный вопрос для советов, потому что «Советы по игре в гольф в vim» и «Советы по эффективному использованию vim в качестве текстового редактора» - это одно и то же.
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, но оно может варьироваться).

DJMcMayhem
источник
1
Если вызов определенно связан с редактором гольфа (и, следовательно, обычно набирается при нажатии клавиш), заглавная буква - это тоже два нажатия клавиш (как, $впрочем, и так, по крайней мере, что-то Cи Dсохранится).
Мартин Эндер
1
При наборе нажатий клавиш мне неясно, что последовательные буквы, для которых требуется клавиша Shift, учитывают клавишу Shift только один раз на группу, так как вы можете (по крайней мере, в практических целях) удерживать ее, пока вы нажимаете другие клавиши.
Алекс А.
6
@AlexA. Лично я считаю, что модификаторы не должны учитываться. Может быть, нам нужен мета-пост об этом ...
DJMcMayhem
Gи ggне эквивалентны. Первый идет в конец буфера, а второй - в начало.
Джордан
@ Джордан Это хороший момент. Я имел в виду, что они одинаковы при подсчете, например 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 с

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.
DJMcMayhem
источник
8

Есть более укороченные версии бывших команд, которые вы думаете. Например, вы, вероятно, уже знали, что :globalможет быть сокращено до :g, но знаете ли вы, что :nnoremapэквивалентно:nn ?

Это хорошая идея, чтобы запустить :h :fooвсе команды ex, которые вы используете в своем ответе, чтобы увидеть, если есть более короткая версия.

Дверная ручка
источник
6
:%s/\n//g

это всегда эквивалентно

:%s/\n//

что также эквивалентно

:%s/\n

достаточно удивительно. (Как правило, без каких-либо флагов последняя косая черта в :sвыражении никогда не требуется.)

Дверная ручка
источник
2
Это работает для новой строки, но не работает для любого символа, который может появляться более одного раза в строке. Например :%s/x, не удаляет все вхождения x, только первое в каждой строке.
DJMcMayhem
1
Вы также можете использовать, :&&чтобы повторить команду замены и ее флаги.
DJMcMayhem
6

Допустим, вы находитесь в режиме вставки и хотите сделать одну команду в обычном режиме. Вы могли бы написать это так:

isome_text<esc><foobar>gisome_more_text

Не делай так. Вместо этого используйте <C-o>, который выполняет одну обычную команду, а затем немедленно возвращается в режим вставки.

isome_text<C-o><foobar>some_more_text
DJMcMayhem
источник
Я не думаю, что эти места также необходимы
Фонд Иск Моники
@QPaysTaxes Вы правы, они не правы. Я думал, что это сделает его более читабельным. Я отредактирую это.
DJMcMayhem
Вам не нужно <CR>после, <foobar>чтобы отправить команду?
Фонд Моники иск
@QPaysTaxes Только если это бывшая команда или поиск. (Например , любая команда , начиная с :, /или ?)
DJMcMayhem
О, мой плохой. Я перепутал командный и нормальный режимы. Круто: D
финансировать иск Моники
5

Есть три оператора "изменения регистра",

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

Так как это операторы, они принимают движение, поэтому для преобразования текущего символа в нижний регистр вы должны использовать

gul

Вот тут-то и начинается забавный трюк. :) Если вы хотите изменить регистр отдельного символа или текущей строки, в визуальном режиме он будет на байт короче. Например gul, эквивалентно

vu

И gu_(_ текущая строка) эквивалентно

Vu

Этот трюк не работает для переключения, потому что v?запускает поиск в обратном направлении в визуальном режиме (так же, как и v/в обратном направлении), так что вам нужно vg?вместо этого. Однако здесь вы можете использовать ~оператор, чтобы сэкономить еще больше байтов! (Спасибо @Doorknob за указание на это)

Вы можете увидеть этот трюк в действии на моем ответе vim здесь , и на эквивалентном ответе V на и.

DJMcMayhem
источник
1
Не забудьте ~, что переключает регистр символа под курсором и перемещает один вправо!
Дверная ручка
5

Алфавит в 10 нажатий клавиш

Вся заслуга в этой технике принадлежит Линн, которая впервые использовала его в этом ответе . Я пишу это здесь для потомков.

Используйте следующие десять нажатий клавиш, чтобы восстановить строчный алфавит:

:h<_␍jjYZZ

(Где возврат каретки, т. Е. Клавиша ввода.)

объяснение

:h<_␍открывает раздел справки v_b_<_example(пример визуального блочного выделения), в котором содержится текст abcdefghijklmnopqrstuvwyxz. jjYперемещается вниз к этой строке и дергает ее, затем ZZзакрывает окно справки.

Иордания
источник
4

Знай свои регистры

Смахивание или удаление текста в конкретном регистре (например "aY), чтобы использовать его позже, не всегда необходимо. Vim имеет несколько регистров, которые автоматически заполняются субъектами различных команд. Напечатайте, :help registersчтобы увидеть их все, но вот несколько конкретных замечаний:

  • Безымянный регистр: ""- последний текст, который был вырван или удален.

  • Нумерованный регистр "0- последний текст, который был вырван.

  • Нумерованные регистры "1- "9- последний текст, который был удален, если в нем не было менее одной строки. При каждом "1заполнении его предыдущее содержимое сдвигается на "2и т. Д.

  • Маленький регистр удаления: "-- последний текст короче, чем одна строка, которая была удалена.

  • Последний вставленный текст: ".

В частности, "-и "1регистры могут быть Полезен, что позволяет удалить текст с , например , ddв "1реестр и удалить какой - либо другой текст с Dв"- (конечно, семантика не идентичны, но часто они не должны быть ).

Все регистры могут быть немного сложными для отслеживания, но вы можете увидеть содержимое всех своих регистров в любое время, набрав :registers.

Иордания
источник
3

Это появилось в чате раньше, поэтому я подумал, что я мог бы также опубликовать его как полный совет.

<C-a>и <C-x>увеличивать и уменьшать следующий номер в строке. Это чрезвычайно полезная функция для простой математики, но она также позволяет аккуратно взломать.

Допустим, вам нужно перейти к следующему номеру. Например, нам нужно изменить

I need 2 spell better

в

I need to spell better

Очевидный способ - перейти к 2, а затем выполнить:

sto                "Synonymous with 'clto'

Так как это короче

:s/2/to<cr>

Есть много разных способов перейти к 2. Например,

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

Как и многие другие способы.

Это все 2 (или более) нажатия клавиш. Однако, так <C-a>и <C-x>не только цифры увеличения / уменьшения, но и перейти к следующему номеру, мы можем взять байты выключения с

<C-a>sto
DJMcMayhem
источник
3

Гольф движений

Часто, если вы работаете с блоком текста (особенно в задачах ), вам необходимо перейти к первому или последнему символу в буфере. Gи ggдовольно хорошо, но есть некоторые раздражающие вещи. Например, чтобы получить последний символ, вам нужно G$и ggне обязательно ставить вас в первый столбец, если есть начальные пробелы. Вот некоторые более приятные движения, хотя обратите внимание, что они работают, только если ваш текст не имеет пустых строк в середине:

  • Первый символ буфера: {лучше чем gg0. Если в середине текста есть пустые строки, вы также можете использовать, goчто приведет вас к первому символу в буфере, несмотря ни на что.

  • Последний символ буфера: }лучше чемG$

Они также работают в качестве аргумента для оператора, но обратите внимание, что это движения персонажа, а не движения линии!

DJMcMayhem
источник
HГольф больше, чемgg
Kritixi Lithos
@KritixiLithos, кроме этого H, не является надежным. Его поведение зависит от размера видимого окна и от того, где вы находитесь в буфере. (Это переназначено в V, чтобы избежать этой путаницы)
DJMcMayhem
2

Делать вычисления с регистром выражений

Вы можете делать расчеты как в обычном режиме, так и в режиме вставки.

Нормальный режим

В обычном режиме, если вы печатаете @= курсор переместится в командную строку, где вы можете ввести любое выражение. Когда вы нажмете ввод, результат выражения будет выполнен как команды нормального режима.

Например, предположим, что вы хотите перейти к среднему столбцу текущей строки. Вызов функции col('$')возвращает количество столбцов в строке, поэтому мы можем сделать это, набрав следующее:

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

Когда вы нажимаете ввод, курсор возвращается в буфер, и vim ждет оператора (например |), как будто вы только что ввели число. В качестве альтернативы, вы могли бы ввести это:

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

... но, конечно, это больше байтов.

Режим вставки

Вы также можете использовать регистр выражений в режиме вставки, нажав <Ctrl-r>=вместо @=. Он работает так же в обычном режиме, за исключением того, что результат ввода выражения будет выполняться в режиме вставки. Например, если вы набрали<Ctrl-r>=col('$')<CR> , число столбцов в текущей строке будет вставлено в курсор, как если бы вы ввели его.

Для получения дополнительной информации о регистре выражений введите :help "=.

Повторное использование выражений

Последнее использованное вами выражение сохраняется в регистре выражений "=. Ввод @=<CR>в обычном режиме или <Ctrl-r>=<CR>в режиме вставки оценит выражение снова, что позволит вам использовать их так же, как макросы.

Делать расчеты в подстановках

Вы также можете оценивать выражения при выполнении подстановок регулярных выражений. Все, что вам нужно сделать, это начать замену \=. Например, предположим, что вы хотите пронумеровать строки в этом файле:

foo
bar
baz

Вызов функции line('.')возвращает текущий номер строки, поэтому задание легко. Ввод этого:

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

... дает желаемый результат:

1 foo
2 bar
3 baz

Чтобы использовать захваченные группы в таком выражении, вы можете использовать submatch()функцию, которая, например submatch(0), эквивалентна \0обычной замене, submatch(1)эквивалентна и \1т. Д. Это, к сожалению, израсходует много нажатий клавиш.

Для получения дополнительной информации о замене выражений введите :help sub-replace-expression.

Иордания
источник
Для вашего последнего примера есть более короткие пути. Например i1 <esc>bqqywjPb<C-a>@qq@q, это чисто нормальное решение, которое на 5 байт короче. И если вы на Unix, вы могли бы даже сделать :%!nl. Тем не менее, хорошие советы, хотя!
DJMcMayhem
1
Моя цель состояла в том, чтобы продемонстрировать, как использовать эту функцию, а не как нумеровать строки при наименьшем количестве нажатий клавиш.
Джордан
1

Вы можете напрямую изменить текст макроса, который может быть значительно короче, чем сложный условный. Например, допустим, вы хотите вставить что-то n раз, где n - пользовательский ввод. Сначала я попытался сделать это:

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

Объяснение:

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

Это 18 нажатий клавиш, и это очень уродливый способ сделать это. Вместо этого перейдите к местоположению этого номера и сделайте следующее:

Ap<esc>"qdd@q

Объяснение:

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

Это 9 нажатий клавиш, огромное улучшение.

Редактировать:

Еще короче - запустить макрос для вашего номера, а затем набрать вашу команду. Например:

"qdd@qp

Объяснение:

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

7 нажатий клавиш.

DJMcMayhem
источник
1
1. Используйте D, а не dd. 2. Если команда не включает регистры, вы можете сделать ее еще короче. Например, если вы хотите , чтобы повторить символ xстолько раз , как число под курсором, а "qD@qix<esc>, использования D@"ix<esc>.
Дверная ручка