Aller à X octets d'ici

9

Comment déplacer X octets vers l'avant, à partir de l'emplacement actuel du curseur (y compris les sauts de ligne)?

[count]gopourrait être utilisé pour avancer X octets depuis le début du tampon. J'ai essayé Shift + V, G, [count]go(en supposant que [count]gocela commencerait à compter depuis le début de ma sélection), mais malheureusement cela n'a pas fonctionné non plus car il gone commence à compter qu'à partir du début de la mémoire tampon.

J'ai également essayé :set rulerformat=%od'afficher le décalage d'octet actuel (comme suggéré par le passage à un décalage d'octet et l'affichage de la position comme décalage d'octet ), j'ai ajouté les chiffres dans ma tête et finalement publié [count]go. Cela fonctionne, mais ce n'est pas très pratique ...

Rob W
la source
Si tout est sur une seule ligne, vous pouvez utiliser Xl(où Xest le nombre de caractères) ou le nombre de caractères suivi de la flèche droite.
Lekensteyn

Réponses:

9

Cette recherche déplace 40 caractères (pas d'octets, cependant) vers l'avant:

/\_.\{40}/e

en recherchant exactement 40 caractères ( \{40}) de toute sorte, y compris newline ( \_.), et en plaçant le curseur à la fin de la recherche ( /e). Voir: http://vimregex.com/#Non-Greedy , :help search-offsetet:help \_

Voir également :h 23.4pour l'édition binaire.


Mise à jour: Sur la base de cette réponse, voici une fonction qui passe au décalage d'octet:

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

Peut être utilisé comme ceci:

:JumpToOffset 400

ou en tapant le mappage du clavier mappé, avec un nombre:

40CTRL-C

Si vous n'utilisez pas de comptage, le numéro de comptage précédent est réutilisé. Vous pouvez donc faire: 40CTRL-C CTRL-C CTRL-C 30CTRL-C CTRL-Csauter 40, 40, 40, 30, 30 octets, etc.

Appuyez Ctrl-Opour sauter en arrière (voir les commentaires à l'intérieur de la fonction).

VanLaser
la source
Merci d'avoir répondu. Je cherche vraiment à avancer X octets, pas des caractères cependant. Pourriez-vous expliquer ce que fait votre modèle de recherche, éventuellement avec des références à la documentation?
Rob W
Terminé. Il est également possible d'automatiser le [count]goprocessus dans une fonction vim (lire le décalage d'octet actuel, ajouter le nombre souhaité, golà).
VanLaser
... ajout d'une fonction et d'une commande automatisées.
VanLaser
Merci pour la mise à jour, cela commence à bien paraître! Il y a deux petites différences entre [count]goet votre méthode: 1) [count]goajoute un élément à la liste de sauts, donc je peux utiliser Ctrl+Opour revenir rapidement à ma position précédente. 2) [count]gopeut être utilisé sans :, est-il possible d'introduire un nouveau [count]GOqui fait votre truc. Pourriez-vous modifier votre réponse pour qu'elle corresponde également à ce comportement de go?
Rob W
modifié pour les deux points
VanLaser
9

J'ai fini par utiliser la solution suivante, qui met en œuvre la logique de ma question.

  • [count]GOpour avancer les [count]octets.
  • [count]Gopour déplacer les [count]octets en arrière.

Ajoutez ceci à votre .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>"

Merci à VanLaser pour sa mise en œuvre initiale, qui m'a mis dans la bonne direction.

Rob W
la source
Une question, où avez-vous exactement besoin de cette fonctionnalité? (BTW j'ai fini par combiner votre solution avec la réutilisation du décompte précédent si aucun n'est fourni).
VanLaser
1
@VanLaser Je lisais le contenu brut d'un fichier PDF, afin de mieux comprendre le format du fichier PDF. Un fichier PDF se compose de nombreux objets, et bon nombre de ces objets ont un préfixe de longueur. Être capable de sauter X octets en avant était utile pour le débogage. Et avant de demander pourquoi j'édite des fichiers PDF bruts: je développe une nouvelle fonctionnalité pour PDF.js qui nécessite une connaissance plus approfondie du format de fichier PDF.
Rob W
Merci pour la réponse (et bonne chance)! La version combinée est ici, si vous êtes intéressé: pastebin.com/7sVyiA85
VanLaser
@VanLaser J'ai mis à jour ma réponse avec une version finale. Il s'avère que votre méthode de comptage de lignes d'origine était correcte, mais il y avait un bug dans Vim. J'ai soumis un patch qui a été accepté , donc dans la dernière version de Vim, votre réponse fonctionnera également comme prévu.
Rob W
Vous semblez y avoir fait de véritables fouilles (aller à la source) - félicitations!
VanLaser