Como Ctrl-A y Ctrl-X pero modifica solo el primer dígito

10

¿Hay alguna manera de aumentar / disminuir el primer dígito después / debajo del cursor, no el número entero?

Sé que no es cómo funciona vim, pero ¿hay un complemento que lo haga? No pude encontrarlo.

Es muy útil al editar CSS y en otros casos también.

Dado:

▐margin: 10px

Cuando presiono CTRL-Aquiero ver:

▐margin: 20px

Real:

▐margin: 11px
firedev
fuente
10
También puede 10<C-a>agregar 10 o r2reemplazar el 1 con un 2.
jamessan

Respuestas:

6

Esto parece funcionar bastante bien, y hace cosas bastante sensatas cuando se usa <C-a>en un 9 (95 se convierte en 105), o <C-x>en un 0 (105 se convierte en 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
  • Primero, buscamos cualquier dígito, search()tiene la ventaja de no reiniciar @/.
  • a <Esc>h - Vaya al modo de inserción, agregue un espacio después del dígito y vaya a la izquierda para que el cursor esté en la parte superior del dígito.
  • Ahora podemos usar <C-a>o <C-x>.
  • Usamos lxhpara eliminar el espacio que agregamos.

He asignado esto a g<C-a>y g<C-x>, por lo que aún puede llamar al original.

Una versión ligeramente diferente que solo buscará números en la línea actual (pero dejará un espacio colgante si no hay un número en la línea actual):

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

Y aquí hay otra versión que usa el mismo concepto que antes, pero también agrega un espacio antes del dígito. Esto hará g<C-a>caso omiso de cualquier signo munis antes del número (por defecto, <C-a>en la -42voluntad 'incremento' a -41.

También acepta un recuento, por lo que 5g<C-a>incrementará el número en 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
fuente
9

Incremento básico

Aquí hay una macro simple para realizar la acción:

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

En modo normal usted

  • m` Marque su ubicación
  • l mover un personaje a la derecha
  • v$x cortar hasta el final de la línea
  • h volver a la posición original
  • <c-a> incremento (o decremento)
  • p pegar tu corte
  • `` volver a tu marca

Salta al siguiente número

Si desea saltar al siguiente número (o permanecer en su posición actual si está en un número), necesita una función que verifique el carácter de curso actual y el posible salto al siguiente número.

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

NextNumcoloca el carácter debajo del cursor, comprueba si es un número y, si no, busca el siguiente número. Después de eso, el resto es igual. Si desea que el mapeo sea diferente, simplemente cambie el nnoremap <leader>aque desee, por ejemplo nnoremap <c-a>.

Ignorando negativos y números superiores a 9

Si desea simplemente recorrer los dígitos y no hacer que actúen como enteros con signo, las siguientes funciones aumentarán y disminuirán y se desplazarán a 0 y 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>

Ahora, cuando estás encendido 8y tecleas <leader>a, obtienes 9. Hacerlo nuevamente da como resultado 0. Si pulsa <leader>xen 0llegar 9. Lo mismo ocurre con los números negativos. Las funciones cortan un solo carácter, incrementan, disminuyen o vuelcan y luego pegan en su lugar.

jecxjo
fuente
Algo no está bien aquí, pero tendré en cuenta esa idea, tal vez se pueda mejorar. Debería saltar al primer dígito en la línea actual, si corresponde, y operar en ella. Preferiblemente sea mapeable <c-a>/<c-x>también.
firedev
La versión actualizada. Ahora salta al siguiente número o si actualmente tiene más de un dígito le permite incrementarlo.
jecxjo
¡Si! Esto es asombroso, gracias! Sin embargo, no entiendo por qué la pregunta fue rechazada, esto me molestó desde el primer día y aparentemente muchas personas redefinen <c-a>y hacen <c-x>algo más porque el comportamiento predeterminado no es tan útil.
firedev
Pude ver que se votó negativamente porque la pregunta era para algo muy específico y la pregunta original cambió en el camino ... la necesidad de saltar al primer número. Aparte de eso, en realidad uso <c-a>y <c-x>mucho. Cada vez que actualizo una versión o aumento una variable de rango, simplemente en [N]<c-a>lugar de eliminar y reemplazar.
jecxjo
1
Sería posible pero sería un conjunto de funciones mucho más grande. La implementación actual aprovecha <c-a>y <c-x>que debería descartarse para una función que hace lo mismo pero ignora el guión.
jecxjo
5

Aquí hay una versión que escribí usando una expresión sustituta:

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>

Cada uno solo busca el primer dígito en la línea y suma o resta uno si está en el rango [0-8] o [1-9], respectivamente. Tiene tres problemas:

  1. Es principalmente manipulación de texto, y solo mira el primer carácter, por lo que no sabe si un número es negativo. Esto es reparable, pero me gusta el comportamiento actual tal cual.
  2. Cambia el registro de búsqueda: "/y si tiene hlsearch activado, todos los números en el búfer actual se resaltarán cuando lo use. Puede agregar :noh<CR>a cada uno de los mapcomandos anteriores para detener el resaltado, pero no sé cómo detener bien el registro.
  3. Funciona en el primer número de la línea, no en el primer número después del cursor.

Además, si fuera yo, mapearía lo anterior a <leader>ay <leader>x, en lugar de hacerlo CTRL-A/X. De esta manera, tiene ambos comportamientos disponibles para usted. <leader>es, por defecto, la tecla de barra invertida ( \).

Cookyt
fuente
El hecho de que no tenga en cuenta el número negativo está bien, de hecho, el comportamiento predeterminado me pareció extraño. Creo que también se ve mucho mejor :noh. Pero el verdadero problema es que no puede usar la posición del cursor como base y, por lo tanto, solo puede incrementar el primer dígito de la línea.
firedev
Esto se detiene en el número 9, y por encima de 10 aumenta en 11, no en 10 ... ¿Creo que esto no es intencional (es decir, un error)? Además, siempre desea utilizar el mapeo no recursivo ( noremap) y nunca map . Vea esta página para una explicación más detallada de eso.
Martin Tournoij