Tipps zum Golfen in vim

32

Ich habe kürzlich festgestellt, wie gut Vim für das Golfen funktioniert, insbesondere für die . Laut meta vim handelt es sich zumindest für den Umfang dieser Website um eine durchaus akzeptable Programmiersprache.

Welche allgemeinen Tipps haben Sie zum Golfen in Vim? Ich bin auf der Suche nach Ideen, die sich auf Code-Golf-Probleme anwenden lassen und die zumindest etwas spezifisch für Vim sind (z. B. "Kommentare entfernen" ist keine Antwort).

Bitte posten Sie einen Tipp pro Antwort.

DJMcMayhem
quelle
4
Dies ist eine besonders hilfreiche Frage, da "Tipps zum Golfen in vim" und "Tipps zum effizienten Verwenden von vim als Texteditor" im Grunde dasselbe sind.
DLosc

Antworten:

15

Beachten Sie die Großbuchstaben der gängigen Befehle. Dies kann in vielen Kontexten trivial ein Tastendruck einsparen. Beispielsweise:

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

Eine andere ist die Verwendung Gstatt gg, aber nur , wenn Sie eine Zählung verwenden! Beispiel: Ohne Zählung wird ggan den Anfang und Gan das Ende verschoben. Bei einer Zählung werden beide jedoch in die von Ihnen angegebene Zeile verschoben. Dies 5Gist kürzer als, aber gleichbedeutend mit 5gg .

Eine andere ist die Verwendung Hanstelle von gg, es ist jedoch wichtig zu beachten, dass dies nur funktioniert, wenn Sie garantieren können, dass keine Eingabe mehr als die Standardanzahl von Zeilen belegt (ich glaube, dies ist 24, sie kann jedoch variieren).

DJMcMayhem
quelle
1
Wenn eine Herausforderung speziell für das Editieren von Golf besteht (und daher normalerweise durch Tastenanschläge erzielt wird), besteht ein Großbuchstabe ebenfalls aus zwei Tastenanschlägen (so ist es $aber zumindest Cund Dwürde etwas sparen).
Martin Ender
1
Bei der Eingabe von Tastenanschlägen ist mir nicht klar, ob aufeinanderfolgende Buchstaben, für die die Umschalttaste erforderlich ist, die Umschalttaste nur einmal pro Gruppe zählen, da Sie sie (zumindest aus praktischen Gründen) gedrückt halten können, während Sie die anderen Tasten drücken.
Alex A.
6
@AlexA. Persönlich denke ich, dass Modifikatoren nicht zählen sollten. Vielleicht brauchen wir einen Meta-Beitrag dazu ...
DJMcMayhem
Gund ggsind nicht gleichwertig. Ersteres geht zum Ende des Puffers und letzteres zum Anfang.
Jordanien
@Jordan Das ist ein guter Punkt. Ich meinte, sie sind gleich, wenn sie gezählt werden, z . B. 5Gäquivalent zu 5gg. Ich werde einige Details zu diesem Punkt hinzufügen.
DJMcMayhem
11

Jedes Mal, wenn ein Befehl fehlschlägt, wird ein Klingelton ausgegeben, der das aktuelle Makro löscht. Sie können dies (ab) verwenden, um eine grobe Form einer Schleife zu erstellen. Zum Beispiel, wenn Sie die Tastenanschläge wiederholen möchten, <foobar>bis Ihr Puffer weniger als 3 Zeilen enthält. Du kannst tun

qq<foobar>3G``@qq

was bedeutet:

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

Es ist wichtig zu beachten, dass, wenn Sie dies in einer VIM-Sitzung testen, dies @qmöglicherweise unbeabsichtigte Nebenwirkungen haben kann, da Makros von geladen werden .vim_profile. Sie können dies auf verschiedene Arten umgehen. Die beste Lösung ist wahrscheinlich, vim mit zu starten

vim -i NONE

Sie können auch Ihre löschen .viminfo.

Wenn Sie vim bereits gestartet haben, können Sie Folgendes eingeben

qqq

am anfang das makro auf null stellen.

Andere Bedingungen, durch die Sie das 3G ersetzen können, sind

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

oder

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

Es gibt verkürzte Versionen von ex-Befehlen, die Sie denken. Zum Beispiel wussten Sie wahrscheinlich schon, dass :globaldas gekürzt werden kann :g, aber wussten Sie, dass dies :nnoremapäquivalent ist zu :nn?

Es ist eine gute Idee, :h :fooalle ex-Befehle auszuführen, die Sie in Ihrer Antwort verwenden, um festzustellen, ob es eine kürzere Version gibt.

Türknauf
quelle
6
:%s/\n//g

ist immer äquivalent zu

:%s/\n//

was auch gleichbedeutend ist mit

:%s/\n

überraschend genug. (Im Allgemeinen ist ohne Flags der letzte Schrägstrich in einem :sAusdruck niemals erforderlich.)

Türknauf
quelle
2
Dies funktioniert für Zeilenumbrüche, jedoch nicht für Zeichen, die mehr als einmal in einer Zeile vorkommen können. Zum Beispiel :%s/xwird nicht jedes Vorkommen von x entfernt, sondern nur das erste in jeder Zeile.
DJMcMayhem
1
Sie können auch verwenden :&&, um einen Ersatzbefehl und seine Flags zu wiederholen .
DJMcMayhem
6

Angenommen, Sie befinden sich im Einfügemodus und möchten einen einzelnen Befehl für den normalen Modus ausführen. Das könnten Sie so schreiben:

isome_text<esc><foobar>gisome_more_text

Mach es nicht so. Stattdessen <C-o>kehrt use , das einen einzelnen normalen Befehl ausführt, sofort in den Einfügemodus zurück.

isome_text<C-o><foobar>some_more_text
DJMcMayhem
quelle
Ich glaube auch nicht, dass diese Felder erforderlich sind
Fund Monicas Klage
@ QPaysTaxes Sie haben recht, sie sind nicht. Ich dachte, das würde es lesbarer machen. Ich werde das bearbeiten.
DJMcMayhem
Sie brauchen kein <CR>after <foobar>, um den Befehl zu senden?
Fund Monicas Klage
@QPaysTaxes Nur wenn es sich um einen Ex-Befehl oder eine Suche handelt. (Eg jeden Befehl beginnend mit einem :, /oder ?)
DJMcMayhem
Oh mein Schlechtes. Ich habe Befehl und normale Modi verwechselt. Cool: D
Fund Monicas Klage
5

Es gibt drei "Änderungsfall" -Operatoren,

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

Da es sich um Operatoren handelt, werden sie bewegt, um das aktuelle Zeichen in Kleinbuchstaben umzuwandeln

gul

Hier kommt der unterhaltsame Trick ins Spiel. :) Wenn Sie die Groß- und Kleinschreibung eines einzelnen Zeichens oder der aktuellen Zeile ändern möchten, ist diese im visuellen Modus um ein Byte kürzer. Zum Beispiel gulist äquivalent zu

vu

Und gu_(_ ist aktuelle Zeile) entspricht

Vu

Dieser Trick funktioniert nicht zum Umschalten, da v?er im visuellen Modus eine Rückwärtssuche auslöst (genau wie beim v/Bewegen in die entgegengesetzte Richtung), sodass Sie ihn vg?stattdessen benötigen . Hier können Sie jedoch die~ Operator verwenden, um noch mehr Bytes zu sparen! (Danke @Doorknob für den Hinweis)

Sie können diesen Trick in Aktion auf meiner VIM-Antwort hier und auf der entsprechenden V-Antwort auf und Post sehen.

DJMcMayhem
quelle
1
Vergiss nicht ~, was die Groß- und Kleinschreibung des Zeichens unter dem Cursor umschaltet und eins nach rechts verschiebt!
Türklinke
5

Das Alphabet in 10 Tastenanschlägen

Die ganze Anerkennung für diese Technik geht an Lynn, die sie zum ersten Mal in dieser Antwort verwendet hat . Ich schreibe es hier für die Nachwelt.

Verwenden Sie die folgenden zehn Tastenanschläge, um das Kleinbuchstaben-Alphabet zu ziehen:

:h<_␍jjYZZ

(Wo ist ein Wagenrücklauf, dh die Eingabetaste.)

Erläuterung

:h<_␍Öffnet den Hilfebereich v_b_<_example(ein Beispiel für eine visuelle blockweise Auswahl), der den Text enthält abcdefghijklmnopqrstuvwyxz. jjYBewegt sich nach unten zu dieser Zeile und zieht sie an sich. Dann wird ZZdas Hilfefenster geschlossen.

Jordan
quelle
4

Kennen Sie Ihre Register

Das Ziehen oder Löschen von Text in ein bestimmtes Register (z. B. "aY), um ihn später zu verwenden, ist nicht immer erforderlich. Vim hat mehrere Register, die automatisch mit den Subjekten verschiedener Befehle gefüllt werden. Geben Sie ein :help registers, um sie alle zu sehen, aber hier sind einige besondere Hinweise:

  • Unbenanntes Register: ""- Der letzte Text, der gezerrt oder gelöscht wurde.

  • Nummeriertes Register "0- Der letzte Text, der gezerrt wurde.

  • Nummerierte Register "1- "9- Der letzte Text, der gelöscht wurde, es sei denn, er bestand aus weniger als einer Zeile. Jedes Mal, wenn "1es gefüllt wird, wird der vorherige Inhalt verschoben "2und so weiter.

  • Kleines Löschregister: "-- Der letzte Text, der kürzer als eine Zeile ist, die gelöscht wurde.

  • Zuletzt eingefügter Text: ".

Insbesondere die "-und "1können Register nützlich zusammen sein, so dass Sie einen Text mit zB löschen ddin das "1Register und löschen einen anderen Text mit Din die "-(natürlich sind die Semantik nicht identisch, aber oft müssen sie nicht sein ).

Es kann schwierig sein, alle Register im Auge zu behalten, aber Sie können den Inhalt aller Register jederzeit durch Eingabe abrufen :registers.

Jordan
quelle
3

Dies kam früher im Chat auf , also dachte ich, ich könnte es genauso gut als vollständigen Tipp posten.

<C-a>und <C-x>erhöhen und verringern Sie die nächste Zahl in der Zeile. Dies ist eine äußerst nützliche Funktion für einfache Berechnungen, ermöglicht aber auch einen ordentlichen kleinen Hack.

Angenommen, Sie müssen zur nächsten Nummer springen. Zum Beispiel müssen wir uns ändern

I need 2 spell better

zu

I need to spell better

Der naheliegende Weg ist, zu der 2 zu springen und dann Folgendes zu tun:

sto                "Synonymous with 'clto'

Da ist das kürzer als

:s/2/to<cr>

Es gibt viele verschiedene Möglichkeiten, um zur 2. zu springen.

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

Sowie viele andere Möglichkeiten.

Dies sind alle 2 (oder mehr) Tastenanschläge. Da jedoch <C-a>und <C-x>nicht nur Inkrement / Dekrement - Zahlen, sondern auch auf die nächste Zahl springen, können wir ein Byte starten mit

<C-a>sto
DJMcMayhem
quelle
3

Golfere Bewegungen

Wenn Sie mit einem Textblock arbeiten (insbesondere bei Herausforderungen in der ), müssen Sie häufig zum ersten oder letzten Zeichen im Puffer wechseln. Gund ggsind ziemlich gut, aber es gibt einige ärgerliche Dinge. Um beispielsweise das letzte Zeichen zu erhalten, müssen G$und ggwerden Sie nicht unbedingt in die erste Spalte gesetzt, wenn ein führendes Leerzeichen vorhanden ist. Hier sind einige schönere Bewegungen, obwohl sie nur funktionieren, wenn Ihr Text keine leeren Zeilen in der Mitte enthält:

  • Erstes Zeichen des Puffers: {ist besser als gg0. Befinden sich in der Mitte des Textes leere Zeilen, können Sie auch verwenden go, um zum ersten Zeichen im Puffer zu gelangen.

  • Letztes Zeichen des Puffers: }ist besser alsG$

Diese dienen auch als Argument für einen Bediener, beachten Sie jedoch, dass es sich um zeichenweise Bewegungen handelt, nicht um linienweise Bewegungen!

DJMcMayhem
quelle
Hist Golfspieler alsgg
Kritixi Lithos
@KritixiLithos außer das Hist nicht zuverlässig. Das Verhalten hängt von der Größe des sichtbaren Fensters und der Position im Puffer ab. (Es ist in V neu abgebildet, um diese Verwirrung zu vermeiden)
DJMcMayhem
2

Berechnen Sie mit dem Ausdrucksregister

Sie können Berechnungen sowohl im normalen Modus als auch im Einfügemodus durchführen.

Normaler Modus

Wenn Sie im normalen Modus @=den Cursor eingeben, gelangen Sie in die Befehlszeile, in der Sie einen beliebigen Ausdruck eingeben können. Wenn Sie die Eingabetaste drücken, wird das Ergebnis des Ausdrucks als Normalmodusbefehl ausgeführt.

Angenommen, Sie möchten in die mittlere Spalte der aktuellen Zeile wechseln. Der Funktionsaufruf col('$')gibt die Anzahl der Spalten in der Zeile zurück. Um dies zu erreichen, geben Sie Folgendes ein:

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

Wenn Sie die Eingabetaste drücken, kehrt der Cursor zum Puffer zurück und vim wartet auf einen Operator (wie |), als hätten Sie gerade eine Nummer eingegeben. Alternativ hätten Sie Folgendes eingeben können:

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

... aber das sind natürlich mehr Bytes.

Einfügemodus

Sie können das Ausdrucksregister auch im Einfügemodus verwenden, indem Sie <Ctrl-r>=anstelle von drücken @=. Dies funktioniert im normalen Modus genauso, mit der Ausnahme, dass das Ergebnis des von Ihnen eingegebenen Ausdrucks im Einfügemodus ausgeführt wird. Wenn Sie beispielsweise tippen <Ctrl-r>=col('$')<CR>, wird die Anzahl der Spalten in der aktuellen Zeile so am Cursor eingefügt, als hätten Sie sie eingegeben.

Geben Sie ein, um weitere Informationen zum Ausdrucksregister zu erhalten :help "=.

Ausdrücke wiederverwenden

Der zuletzt verwendete Ausdruck wird im Ausdrucksregister gespeichert "=. Wenn Sie @=<CR>im normalen Modus oder <Ctrl-r>=<CR>im Einfügemodus tippen, wird der Ausdruck erneut ausgewertet, sodass Sie sie ähnlich wie Makros verwenden können.

Berechnen Sie in Substitutionen

Sie können Ausdrücke auch dann auswerten, wenn Sie reguläre Ausdrücke ersetzen. Alles was Sie tun müssen, ist Ihre Substitution mit zu beginnen \=. Angenommen, Sie möchten die Zeilen in dieser Datei nummerieren:

foo
bar
baz

Der Funktionsaufruf line('.')gibt die aktuelle Zeilennummer zurück, sodass die Arbeit einfach ist. Eingabe:

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

... ergibt das gewünschte Ergebnis:

1 foo
2 bar
3 baz

Um erfassten Gruppen in einem solchen Ausdruck verwenden Sie die verwenden können , submatch()Funktion, wo zB submatch(0)äquivalent ist \0in einer gewöhnlichen Substitution, submatch(1)entspricht \1usw. Diese eats up viele Tastenanschläge, leider.

Geben Sie ein, um weitere Informationen zur Ersetzung von Ausdrücken zu erhalten :help sub-replace-expression.

Jordan
quelle
Für Ihr letztes Beispiel gibt es kürzere Wege. Beispielsweise i1 <esc>bqqywjPb<C-a>@qq@qhandelt es sich um eine reine Normalmoduslösung, die 5 Byte kürzer ist. Und wenn Sie unter Unix arbeiten, können Sie dies sogar tun :%!nl. Trotzdem gute Tipps!
DJMcMayhem
1
Mein Ziel war es, zu demonstrieren, wie man die Funktion verwendet, und nicht, wie man Zeilen mit den wenigsten Tastenanschlägen nummeriert.
Jordanien
1

Sie können den Text eines Makros direkt ändern, der erheblich kürzer sein kann als eine gewundene Bedingung. Angenommen, Sie möchten n- mal etwas einfügen , wobei n eine Benutzereingabe ist. Ich habe zuerst versucht, dies zu tun:

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

Erläuterung:

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

Dies sind 18 Tastenanschläge und eine wirklich hässliche Methode, dies zu tun. Wechseln Sie stattdessen zum Speicherort dieser Nummer und gehen Sie folgendermaßen vor:

Ap<esc>"qdd@q

Erläuterung:

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

Dies sind 9 Tastenanschläge, eine enorme Verbesserung.

Bearbeiten:

Noch kürzer ist es, das Makro für Ihre Nummer auszuführen und dann Ihren Befehl einzugeben. Beispielsweise:

"qdd@qp

Erläuterung:

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

7 Tastenanschläge.

DJMcMayhem
quelle
1
1. Verwenden Sie Dnicht dd. 2. Wenn der Befehl keine Register enthält, können Sie ihn noch kürzer machen. Zum Beispiel, wenn Sie das Zeichen wiederholen wollen xso oft wie die Zahl unter dem Cursor, statt "qD@qix<esc>, Verwendung D@"ix<esc>.
Türklinke