Gehen Sie von hier aus zu X Bytes

9

Wie kann ich X Bytes ausgehend von der aktuellen Cursorposition (einschließlich Zeilenumbrüchen) vorwärts verschieben?

[count]gokönnte verwendet werden, um X Bytes vom Anfang des Puffers vorwärts zu bewegen. Ich habe es versucht Shift + V, G, [count]go(vorausgesetzt, das [count]gowürde ab dem Beginn meiner Auswahl mit dem Zählen beginnen), aber leider hat das auch nicht funktioniert, da das goZählen erst ab dem Beginn des Puffers beginnt.

Ich habe auch versucht :set rulerformat=%o, den aktuellen Byte-Offset anzuzeigen (wie durch Springen zu einem Byte-Offset und Anzeigen der Position als Byte-Offset vorgeschlagen ), die Zahlen in meinem Kopf hinzugefügt und schließlich ausgegeben [count]go. Das funktioniert, ist aber nicht sehr praktisch ...

Rob W.
quelle
Wenn sich alles in einer Zeile befindet, können Sie Xl(wobei Xdie Anzahl der Zeichen ist) oder die Anzahl der Zeichen gefolgt vom Rechtspfeil verwenden.
Lekensteyn

Antworten:

9

Diese Suche bewegt 40 Zeichen (allerdings keine Bytes) vorwärts:

/\_.\{40}/e

indem Sie nach genau 40 Zeichen ( \{40}) jeglicher Art suchen, einschließlich newline ( \_.), und den Cursor am Ende der Suche platzieren ( /e). Siehe: http://vimregex.com/#Non-Greedy , :help search-offsetund:help \_

Siehe auch :h 23.4für die binäre Bearbeitung.


Update: Basierend auf dieser Antwort ist hier eine Funktion, die zum Byte-Offset springt:

let s:last_jump_bytes = 0

function! JumpTo(byte_nr)
    let crt_byte = line2byte(line('.')) + col('.')
    if (a:byte_nr == 0)
        let dst_byte = crt_byte + s:last_jump_bytes
    else
        let dst_byte = crt_byte + a:byte_nr
        let s:last_jump_bytes = a:byte_nr
    endif
    let dst_line = byte2line(dst_byte)
    let dst_col = dst_byte -line2byte(dst_line)
    "remove next line if you don't want to record this for `Ctrl-O`
    execute "normal " . dst_line . "G"
    call setpos('.', [0, dst_line, dst_col])
endfunction

command! -nargs=1 JumpToOffset :call JumpTo(<f-args>)

" silly mapping to Ctrl-C (demo)
nnoremap <expr> <silent> <c-c> ":<c-u>call JumpTo(" . v:count . ")<cr>"

Kann so verwendet werden:

:JumpToOffset 400

oder geben Sie die zugeordnete Tastaturzuordnung mit einer Anzahl ein:

40CTRL-C

Wenn Sie keine Zählung verwenden, wird die vorherige Zählnummer erneut verwendet. Sie können also tun: 40CTRL-C CTRL-C CTRL-C 30CTRL-C CTRL-C40, 40, 40, 30, 30 Bytes usw. springen.

Drücken Sie, Ctrl-Oum zurückzuspringen (siehe Kommentare in der Funktion).

VanLaser
quelle
Danke für die Antwort. Ich bin wirklich auf der Suche nach X-Bytes, aber nicht nach Zeichen. Können Sie erklären, was Ihr Suchmuster bewirkt, möglicherweise unter Bezugnahme auf die Dokumentation?
Rob W
Getan. Es ist auch möglich, den [count]goProzess in einer vim-Funktion zu automatisieren (aktuellen Byte-Offset lesen, dort die gewünschte Nummer hinzufügen go).
VanLaser
... automatisierte Funktion und Befehl hinzugefügt.
VanLaser
Danke für das Update, das sieht gut aus! Es gibt zwei kleine Unterschiede zwischen [count]gound Ihrer Methode: 1) [count]goFügt der Sprungliste ein Element hinzu, damit ich Ctrl+Oschnell zu meiner vorherigen Position zurückkehren kann. 2) [count]gokann ohne verwendet werden :, ist es möglich, eine neue einzuführen [count]GO, die Ihr Ding macht. Könnten Sie Ihre Antwort so bearbeiten, dass sie auch dem Verhalten von entspricht go?
Rob W
bearbeitet für beide Punkte
VanLaser
9

Am Ende habe ich die folgende Lösung verwendet, die die Logik aus meiner Frage implementiert.

  • [count]GOzu bewegen [count]Bytes nach vorn.
  • [count]Gozu verschieben [count]Bytes nach hinten.

Fügen Sie dies zu Ihrem hinzu .vimrc:

function! JumpToByte(byte_nr)
    " See /vi//a/3911/2720 for the byte counting bug
    let crt_byte = line2byte(line('.')) + col('.') - 1
    if version < 781 && &l:binary == 1 && &l:eol == 0
        let crt_byte += 1
        let crt_byte += line('.') == 1
    endif
    let dst_byte = crt_byte + a:byte_nr
    execute "normal " . dst_byte . "go"
endfunction
nnoremap <expr> <silent> GO ":<c-u>call JumpToByte(" . v:count . ")<cr>"
nnoremap <expr> <silent> Go ":<c-u>call JumpToByte(-" . v:count . ")<cr>"

Vielen Dank an VanLaser für seine erste Implementierung, die mich in die richtige Richtung gebracht hat.

Rob W.
quelle
Eine Frage, wo genau benötigen Sie diese Funktionalität? (Übrigens habe ich Ihre Lösung mit der Wiederverwendung der vorherigen Zählung kombiniert, wenn keine angegeben ist).
VanLaser
1
@VanLaser Ich habe den Rohinhalt einer PDF-Datei gelesen, um das PDF-Dateiformat besser zu verstehen. Eine PDF-Datei besteht aus vielen Objekten, und viele dieser Objekte haben ein Längenpräfix. Für das Debuggen war es hilfreich, X Bytes voraus springen zu können. Und bevor Sie fragen, warum ich unformatierte PDF-Dateien bearbeite: Ich entwickle eine neue Funktion für PDF.js, die tiefere Kenntnisse des PDF-Dateiformats erfordert.
Rob W
Danke für die Antwort (und viel Glück)! Die kombinierte Version ist hier, wenn Interesse besteht : pastebin.com/7sVyiA85
VanLaser
@ VanLaser Ich habe meine Antwort mit einer endgültigen Version aktualisiert. Es stellt sich heraus, dass Ihre ursprüngliche Zählmethode in Ordnung war, aber es gab einen Fehler in Vim. Ich habe einen Patch eingereicht, der akzeptiert wurde. In der neuesten Version von Vim funktioniert Ihre Antwort auch wie vorgesehen.
Rob W
Sie scheinen dort richtig gegraben zu haben (zur Quelle gehen) - herzlichen Glückwunsch!
VanLaser