Przejdź do X bajtów stąd

9

Jak mogę przenieść bajty X do przodu, zaczynając od bieżącej lokalizacji kursora (łącznie z podziałami linii)?

[count]gomoże być użyty do przesunięcia X bajtów do przodu od początku bufora. Próbowałem Shift + V, G, [count]go(zakładając, [count]goże zacznie się odliczanie od początku mojego wyboru), ale niestety to też nie zadziałało, ponieważ gozaczyna się odliczanie od początku bufora.

Próbowałem również :set rulerformat=%owyświetlić bieżące przesunięcie bajtu (jak sugeruje Przeskok do przesunięcia bajtu i wyświetlanie pozycji jako przesunięcie bajtu ), dodałem liczby w mojej głowie i ostatecznie wydałem [count]go. To działa, ale nie jest zbyt praktyczne ...

Rob W.
źródło
Jeśli wszystko jest w jednym wierszu, możesz użyć Xl(gdzie Xjest liczba znaków) lub liczby znaków, a następnie strzałki w prawo.
Lekensteyn,

Odpowiedzi:

9

To wyszukiwanie przesuwa 40 znaków (ale nie bajtów) do przodu:

/\_.\{40}/e

wyszukując dokładnie 40 znaków \{40}dowolnego rodzaju (w tym newline ( \_.) i umieszczając kursor na końcu wyszukiwania ( /e). Zobacz: http://vimregex.com/#Non-Greedy , :help search-offseti:help \_

Zobacz także :h 23.4edycję binarną.


Aktualizacja: Na podstawie tej odpowiedzi, oto funkcja, która przeskakuje do przesunięcia bajtu:

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>"

Można użyć w następujący sposób:

:JumpToOffset 400

lub wpisując mapowane mapowanie klawiatury z liczbą:

40CTRL-C

Jeśli nie użyjesz licznika, poprzedni numer zostanie ponownie użyty. Więc możesz zrobić: 40CTRL-C CTRL-C CTRL-C 30CTRL-C CTRL-Cprzeskoczyć 40, 40, 40, 30, 30 bajtów itp.

Naciśnij, Ctrl-Oaby przeskoczyć do tyłu (patrz komentarze wewnątrz funkcji).

VanLaser
źródło
Dziękuję za odpowiedź. Naprawdę szukam do przodu X bajtów, ale nie znaków. Czy mógłbyś wyjaśnić, co robi Twój wzorzec wyszukiwania, ewentualnie z odniesieniami do dokumentacji?
Rob W
Gotowy. Możliwe jest również zautomatyzowanie [count]goprocesu za pomocą funkcji vim (odczyt aktualnego przesunięcia bajtu, dodaj żądaną liczbę, gotam).
VanLaser,
... dodano automatyczne funkcje i polecenia.
VanLaser,
Dzięki za aktualizację, wygląda to dobrze! Istnieją dwie małe różnice pomiędzy [count]goi twoją metodą: 1) [count]gododaje element do listy skoków, dzięki czemu mogę Ctrl+Oszybko wrócić do poprzedniej pozycji. 2) [count]gomożna używać bez :, czy można wprowadzić nowy, [count]GOktóry spełni twoje oczekiwania. Czy możesz edytować swoją odpowiedź, aby pasowała również do tego zachowania go?
Rob W
edytowane dla obu punktów
VanLaser,
9

Skończyło się na użyciu następującego rozwiązania, które implementuje logikę z mojego pytania.

  • [count]GOaby przenieść [count]bajty do przodu.
  • [count]Goaby przenieść [count]bajty do tyłu.

Dodaj to do .vimrc:

function! JumpToByte(byte_nr)
    " See https://vi.stackexchange.com/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>"

Dzięki VanLaser za jego początkową implementację, która skierowała mnie we właściwym kierunku.

Rob W.
źródło
Jedno pytanie, gdzie dokładnie potrzebujesz tej funkcjonalności? (BTW Skończyło się na tym, że połączyłem twoje rozwiązanie z ponownym użyciem poprzedniego licznika, jeśli nie podano żadnego).
VanLaser,
1
@ VanLaser Czytałem surową zawartość pliku PDF, aby lepiej zrozumieć format pliku PDF. Plik PDF składa się z wielu obiektów, a wiele z nich ma prefiks długości. Możliwość przeskakiwania do przodu o X bajtów była przydatna podczas debugowania. Zanim zapytasz, dlaczego edytuję nieprzetworzone pliki PDF: opracowuję nową funkcję dla pliku PDF.js, która wymaga głębszej znajomości formatu pliku PDF.
Rob W
Dzięki za odpowiedź (i powodzenia)! Wersja łączona jest dostępna, jeśli zainteresowany: pastebin.com/7sVyiA85
VanLaser
@ VanLaser Zaktualizowałem swoją odpowiedź do ostatecznej wersji. Okazuje się, że twoja pierwotna metoda liczenia linii była w porządku, ale w Vimie był błąd. Przesłałem łatkę, która została zaakceptowana , więc w najnowszej wersji Vima twoja odpowiedź również będzie działać zgodnie z przeznaczeniem.
Rob W
Wygląda na to, że wykonałeś tam prawdziwe kopanie (przechodząc do źródła) - gratulacje!
VanLaser,