Conseils pour jouer au golf à Vim

32

J'ai récemment réalisé à quel point vim fonctionne très bien pour le golf, en particulier pour la . De plus, selon meta vim est un «langage de programmation» parfaitement acceptable au moins, pour la portée de ce site, c'est-à-dire.

Quels conseils généraux avez-vous pour jouer au golf à Vim? Je recherche des idées qui peuvent être appliquées aux problèmes de code-golf et qui sont également au moins quelque peu spécifiques à Vim (par exemple, "supprimer les commentaires" n'est pas une réponse).

Veuillez poster un pourboire par réponse.

DJMcMayhem
la source
4
Il s'agit d'une question de conseils particulièrement utile car «Conseils pour jouer au golf dans vim» et «Conseils pour utiliser efficacement vim en tant qu'éditeur de texte» sont essentiellement la même chose.
DLosc

Réponses:

15

Soyez conscient des variantes majuscules des commandes courantes. Cela peut enregistrer de manière triviale une frappe dans de nombreux contextes. Par exemple:

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

Un autre est d'utiliser à la Gplace de gg, mais seulement si vous utilisez un compte! Par exemple, sans décompte, ggpasse au début et Gse termine à la fin. Cependant, avec un comptage, ils se déplacent tous les deux vers la ligne que vous spécifiez, c'est donc 5Gplus court que mais équivalent à 5gg .

Un autre est à utiliser Hà la place de gg, mais il est important de noter que cela ne fonctionne que si vous pouvez garantir qu'aucune entrée ne prendra plus que le nombre de lignes par défaut (je pense que c'est 24, mais cela peut varier).

DJMcMayhem
la source
1
Si un défi concerne spécifiquement l'éditeur de golf (et donc généralement marqué par des frappes), une lettre majuscule est également deux frappes (il en est de $même, donc au moins Cet Dsauverait quelque chose).
Martin Ender
1
Quelque chose que je ne comprends pas lorsque je note des touches est de savoir si les lettres consécutives qui nécessitent la touche Maj ne comptent la touche Maj qu'une fois par groupe, car vous pouvez (au moins à des fins pratiques) la maintenir enfoncée pendant que vous appuyez sur les autres touches.
Alex A.
6
@AlexA. Personnellement, je pense que les modificateurs ne devraient pas compter. Peut-être que nous avons besoin d'un meta post à ce sujet ...
DJMcMayhem
Get ggne sont pas équivalents. Le premier va à la fin du tampon et le second va au début.
Jordan
@Jordan C'est un bon point. Je voulais dire qu'ils sont les mêmes lorsqu'ils reçoivent un compte, par exemple 5Gest équivalent à 5gg. J'ajouterai plus de détails sur ce point.
DJMcMayhem
11

Chaque fois qu'une commande échoue, elle fait du bruit, ce qui annule la macro actuelle. Vous pouvez (ab) l'utiliser pour créer une forme de boucle brute. Par exemple, si vous souhaitez répéter les frappes <foobar>jusqu'à ce que votre mémoire tampon comporte moins de 3 lignes. Tu peux faire

qq<foobar>3G``@qq

ce qui signifie:

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

Il est important de noter que si vous testez cela dans une session vim, cela @qpeut avoir des effets secondaires imprévus, car les macros sont chargées à partir de .vim_profile. Vous pouvez contourner cela de différentes manières. La meilleure solution consiste probablement à lancer vim avec

vim -i NONE

Vous pouvez également supprimer votre .viminfo.

Si vous avez déjà lancé vim, vous pouvez taper

qqq

au début pour remettre à zéro la macro.

Les autres conditions avec lesquelles vous pouvez remplacer la 3G sont

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
la source
8

Vous pensez qu'il existe des versions plus raccourcies des commandes ex. Par exemple, vous saviez probablement déjà que cela :globalpeut être raccourci :g, mais saviez-vous que cela :nnoremapéquivaut à :nn?

C'est une bonne idée d'exécuter :h :footoutes les commandes ex que vous utilisez dans votre réponse pour voir s'il existe une version plus courte.

Poignée de porte
la source
6
:%s/\n//g

est toujours équivalent à

:%s/\n//

qui se trouve être également équivalent à

:%s/\n

assez étonnamment. (En général, sans indicateur, la dernière barre oblique d'une :sexpression n'est jamais nécessaire.)

Poignée de porte
la source
2
Cela fonctionne pour la nouvelle ligne, mais ne fonctionne pour aucun caractère qui pourrait apparaître plus d'une fois dans une ligne. Par exemple, :%s/xne supprime pas chaque occurrence de x, juste la première sur chaque ligne.
DJMcMayhem
1
Vous pouvez également utiliser :&&pour répéter une commande de substitution et ses indicateurs.
DJMcMayhem
6

Supposons que vous soyez en mode insertion et que vous souhaitiez effectuer une seule commande en mode normal. Vous pourriez écrire cela comme ceci:

isome_text<esc><foobar>gisome_more_text

Ne le faites pas comme ça. Au lieu de cela, utilisez <C-o>, qui exécute une seule commande normale, puis revient immédiatement en mode insertion.

isome_text<C-o><foobar>some_more_text
DJMcMayhem
la source
Je ne pense pas que ces espaces soient nécessaires non plus
Fund Monica's Lawsuit
@QPaysTaxes Vous avez raison, ils ne le sont pas. Je pensais que cela le rendrait plus lisible. Je vais éditer ça.
DJMcMayhem
Vous n'avez pas besoin d'un <CR>après <foobar>pour envoyer la commande?
Fund Monica's Lawsuit
@QPaysTaxes Uniquement s'il s'agit d'une commande ex ou d'une recherche. (Par exemple , une commande à partir d'un :, /ou ?)
DJMcMayhem
Oh, ma mauvaise. J'ai confondu commande et modes normaux. Cool: D
Fund Monica's Lawsuit
5

Il existe trois opérateurs de «changement de cas»,

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

Puisque ce sont des opérateurs, ils prennent un mouvement, donc pour convertir le caractère actuel en minuscules, vous utiliseriez

gul

Voici où l'astuce amusante entre en jeu. :) Si vous voulez changer la casse d'un seul caractère ou la ligne actuelle, c'est un octet plus court en mode visuel. Par exemple, guléquivaut à

vu

Et gu_(_ est la ligne actuelle) est équivalent à

Vu

Cette astuce ne fonctionne pas pour le basculement, car elle v?déclenche une recherche en arrière en mode visuel (tout comme en se v/déplaçant dans la direction opposée), vous en avez donc besoin à la vg?place. Cependant, voici où vous pouvez utiliser l' ~opérateur, pour économiser encore plus d'octets! (Merci @Doorknob de l'avoir signalé)

Vous pouvez voir cette astuce en action sur ma réponse vim ici , et sur la réponse V équivalente sur le et le post.

DJMcMayhem
la source
1
N'oubliez pas ~, ce qui fait basculer la casse du caractère sous le curseur et en déplace un vers la droite!
Poignée de porte
5

L'alphabet en 10 touches

Tout le mérite de cette technique revient à Lynn, qui l'a d'abord utilisée dans cette réponse . Je l'écris ici pour la postérité.

Utilisez les dix touches suivantes pour extraire l'alphabet minuscule:

:h<_␍jjYZZ

(Où est un retour chariot, c'est-à-dire la touche Entrée.)

Explication

:h<_␍ouvre la section d'aide v_b_<_example(un exemple de sélection visuelle par blocs), qui contient le texte abcdefghijklmnopqrstuvwyxz. jjYdescend vers cette ligne et la tire, puis ZZferme la fenêtre d'aide.

Jordanie
la source
4

Connaissez vos registres

Tirer ou supprimer du texte dans un registre spécifique (par exemple "aY) pour l'utiliser plus tard n'est pas toujours nécessaire. Vim possède plusieurs registres qui sont automatiquement remplis avec les sujets de diverses commandes. Tapez :help registerspour les voir tous, mais voici quelques remarques particulières:

  • Registre sans nom: ""- Le dernier texte qui a été retiré ou supprimé.

  • Registre numéroté "0- Le dernier texte qui a été tiré.

  • Registres numérotés "1- "9- Le dernier texte qui a été supprimé sauf s'il était inférieur à une ligne. Chaque fois qu'il "1est rempli, son contenu précédent est déplacé vers "2et ainsi de suite.

  • Petit registre de suppression: "-- Le dernier texte de moins d'une ligne qui a été supprimé.

  • Dernier texte inséré: ".

En particulier, les registres "-et "1peuvent être utiles ensemble, vous permettant de supprimer du texte avec par exemple dddans le "1registre et de supprimer un autre texte avec Ddans le "-(bien sûr, la sémantique n'est pas identique, mais souvent ils n'ont pas besoin d'être ).

Tous les registres peuvent être un peu difficiles à suivre, mais vous pouvez voir le contenu de tous vos registres à tout moment en tapant :registers.

Jordan
la source
3

Cela est apparu dans le chat plus tôt, j'ai donc pensé que je pourrais aussi bien le poster comme un conseil complet.

<C-a>et <C-x>incrémenter et décrémenter le nombre suivant sur la ligne. C'est une fonctionnalité extrêmement utile pour certains calculs simples, mais elle permet également un petit hack soigné.

Disons que vous devez passer au numéro suivant. Par exemple, nous devons changer

I need 2 spell better

à

I need to spell better

La façon la plus évidente est de passer au 2, puis de faire:

sto                "Synonymous with 'clto'

Puisque c'est plus court que

:s/2/to<cr>

Il existe de nombreuses façons de passer au 2. Par exemple,

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

Ainsi que de nombreuses autres façons.

Ce sont tous 2 (ou plus) frappes. Cependant, étant donné <C-a>que <C-x>non seulement les nombres incrémentent / décrémentent, mais sautent également au nombre suivant, nous pouvons prendre un octet avec

<C-a>sto
DJMcMayhem
la source
3

Mouvements de golfeur

Souvent, si vous travaillez avec un bloc de texte (en particulier dans défis ), vous devrez vous déplacer vers le premier ou le dernier caractère du tampon. Get ggsont assez bons, mais il y a des choses ennuyeuses. Par exemple, pour obtenir le dernier caractère, vous avez besoin G$et ggne vous placerez pas nécessairement dans la première colonne s'il y a un espace de tête. Voici quelques mouvements plus agréables, mais notez qu'ils ne fonctionnent que si votre texte n'a pas de lignes vides au milieu:

  • Premier caractère du tampon: {est meilleur que gg0. S'il y a des lignes vides au milieu du texte, vous pouvez également utiliser goce qui vous amène au premier caractère du tampon, quoi qu'il arrive .

  • Dernier caractère du tampon: }est meilleur queG$

Ceux-ci fonctionnent également comme un argument pour un opérateur, mais notez que ce sont des mouvements de caractère, pas des mouvements de ligne!

DJMcMayhem
la source
Hest plus golfeur quegg
Kritixi Lithos
@KritixiLithos sauf que ce Hn'est pas fiable. Son comportement dépend de la taille de la fenêtre visible et de l'endroit où vous vous trouvez dans le tampon. (Il est remappé en V pour éviter cette confusion)
DJMcMayhem
2

Faire des calculs avec le registre d'expression

Vous pouvez effectuer des calculs en mode normal et en mode insertion.

Mode normal

En mode normal, si vous tapez, @=votre curseur se déplacera vers la ligne de commande, où vous pourrez saisir n'importe quelle expression. Lorsque vous appuyez sur Entrée, le résultat de l'expression sera exécuté en tant que commandes en mode normal.

Par exemple, supposons que vous souhaitiez accéder à la colonne du milieu de la ligne actuelle. L'appel de fonction col('$')renvoie le nombre de colonnes de la ligne, afin que nous puissions accomplir quoi en tapant ce qui suit:

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

Lorsque vous appuyez sur entrée, le curseur revient dans le tampon et vim attend un opérateur (comme |) comme si vous veniez de saisir un nombre. Alternativement, vous auriez pu saisir ceci:

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

... mais bien sûr, c'est plus d'octets.

Mode d'insertion

Vous pouvez également utiliser le registre d'expression en mode insertion en appuyant sur <Ctrl-r>=au lieu de @=. Cela fonctionne de la même manière en mode normal, sauf que le résultat de l'expression que vous entrez sera exécuté en mode insertion. Par exemple, si vous avez tapé <Ctrl-r>=col('$')<CR>, le nombre de colonnes de la ligne actuelle serait inséré au niveau du curseur comme si vous l'aviez tapé.

Pour plus d'informations sur le registre d'expression, tapez :help "=.

Réutiliser des expressions

La dernière expression utilisée est stockée dans le registre d'expression, "=. Taper @=<CR>en mode normal ou <Ctrl-r>=<CR>en mode insertion évaluera à nouveau l'expression, vous permettant de les utiliser un peu comme des macros.

Faire des calculs par substitution

Vous pouvez également évaluer des expressions lorsque vous effectuez des substitutions d'expressions régulières. Tout ce que vous avez à faire est de commencer votre substitution par \=. Par exemple, supposons que vous vouliez numéroter les lignes de ce fichier:

foo
bar
baz

L'appel de fonction line('.')renvoie le numéro de ligne actuel, donc le travail est facile. Entrer ceci:

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

... donne le résultat souhaité:

1 foo
2 bar
3 baz

Pour utiliser des groupes capturés dans une telle expression, vous pouvez utiliser la submatch()fonction, où par exemple submatch(0)est équivalent à \0dans une substitution ordinaire, submatch(1)est équivalent à \1, etc. Cela mange beaucoup de frappes, malheureusement.

Pour plus d'informations sur la substitution d'expression, tapez :help sub-replace-expression.

Jordan
la source
Pour votre dernier exemple, il existe des moyens plus courts. Par exemple, i1 <esc>bqqywjPb<C-a>@qq@qc'est une solution en mode normal pur qui est plus courte de 5 octets. Et si vous êtes sous Unix, vous pourriez même le faire :%!nl. Encore de bons conseils!
DJMcMayhem
1
Mon objectif était de montrer comment utiliser la fonction, pas comment numéroter les lignes en un minimum de touches.
Jordan
1

Vous pouvez modifier directement le texte d'une macro, qui peut être considérablement plus court qu'un conditionnel alambiqué. Par exemple, supposons que vous souhaitiez coller quelque chose n fois, où n est l'entrée utilisateur. J'ai d'abord essayé de faire ceci:

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

Explication:

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

C'est 18 frappes, et une façon vraiment laide de le faire. Au lieu de cela, accédez à l'emplacement de ce numéro et procédez comme suit:

Ap<esc>"qdd@q

Explication:

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

Il s'agit de 9 touches, une énorme amélioration.

Modifier:

Encore plus court consiste à exécuter la macro de votre numéro, puis à taper votre commande. Par exemple:

"qdd@qp

Explication:

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

7 touches.

DJMcMayhem
la source
1
1. N'utilisez Dpas dd. 2. Si la commande n'implique pas de registres, vous pouvez la raccourcir encore plus. Par exemple, si vous souhaitez répéter le caractère xautant de fois que le nombre sous le curseur, au lieu de "qD@qix<esc>, utilisez D@"ix<esc>.
Poignée de porte