Перейти к X байтов отсюда

9

Как я могу переместить X байтов вперед, начиная с текущей позиции курсора (включая разрывы строк)?

[count]goможет использоваться для перемещения вперед на X байтов от начала буфера. Я попытался Shift + V, G, [count]go(предполагая, [count]goчто отсчет начнется с начала моего выбора), но, к сожалению, это тоже не сработало, потому что goотсчет начинается только с начала буфера.

Я также попытался :set rulerformat=%oотобразить текущее байтовое смещение (как было предложено при переходе к байтовому смещению и отображении позиции в виде байтового смещения ), добавил числа в моей голове и, наконец, выдал [count]go. Это работает, но это не очень практично ...

Роб W
источник
Если все в одной строке, вы можете использовать Xl(где Xчисло символов) или количество символов, за которыми следует стрелка вправо.
Лекенштейн

Ответы:

9

Этот поиск перемещает 40 символов (но не байтов) вперед:

/\_.\{40}/e

ища ровно 40 chars ( \{40}) любого вида, включая newline ( \_.), и поместив курсор в конец поиска ( /e). Смотрите: http://vimregex.com/#Non-Greedy , :help search-offsetи:help \_

Также смотрите :h 23.4для двоичного редактирования.


Обновление: на основе этого ответа вот функция, которая переходит к байтовому смещению:

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

Можно использовать так:

:JumpToOffset 400

или набрав отображенную раскладку клавиатуры, со счетом:

40CTRL-C

Если вы не используете счет, предыдущий номер счета используется повторно. Так что вы можете сделать: 40CTRL-C CTRL-C CTRL-C 30CTRL-C CTRL-Cпрыгать 40, 40, 40, 30, 30 байт и т. Д.

Нажмите, Ctrl-Oчтобы перейти назад (см. Комментарии внутри функции).

VanLaser
источник
Спасибо за ответ. Я действительно ищу движение вперед X байтов, а не символы. Не могли бы вы объяснить, что делает ваш шаблон поиска, возможно, со ссылками на документацию?
Роб W
Выполнено. Также возможно автоматизировать [count]goпроцесс через функцию vim (прочитать текущее смещение байта, добавить желаемое число, goтам).
VanLaser
... добавлены автоматические функции и команды.
VanLaser
Спасибо за обновление, это начинает выглядеть хорошо! Есть два небольших различия между [count]goвашим методом: 1) [count]goдобавляет элемент в список переходов, чтобы я мог Ctrl+Oбыстро вернуться к своей предыдущей позиции. 2) [count]goможно использовать без :, можно ли ввести новое, [count]GOкоторое делает ваше дело. Не могли бы вы отредактировать свой ответ, чтобы он соответствовал этому поведению go?
Роб W
отредактировано для обеих точек
VanLaser
9

В итоге я использовал следующее решение, которое реализует логику из моего вопроса.

  • [count]GOдля перемещения [count]байтов вперед.
  • [count]Goпереместить [count]байты назад.

Добавьте это к вашему .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>"

Спасибо VanLaser за его первоначальную реализацию, которая направила меня в правильном направлении.

Роб W
источник
Один вопрос, где именно вам нужен этот функционал? (Кстати, я закончил тем, что комбинировал ваше решение с повторным использованием предыдущего подсчета, если ничего не предоставлено).
VanLaser
1
@VanLaser Я читал необработанное содержимое файла PDF, чтобы лучше понять формат файла PDF. Файл PDF состоит из множества объектов, и многие из этих объектов имеют префикс длины. Возможность отскочить на X байт была полезна для отладки. И прежде чем вы спросите, почему я редактирую сырые файлы PDF: я разрабатываю новую функцию для PDF.js, которая требует более глубокого знания формата файлов PDF.
Роб W
Спасибо за ответ (и удачи)! Комбинированная версия здесь, если интересно: pastebin.com/7sVyiA85
VanLaser
@VanLaser Я обновил свой ответ финальной версией. Оказалось, что ваш оригинальный метод подсчета строк был в порядке, но в Vim была ошибка. Я представил исправление, которое было принято , поэтому в последней версии Vim ваш ответ также будет работать так, как задумано.
Роб W
Похоже, вы действительно покопались там (переходя к источнику) - поздравляю!
VanLaser