Dicas para jogar golfe no vim

32

Recentemente, percebi como o vim funciona muito bem no golfe, especialmente na . Além disso, de acordo com o meta vim, é uma 'linguagem de programação' perfeitamente aceitável pelo menos para o escopo deste site.

Que dicas gerais você tem para jogar golfe no Vim? Estou procurando idéias que possam ser aplicadas a problemas de código-golfe e que também sejam pelo menos um pouco específicas para o Vim (por exemplo, "remover comentários" não é uma resposta).

Poste uma dica por resposta.

DJMcMayhem
fonte
4
Esta é uma pergunta de dicas particularmente útil porque "Dicas para jogar golfe no vim" e "Dicas para usar o vim com eficiência como um editor de texto" são basicamente a mesma coisa.
DLosc 28/10

Respostas:

15

Esteja ciente das variantes maiúsculas de comandos comuns. Isso pode salvar trivialmente um pressionamento de tecla em muitos contextos. Por exemplo:

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

Outro é usar em Gvez de gg, mas somente se você usar uma contagem! Por exemplo, sem contagem, ggmove-se para o início e Gmove-se para o fim. No entanto, com uma contagem, os dois se movem para a linha que você especificar, portanto, 5Gé mais curto do que mas equivalente a 5gg .

Outra é usar Hno lugar de gg, mas é importante observar que isso só funciona se você puder garantir que qualquer entrada não ocupe mais do que o número padrão de linhas (acredito que seja 24, mas pode variar).

DJMcMayhem
fonte
1
Se um desafio é especificamente o editor de golfe (e, portanto, geralmente marcado com pressionamentos de tecla), uma letra maiúscula também possui dois pressionamentos de tecla (no $entanto, pelo menos, portanto, Ce Disso salvaria algo).
Martin Ender
1
Algo que não estou claro ao pontuar nas teclas é se letras consecutivas que exigem a tecla Shift contam apenas a tecla Shift uma vez por grupo, já que você pode (pelo menos por motivos práticos) pressioná-la enquanto pressiona as outras teclas.
Alex A.
6
@AlexA. Pessoalmente, acho que os modificadores não devem contar. Talvez precisemos de um meta post sobre isso ...
DJMcMayhem
Ge ggnão são equivalentes. O primeiro vai para o fim do buffer e o segundo vai para o começo.
Jordânia
@ Jordan Esse é um bom ponto. Eu quis dizer que eles são iguais quando recebem uma contagem, por exemplo, 5Gé equivalente a 5gg. Vou adicionar mais alguns detalhes sobre esse ponto.
DJMcMayhem
11

Sempre que um comando falhar, ele emitirá um ruído de toque, que cancelará a macro atual. Você pode (ab) usar isso para criar uma forma bruta de loop. Por exemplo, se você deseja repetir as teclas pressionadas <foobar>até que seu buffer tenha menos de 3 linhas. Você pode fazer

qq<foobar>3G``@qq

que significa:

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

É importante observar que, se você estiver testando isso em uma sessão do vim, @qpoderá ter efeitos colaterais indesejados, pois as macros são carregadas .vim_profile. Você pode contornar isso de duas maneiras diferentes. Provavelmente, a melhor solução alternativa é lançar o vim com

vim -i NONE

Você também pode excluir o seu .viminfo.

Se você já iniciou o vim, pode digitar

qqq

no início para zerar a macro.

Outras condições com as quais você pode substituir o 3G são:

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

ou

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

Existem versões mais reduzidas dos comandos ex que você pensa. Por exemplo, você provavelmente já sabia que isso :globalpode ser reduzido :g, mas você sabia que isso :nnoremapé equivalente a :nn?

É uma boa ideia executar :h :footodos os comandos ex que você está usando na sua resposta para ver se há uma versão mais curta.

Maçaneta da porta
fonte
6
:%s/\n//g

é sempre equivalente a

:%s/\n//

o que também é equivalente a

:%s/\n

surpreendentemente. (Em geral, sem nenhum sinalizador, a última barra em uma :sexpressão nunca é necessária.)

Maçaneta da porta
fonte
2
Isso funciona para nova linha, mas não para caracteres que possam aparecer mais de uma vez em uma linha. Por exemplo :%s/x, não remove todas as ocorrências de x, apenas a primeira em cada linha.
DJMcMayhem
1
Você também pode usar :&&para repetir um comando substituto e seus sinalizadores.
DJMcMayhem
6

Digamos que você esteja no modo de inserção e deseje fazer um único comando no modo normal. Você pode escrever assim:

isome_text<esc><foobar>gisome_more_text

Não faça assim. Em vez disso, use <C-o>, que executa um único comando normal e retorna imediatamente ao modo de inserção.

isome_text<C-o><foobar>some_more_text
DJMcMayhem
fonte
Também não acho que esses espaços sejam necessários.
Fund Monica's Lawsuit
@QPaysTaxes Você está certo, eles não estão. Eu pensei que isso tornaria mais legível. Eu vou editar isso.
DJMcMayhem
Você não precisa de um <CR>depois <foobar>para enviar o comando?
Fund Monica's Lawsuit
@QPaysTaxes Somente se for um comando ex ou uma pesquisa. (Por exemplo, qualquer comando que comece com a :, /ou ?)
DJMcMayhem
Oh culpa minha. Confundi comando e modos normais. Cool: D
Fund Monica's Lawsuit
5

Existem três operadores "caso de mudança",

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

Como são operadores, eles fazem um movimento, portanto, para converter o caractere atual em minúsculas, você usaria

gul

É aqui que entra o truque divertido. :) Se você deseja alterar o caso de um único caractere ou a linha atual, é um byte mais curto no modo visual. Por exemplo, gulé equivalente a

vu

E gu_(_ é a linha atual) é equivalente a

Vu

Esse truque não funciona para alternar, porque v?aciona uma pesquisa para trás no modo visual (exatamente como se v/move na direção oposta), então você precisa vg?. No entanto, é aqui que você pode usar o ~operador para salvar ainda mais bytes! (Obrigado @ Doorknob por apontar isso)

Você pode ver esse truque em ação na minha resposta vim aqui e na resposta equivalente V no post e.

DJMcMayhem
fonte
1
Não se esqueça ~, que alterna o caso do personagem sob o cursor e move um para a direita!
Maçaneta
5

O alfabeto em 10 pressionamentos de teclas

Todo o crédito por essa técnica é atribuído a Lynn, que a usou pela primeira vez nesta resposta . Estou escrevendo aqui para a posteridade.

Use as seguintes dez teclas para puxar o alfabeto em minúsculas:

:h<_␍jjYZZ

(Onde é um retorno de carro, ou seja, a tecla Enter.)

Explicação

:h<_␍abre a seção de ajuda v_b_<_example(um exemplo de seleção visual em blocos), que contém o texto abcdefghijklmnopqrstuvwyxz. jjYdesce para essa linha e a puxa e depois ZZfecha a janela de ajuda.

Jordânia
fonte
4

Conheça seus registros

Arrancar ou excluir texto em um registro específico (por exemplo "aY) para usá-lo mais tarde nem sempre é necessário. O Vim possui vários registros que são preenchidos automaticamente com os assuntos de vários comandos. Digite :help registerspara ver todos eles, mas aqui estão algumas observações particulares:

  • Registro sem nome: ""- O último texto que foi arrancado ou excluído.

  • Registro numerado "0- o último texto que foi arrancado.

  • Registradores numerados "1- "9- O último texto que foi excluído, a menos que tenha menos de uma linha. Cada vez que "1é preenchido, seu conteúdo anterior é deslocado para "2e assim por diante.

  • Registro de exclusão pequeno: "-- O último texto menor que uma linha que foi excluída.

  • Último texto inserido: ".

Em particular, os registradores "-e "1podem ser úteis juntos, permitindo que você exclua algum texto com, por exemplo, ddno "1registro e exclua algum outro texto com Dno "-(é claro, a semântica não é idêntica, mas geralmente não precisa ser usada). )

Todos os registros podem ser um pouco difíceis de acompanhar, mas você pode ver o conteúdo de todos os registros a qualquer momento digitando :registers.

Jordânia
fonte
3

Isso apareceu no bate-papo mais cedo, então pensei em publicá-lo como uma dica completa.

<C-a>e <C-x>aumente e diminua o próximo número na linha. Este é um recurso extremamente útil para algumas contas simples, mas também permite um pequeno truque.

Digamos que você precise pular para o próximo número. Por exemplo, precisamos mudar

I need 2 spell better

para

I need to spell better

A maneira óbvia é pular para o 2 e depois:

sto                "Synonymous with 'clto'

Como isso é mais curto que

:s/2/to<cr>

Existem muitas maneiras diferentes de pular para o 2. Por exemplo,

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

Assim como muitas outras maneiras.

Estes são todos os 2 (ou mais) pressionamentos de tecla. No entanto, uma vez <C-a>e <C-x>não apenas números de aumentar / diminuir, mas também saltar para o próximo número, podemos tomar um byte fora com

<C-a>sto
DJMcMayhem
fonte
3

Movimentos golfistas

Freqüentemente, se você estiver trabalhando com um bloco de texto (especialmente em desafios de ), precisará passar para o primeiro ou o último caractere no buffer. Ge ggsão muito bons, mas existem algumas coisas irritantes. Por exemplo, para obter o último caractere, você precisa G$e ggnão o colocará necessariamente na primeira coluna, se houver espaço em branco à esquerda. Aqui estão alguns movimentos mais agradáveis, embora observe que eles só funcionam se o seu texto não tiver linhas vazias no meio:

  • Primeiro caractere do buffer: {é melhor que gg0. Se houver linhas vazias no meio do texto, você também pode usar o goque leva ao primeiro caractere no buffer, não importa o quê.

  • Último caractere do buffer: }é melhor queG$

Eles também funcionam como argumento para um operador, mas observe que são movimentos de caráter, não de linha!

DJMcMayhem
fonte
Hé mais golfista quegg
Kritixi Lithos
@KritixiLithos, exceto que Hnão é confiável. Seu comportamento depende do tamanho da janela visível e de onde você está no buffer. (É mapeado de novo em V para evitar esta confusão)
DJMcMayhem
2

Faça cálculos com o registro de expressão

Você pode fazer cálculos no modo normal e no modo de inserção.

Modo normal

No modo normal, se você digitar, @=o cursor se moverá para a linha de comando, onde é possível inserir qualquer expressão. Quando você pressiona enter, o resultado da expressão será executado como comandos no modo normal.

Por exemplo, suponha que você queira ir para a coluna do meio da linha atual. A chamada de função col('$')retorna o número de colunas na linha, para que possamos realizar o que, digitando o seguinte:

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

Quando você pressiona enter, o cursor retorna ao buffer e o vim aguarda um operador (como |) como se você tivesse acabado de inserir um número. Como alternativa, você poderia ter digitado isso:

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

... mas é claro que são mais bytes.

Modo de inserção

Você também pode usar o registro de expressão no modo de inserção pressionando em <Ctrl-r>=vez de @=. Funciona da mesma maneira no modo normal, exceto que o resultado da expressão inserida será executado no modo de inserção. Por exemplo, se você digitou <Ctrl-r>=col('$')<CR>, o número de colunas na linha atual seria inserido no cursor como se você a tivesse digitado.

Para obter mais informações sobre o registro de expressão, digite :help "=.

Reutilizando expressões

A última expressão que você usou é armazenada no registro de expressões "=,. Digitar @=<CR>no modo normal ou <Ctrl-r>=<CR>no modo de inserção avaliará a expressão novamente, permitindo que você as use de maneira semelhante às macros.

Faça cálculos em substituições

Você também pode avaliar expressões ao fazer substituições de expressões regulares. Tudo o que você precisa fazer é iniciar sua substituição \=. Por exemplo, suponha que você deseje numerar as linhas neste arquivo:

foo
bar
baz

A chamada de função line('.')retorna o número da linha atual, facilitando o trabalho. Inserindo isso:

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

... produz o resultado desejado:

1 foo
2 bar
3 baz

Para usar grupos capturados em uma expressão como essa, você pode usar a submatch()função, onde, por exemplo, submatch(0)é equivalente a \0uma substituição comum, submatch(1)é equivalente a \1etc. Isso, infelizmente, consome muitas teclas.

Para mais informações sobre a substituição expressão, tipo :help sub-replace-expression.

Jordânia
fonte
Para o seu último exemplo, existem maneiras mais curtas. Por exemplo, i1 <esc>bqqywjPb<C-a>@qq@qé uma solução de modo normal puro que é 5 bytes mais curta. E se você estiver no unix, você pode até fazer :%!nl. Ainda boas dicas!
DJMcMayhem
1
Meu objetivo era demonstrar como usar o recurso, não como numerar linhas com o menor número de pressionamentos de tecla.
Jordânia
1

Você pode modificar diretamente o texto de uma macro, que pode ser significativamente menor que um condicional complicado. Por exemplo, digamos que você deseja colar algo n vezes, em que n é a entrada do usuário. Eu tentei primeiro fazer isso:

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

Explicação:

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

São 18 teclas digitadas e uma maneira realmente feia de fazer isso. Em vez disso, vá para o local desse número e faça o seguinte:

Ap<esc>"qdd@q

Explicação:

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

São 9 pressionamentos de tecla, uma grande melhoria.

Editar:

Ainda mais curto é executar a macro para o seu número e digite seu comando. Por exemplo:

"qdd@qp

Explicação:

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

7 pressionamentos de tecla.

DJMcMayhem
fonte
1
1. Use D, não dd. 2. Se o comando não envolver registradores, você poderá reduzi-lo ainda mais. Por exemplo, se você deseja repetir o caractere xquantas vezes o número sob o cursor, em vez de "qD@qix<esc>, use D@"ix<esc>.
Maçaneta