Comme Ctrl-A et Ctrl-X mais modifie uniquement le premier chiffre

10

Existe-t-il un moyen d'augmenter / diminuer le premier chiffre après / sous le curseur, pas le nombre entier.

Je sais que ce n'est pas comme ça que vim fonctionne, mais y a-t-il un plugin qui fait ça? Je n'ai pas pu le trouver.

Il est très utile lors de l'édition de CSS et dans d'autres cas également.

Donné:

▐margin: 10px

Quand j'appuie, CTRL-Aje veux voir:

▐margin: 20px

Réel:

▐margin: 11px
firedev
la source
10
Vous pouvez également 10<C-a>ajouter 10 ou r2remplacer le 1 par un 2.
jamessan

Réponses:

6

Cela semble fonctionner assez bien et fait des choses assez sensées lors de l'utilisation <C-a>sur un 9 (95 devient 105), ou <C-x>sur un 0 (105 devient 95):

nnoremap g<C-a> :call search('\d', 'c')<CR>a <Esc>h<C-a>lxh
nnoremap g<C-x> :call search('\d', 'c')<CR>a <Esc>h<C-x>lxh
  • Tout d'abord, nous recherchons n'importe quel chiffre, search()a l'avantage de ne pas réinitialiser @/.
  • a <Esc>h - Passez en mode insertion, ajoutez un espace après le chiffre et allez à gauche pour que le curseur soit au-dessus du chiffre.
  • Nous pouvons maintenant utiliser <C-a>ou <C-x>.
  • Nous utilisons lxhpour supprimer l'espace que nous avons ajouté.

J'ai mappé cela à g<C-a>et g<C-x>, vous pouvez donc toujours appeler l'original.

Une version légèrement différente qui ne recherchera que les numéros sur la ligne actuelle (mais laissera un espace pendant s'il n'y a pas de numéro sur la ligne actuelle):

nnoremap g<C-a> :call search('\d', 'c', line('.'))<CR>a <Esc>h<C-a>lxh
nnoremap g<C-x> :call search('\d', 'c', line('.'))<CR>a <Esc>h<C-x>lxh

Et voici une autre version qui utilise le même concept que précédemment, mais ajoute également un espace avant le chiffre. Cela fera g<C-a>ignorer tout signe avant le numéro Mounis (par défaut, <C-a>sur la -42volonté « increment » à -41.

Il accepte également un nombre, ce qui 5g<C-a>augmentera le nombre de 5:

fun! Increment(dir, count)
    " No number on the current line
    if !search('\d', 'c', getline('.'))
        return
    endif

    " Store cursor position
    let l:save_pos = getpos('.')

    " Add spaces around the number
    s/\%#\d/ \0 /
    call setpos('.', l:save_pos)
    normal! l

    " Increment or decrement the number
    if a:dir == 'prev'
        execute "normal! " . repeat("\<C-x>"), a:count
    else
        execute "normal! " . repeat("\<C-a>", a:count)
    endif

    " Remove the spaces
    s/\v (\d{-})%#(\d) /\1\2/

    " Restore cursor position
    call setpos('.', l:save_pos)
endfun

nnoremap <silent> g<C-a> :<C-u>call Increment('next', v:count1)<CR>
nnoremap <silent> g<C-x> :<C-u>call Increment('prev', v:count1)<CR>
Martin Tournoij
la source
9

Incrément de base

Voici une macro simple pour effectuer l'action:

:nnoremap <leader>a m`lv$xh<c-a>p``
:nnoremap <leader>x m`lv$xh<c-x>p``

En mode normal, vous

  • m` Marquez votre emplacement
  • l déplacer un personnage vers la droite
  • v$x couper à la fin de la ligne
  • h revenir à sa position d'origine
  • <c-a> incrémenter (ou décrémenter)
  • p recollez votre coupe
  • `` revenir à votre marque

Passer au numéro suivant

Si vous souhaitez passer au numéro suivant (ou rester à votre position actuelle si sur un numéro), vous avez besoin d'une fonction qui vérifie le caractère cursé actuel et éventuellement passer au numéro suivant.

function! NextNum()
  let ch = getline(".")[col(".")-1]
  if ch !~ "[0-9]"
    execute "normal! /[0-9]\<cr>"
  endif
endfunction

nnoremap <leader>a :call NextNum()<cr>m`lv$xh<c-a>p``
nnoremap <leader>x :call NextNum()<cr>m`lv$xh<c-x>p``

NextNumobtient le caractère sous le curseur, vérifie si c'est un nombre et sinon recherche le numéro suivant. Après cela, le reste est le même. Si vous voulez que le mappage soit différent, changez simplement le nnoremap <leader>apar ce que vous souhaitez, par exemple nnoremap <c-a>.

Ignorer les négatifs et les nombres supérieurs à 9

Si vous souhaitez simplement parcourir les chiffres et ne pas les faire agir comme des entiers signés, les fonctions suivantes incrémenteront et décrémenteront et passeront à 0 et 9.

function! NextNum()
  let ch = getline(".")[col(".")-1]
  if ch !~ "[0-9]"
    execute "normal! /[0-9]\<cr>"
  endif
endfunction

function! IncDec(val, dec)
  if a:dec
    if a:val == 0
      return 9
    else
      return a:val - 1
    endif
  else
    if a:val == 9
      return 0
    else
      return a:val + 1
    endif
  endif
endfunction

function! DoMath(dec)
  call NextNum()
  normal! x
  let @" = IncDec(@", a:dec)
  normal! P
endfunction

nnoremap <leader>a :call DoMath(0)<cr>
nnoremap <leader>x :call DoMath(1)<cr>

Maintenant, lorsque vous êtes sur 8et tapez, <leader>avous obtenez 9. Le refaire se traduit par 0. Si vous appuyez <leader>xsur 0vous 9. Il en va de même pour les nombres négatifs. Les fonctions coupent un seul caractère, incrémentent, décrémentent ou survolent puis collent en place.

jecxjo
la source
Quelque chose ne va pas ici, mais je garderai cette idée à l'esprit, peut-être qu'elle peut être améliorée. Il doit sauter au premier chiffre de la ligne actuelle, le cas échéant, et opérer dessus. De préférence être mappable <c-a>/<c-x>également.
firedev
La version mise à jour. Saute maintenant au numéro suivant ou si vous êtes actuellement au-dessus d'un chiffre vous permet de l'incrémenter.
jecxjo
Oui! C'est incroyable, merci! Je ne comprends pas pourquoi la question a été rejetée cependant, cela m'ennuyait depuis le premier jour et apparemment beaucoup de gens redéfinissent <c-a>et <c-x>vers autre chose parce que le comportement par défaut n'est pas très utile.
firedev
Je pouvais voir qu'il était rejeté parce que la question était pour quelque chose de très spécifique et la question d'origine a en quelque sorte changé en cours de route ... la nécessité de passer au premier numéro. Cela mis à part, j'utilise en fait <c-a>et <c-x>beaucoup. Chaque fois que je mets à jour une version ou augmente une variable de plage, je viens [N]<c-a>au lieu de supprimer et de remplacer.
jecxjo
1
Ce serait possible, mais ce serait un ensemble de fonctions beaucoup plus vaste. La mise en œuvre actuelle profite de <c-a>et <c-x>qui devrait être abandonné pour une fonction qui fait la même chose , mais ne tient pas compte du tableau de bord.
jecxjo
5

Voici une version que j'ai écrite en utilisant une expression de substitution:

map <c-a> :s/\d/\=submatch(0) < 9 ? submatch(0) + 1 : submatch(0)/<CR>
map <c-x> :s/\d/\=submatch(0) > 0 ? submatch(0) - 1 : submatch(0)/<CR>

Chacun recherche simplement le premier caractère numérique sur la ligne et en ajoute ou en soustrait un s'il se trouve dans la plage [0-8] ou [1-9], respectivement. Il a trois problèmes:

  1. C'est principalement une manipulation de texte, et ne regarde que le premier caractère, donc il ne sait pas si un nombre est négatif. C'est réparable, mais j'aime le comportement actuel tel quel.
  2. Il encombre le registre de recherche:, "/et si vous avez activé la recherche, alors tous les nombres dans le tampon actuel seront mis en évidence lorsque vous l'utiliserez. Vous pouvez ajouter :noh<CR>à chacune des mapcommandes ci-dessus pour arrêter la mise en évidence, mais je ne sais pas comment empêcher gentiment le registre d'être encombré.
  3. Cela fonctionne sur le premier numéro de la ligne, pas sur le premier chiffre après le curseur.

De plus, si c'était moi, je mapperais ce qui précède à <leader>aet <leader>x, plutôt qu'à CTRL-A/X. De cette façon, vous disposez des deux comportements. <leader>est, par défaut, la touche barre oblique inverse ( \).

Cookyt
la source
Le fait qu'il ne tienne pas compte du nombre négatif est très bien, en fait le comportement par défaut me semblait étrange. Je pense que cela semble beaucoup mieux avec :noh. Mais le vrai problème est qu'il ne peut pas utiliser la position du curseur comme base et donc vous ne pouvez incrémenter que le premier chiffre de la ligne.
firedev
Cela s'arrête au nombre 9, et au-dessus de 10, il augmente de 11, pas 10 ... Je pense que ce n'est pas intentionnel (c'est-à-dire un bug)? De plus, vous souhaitez toujours utiliser le mappage non récursif ( noremap) et jamais map . Voir cette page pour une explication plus détaillée de cela.
Martin Tournoij