2012-03-24 9 views
1

Von außen möchte ich Lösungen, die nicht Vim Scripting Hacks verwenden, sondern versuchen, einige grundlegende * ix Tools wiederzuverwenden. Inside Vim stopft nach Lösungen, um das Spalteninkrement mit Insidern wie Scripting zu erhalten.Vim: Columnvise Increment von innen und außen?

1   1 
1   2 
1   3 
1 ---> 4 
1   5 
1   6 
.   . 
.   . 

Vim hat ein Skript, das säulen Schraubstock Inkrementieren der Fall ist, VisIncr. Es hat ungefähr 50/50 Ups und Downs gesammelt, vielleicht ein bisschen das Rad neu erfinden. Wie spalten Sie Dinge in Vim, ohne ein solches Skript zu verwenden? Dann ist die andere Frage, wie spalten Sie Sachen ohne/außerhalb Vim?

Am elegantesten, wiederverwendbar und vorzugsweise klein gewinnt das Rennen!

+0

Die Antwort hängt vom Umfang der Maßnahme: Ob dieser Spalte der einzige Inhalt sind in einer Datei? Oder ist es ein Absatz oder eine willkürliche Reihe von Linien? Enthalten diese Zeilen ursprünglich auch einige Zahlen (wie "1" im obigen Beispiel) oder zusätzlichen Text (oder beides)? Müssen Nummern eingefügt oder bestehende geändert werden? –

+0

Können Sie bitte genau angeben, welche Aufgabe eine Antwort lösen soll? Welche spezifischen Anforderungen haben Sie? Möchten Sie, dass das verknüpfte Skript (oder ein bestimmter Teil seiner Funktionalität, dann angeben) in einer Antwort von Grund auf neu implementiert wird? –

+0

Die Funktion, die ich vorgeschlagen habe, folgt nur dem Verhalten des Referenzskripts (einschließlich der Verwendung einer spaltenweisen visuellen Auswahl), da Sie * sich * noch immer * nicht genau formulieren *, welches Verhalten Sie wollen (und meine Klärungsfragen ignorieren). –

Antwort

3

Ich habe kein Bedürfnis nach einem Skript, ein einfaches Makro

es
"a yyp^Ayy 

dann spielen tun würde, sehen, oder wo es sich zu spielen.

Natürlich gibt es immer die Möglichkeit, dass ich die Frage völlig falsch verstanden ...

+0

@hhh - Nein, nur der zweite Teil ist Teil des Makros selbst. Der erste Teil ist nur aufgrund der Tatsache, dass ich es in Makro namens "a" aufgenommen. Also, im Prinzip ist es, zieh die Linie, füge sie unten ein, erhöhe sie um eins, reiße sie erneut. – Rook

+0

Verbessere es ein wenig. In der ersten Zeile geben Sie "1" ein. Zeichnen Sie ein Makro auf: 'qayyp^Aq'. Spiele es 5 mal: '5 @ a'. – Hong

3

Die optimale Wahl einer Technik stark von den tatsächlichen Umständen abhängt der Transformation. Es gibt mindestens zwei Punkte Variationen beeinflussen Umsetzung:

  1. Ob die Linien auf den Betrieb sind die einzigen, die in einer Datei? Wenn nicht, ist der Bereich der Zeilen, die durch den Kontext definiert sind (d. H. Er wird durch leere Zeilen wie ein Absatz getrennt) oder ist er willkürlich und sollte von Benutzer angegeben werden?

  2. Sind in diesen Zeilen bereits Zahlen enthalten, die geändert werden sollen oder ist es erforderlich, neue einzufügen, die den Text auf den Zeilen intakt lassen?

Da es keine Informationen über diese Fragen zu beantworten, unter wir konstruieren eine flexible Lösung versuchen.

Eine allgemeine Lösung ist eine Ersetzung, die am Anfang der Zeilen in dem vom Benutzer angegebenen Bereich ausgeführt wird. Der visuelle Modus ist wahrscheinlich der einfachste Weg der Auswahl eines beliebigen Bereichs von Linien, so dass wir hier annehmen, dass Grenzen von der Bereich durch die visuelle Auswahl definiert sind.

:'<,'>s/^\d\+/\=line(".")-line("''")+1/ 

Wenn es notwendig ist, jede Zeile in einem Puffer Nummer kann der Befehl wie folgt vereinfacht werden.

:%s/^\d\+/\=line('.')/ 

In jedem Fall sollte, wenn die Anzahl lediglich an den Anfängen der Zeilen eingefügt werden (ohne die, die Modifizierung, die bereits vorhanden sind), kann man das Muster von ^\d\+ zu ^, ändern und eine wahlweise hinzuzufügen Separator:

:'<,'>s/^\d\+/\=(line(".")-line("''")+1).' '/ 

oder

:%s/^/\=line('.').' '/ 

sind.

Für eine Lösung, die auf Befehlszeilentools basiert, kann man die Verwendung von Stream Editoren wie Sed oder Textextraktions- und Berichterstellungstools wie AWK in Erwägung ziehen.

Zu jeder der Zeilen in einer Datei nummerieren Sed verwenden, die Befehle ausführen

$ sed = filename | sed 'N;s/\n/ /' 

Um die gleiche in AWK zu tun, verwenden Sie den Befehl

$ awk '{print NR " " $0}' filename 

die leicht modfied werden könnte um die Nummerierung auf einen bestimmten Linienbereich zu beschränken eine bestimmte Bedingung zu erfüllen. Der folgende Befehl nummeriert z. B. die Zeilen 2 bis 8 der Zeile .

$ awk '{print (2<=NR && NR<=8 ? ++n " " : "") $0}' filename 

ein Interesse daran, wie Befehle ähnlich denen aus dem in die Frage Anweisung verknüpft Skript Mit umgesetzt werden, kann man den folgenden Befehl als eine Referenz verwenden.

vnoremap <leader>i :call EnumVisualBlock()<cr> 
function! EnumVisualBlock() range 
    if visualmode() != "\<c-v>" 
     return 
    endif 
    let [l, r] = [virtcol("'<"), virtcol("'>")] 
    let [l, r] = [min([l, r]), max([l, r])] 
    let start = matchstr(getline("'<"), '^\d\+', col("'<")-1) 
    let off = start - line("'<") 
    let w = max(map([start, line("'>") + off], 'len("".v:val)')) 
    exe "'<,'>" 's/\%'.l.'v.*\%<'.(r+1).'v./'. 
    \ '\=printf("%'.w.'d",line(".")+off).repeat(" ",r-l+1-w)' 
endfunction 
+0

Für eine allgemeinere Technik, die eine zählerbasierte Substitution in Vim implementiert, siehe meine Antwort (http://stackoverflow.com/a/8074421/254635) auf die Frage "[Wie benutze ich Vim, um eine Variable zu verwenden? Anzahl der gefundenen Muster speichern?] (http://stackoverflow.com/q/8073780/254635) ". –

+0

@hhh: Ich habe mir das Skript angesehen, das in der Frageanweisung verlinkt ist. Dieser Code enthält jedoch keine eigene Frage. Möchten Sie eine alternative Implementierung dieses Skripts vorschlagen? Bitte erläutern Sie, was genau eine ideale Lösung tun sollte (oder welche Funktionalität des besagten Skripts sie nachahmen sollte): Alle Anforderungen für eine mögliche Lösung sollten in der Frage klar angegeben werden. –

+0

@hhh: Was meinst du? Warum antwortest du keine der Klärungsfragen? Um Hilfe zu erhalten, beschreiben Sie bitte, was Sie erreichen möchten. (Übrigens, werfen Sie einen Blick auf das Update der Antwort. Vielleicht ist es nahe, was Sie zu implementieren versuchen.) –

1

Wenn Sie 1 1 1 1 ... zu 1 2 3 4 ... ändern. (Diese Zahlen sollten auf verschiedenen Linien.)

:let i=1 | g/1/s//\=i/g | let i+=1 

Wenn einige 1 1 1 1 ... in der gleichen Zeile sind:

:let g:i = 0 

:func! Inc() 
: let g:i+=1 
: return g:i 
:endfun 

:%s/1/\=Inc()/g