从这里转到X个字节


9

如何从当前光标位置(包括换行符)开始向前移动X个字节?

[count]go可用于从缓冲区的开始向前移X个字节。我尝试了一下Shift + V, G, [count]go(假设[count]go将从选择的开头开始计数),但是不幸的是,这也没有用,因为它go仅从缓冲区的开头开始计数。

我还尝试:set rulerformat=%o显示当前字节偏移量(如跳转到字节偏移量并显示为字节偏移量所示),将数字添加到我的头部并最终发出[count]go。这行得通,但不是很实用...


如果所有内容都在一行上,则可以使用XlX字符数在其中)或字符数后跟向右箭头。
Lekensteyn

Answers:


9

该搜索将40个字符(尽管不是字节)向前移动:

/\_.\{40}/e

通过精确地搜索40种字符(\{40}包括换行符\_.),并将光标放在搜索的末尾(/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即可跳回(请参见函数内部的注释)。


感谢您的回答。我真的在寻找向前X个字节,而不是字符。您能否解释一下搜索模式(可能参考文献)?
罗布W

做完了 [count]go尽管在vim函数中(读取当前字节偏移,在go此处添加所需的数字),也可以使过程自动化。
VanLaser 2015年

...添加了自动功能和命令。
VanLaser 2015年

感谢您的更新,它开始看起来不错![count]go和方法之间有两个小区别:1)[count]go将项目添加到跳转列表中,因此我可以Ctrl+O用来快速跳转回我以前的位置。2)[count]go可以不带:,可以引入一个新的功能[count]GO来做。您可以编辑您的答案以使其也符合该行为go吗?
Rob W

针对这两点进行了编辑
VanLaser 2015年

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的最初实施,这为我指明了正确的方向。


一个问题,您到底在哪里需要此功能?(顺便说一句,如果没有提供解决方案,我最终将您的解决方案与重用以前的计数结合在一起)。
VanLaser

1
@VanLaser我正在阅读PDF文件的原始内容,以便更好地了解PDF文件格式。PDF文件包含许多对象,其中许多对象都有长度前缀。能够向前跳转X个字节对于调试很有用。在您问我为什么要编辑原始PDF文件之前:我正在为PDF.js开发一项新功能,需要对PDF文件格式有更深入的了解。
Rob W

感谢您的回答(祝您好运)!如果有兴趣的话,可以在这里查看合并的版本:pastebin.com/7sVyiA85
VanLaser

@VanLaser我已经用最终版本更新了我的答案。原来,您的原始行计数方法很好,但是Vim中存在一个错误。我已经提交了一个被接受的补丁,因此在最新版本的Vim中,您的回答也将按预期工作。
罗布W

您似乎已经在那里进行了一些实际的挖掘(请参见源代码)-恭喜!
VanLaser
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.