Vá para X bytes daqui

9

Como posso mover X bytes para frente, começando na localização atual do cursor (incluindo quebras de linha)?

[count]gopode ser usado para avançar X bytes desde o início do buffer. Eu tentei Shift + V, G, [count]go(supondo que [count]goisso começaria a contar desde o início da minha seleção), mas infelizmente isso também não funcionou porque goapenas começa a contar desde o início do buffer.

Também tentei :set rulerformat=%oexibir o deslocamento de bytes atual (como sugerido por Saltando para um deslocamento de bytes e exibindo a posição como deslocamento de bytes ), adicionei os números na minha cabeça e finalmente emiti [count]go. Isso funciona, mas não é muito prático ...

Rob W
fonte
Se tudo estiver em uma linha, você poderá usar Xl(onde Xestá o número de caracteres) ou o número de caracteres seguido pela seta para a direita.
21430 Lekensteyn

Respostas:

9

Essa pesquisa move 40 caracteres (mas não bytes) para a frente:

/\_.\{40}/e

pesquisando exatamente 40 caracteres ( \{40}) de qualquer tipo, incluindo nova linha ( \_.) e colocando o cursor no final da pesquisa ( /e). Veja: http://vimregex.com/#Non-Greedy , :help search-offsete:help \_

Veja também :h 23.4para edição binária.


Atualização: Com base nesta resposta, aqui está uma função que salta para deslocamento de bytes:

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

Pode ser usado assim:

:JumpToOffset 400

ou digitando o mapeamento do teclado mapeado, com uma contagem:

40CTRL-C

Se você não usar uma contagem, o número da contagem anterior será reutilizado. Então você pode fazer: 40CTRL-C CTRL-C CTRL-C 30CTRL-C CTRL-Cpular 40, 40, 40, 30, 30 bytes etc.

Clique Ctrl-Opara voltar (consulte os comentários dentro da função).

VanLaser
fonte
Obrigado pela resposta. Estou realmente procurando avançar X bytes, mas não caracteres. Você poderia explicar o que seu padrão de pesquisa faz, possivelmente com referências à documentação?
22615 Robert W
Feito. Também é possível automatizar o [count]goprocesso em uma função vim (leia o deslocamento de bytes atual, adicione o número desejado go).
21415 VanLaser
... adicionou função e comando automatizados.
21415 VanLaser
Obrigado pela atualização, isso começa a ficar bem! Existem duas pequenas diferenças entre [count]goe seu método: 1) [count]goadiciona um item à lista de saltos, para que eu possa usar Ctrl+Opara voltar rapidamente à minha posição anterior. 2) [count]gopode ser usado sem :, é possível introduzir um novo [count]GOque faz a sua coisa. Você poderia editar sua resposta para também corresponder ao comportamento de go?
22715 Rob Rob W
editada para os dois pontos
VanLaser 06/07/2015
9

Acabei usando a seguinte solução, que implementa a lógica da minha pergunta.

  • [count]GOpara mover [count]bytes para frente.
  • [count]Gopara mover [count]bytes para trás.

Adicione isso ao seu .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>"

Agradeço a VanLaser por sua implementação inicial, o que me colocou na direção certa.

Rob W
fonte
Uma pergunta: onde exatamente você precisa dessa funcionalidade? (BTW, acabei combinando sua solução com a reutilização da contagem anterior, se nenhuma for fornecida).
VanLaser
11
@VanLaser Eu estava lendo o conteúdo bruto de um arquivo PDF, para entender melhor o formato do arquivo PDF. Um arquivo PDF consiste em muitos objetos, e muitos desses objetos têm um prefixo de comprimento. Ser capaz de pular X bytes à frente foi útil para depuração. E antes que você pergunte por que estou editando arquivos PDF brutos: estou desenvolvendo um novo recurso para PDF.js que requer um conhecimento mais profundo do formato de arquivo PDF.
22715 Rob Rob W
Obrigado pela resposta (e boa sorte)! A versão combinada está aqui, se estiver interessado: pastebin.com/7sVyiA85
VanLaser
@VanLaser Atualizei minha resposta com uma versão final. Acontece que seu método original de contagem de linhas estava bom, mas houve um erro no Vim. Enviei um patch que foi aceito . Portanto, na versão mais recente do Vim, sua resposta também funcionará conforme o esperado.
21715 Rob Rob W
Você parece ter cavado de verdade lá (indo para a fonte) - parabéns!
VanLaser