Как Ctrl-A и Ctrl-X, но изменить только первую цифру

10

Есть ли способ увеличить / уменьшить первую цифру после / под курсором, а не целую цифру.

Я знаю, что это не то, как работает Vim, но есть ли плагин, который делает это? Я не смог его найти.

Это очень полезно при редактировании CSS и в других случаях.

Данный:

▐margin: 10px

Когда я нажимаю, CTRL-Aя хочу видеть:

▐margin: 20px

Актуально:

▐margin: 11px
firedev
источник
10
Вы также 10<C-a>можете добавить 10 или r2заменить 1 на 2.
jamessan

Ответы:

6

Это, кажется, работает довольно хорошо, и делает довольно вменяемые вещи при использовании <C-a>на 9 (95 становится 105), или <C-x>на 0 (105 становится 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
  • Во-первых, мы ищем любую цифру, search()имеет преимущество не сброса @/.
  • a <Esc>h - Перейти в режим вставки, добавить пробел после цифры и перейти влево, чтобы курсор находился сверху цифры.
  • Теперь мы можем использовать <C-a>или <C-x>.
  • Мы используем, lxhчтобы удалить пространство, которое мы добавили.

Я сопоставил это с g<C-a>и g<C-x>, так что вы все еще можете назвать оригинал.

Немного другая версия, которая будет искать только цифры в текущей строке (но оставит висячий пробел, если в текущей строке нет номера):

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

А вот еще одна версия, которая использует ту же концепцию, что и раньше, но также добавляет пробел перед цифрой. Это заставит g<C-a>игнорировать любой знак munis перед числом (по умолчанию, <C-a>on -42будет увеличивать его до -41.

Он также принимает счетчик, так что 5g<C-a>увеличит число на 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>
Мартин Турной
источник
9

Базовый прирост

Вот простой макрос для выполнения действия:

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

В обычном режиме вы

  • m` Отметьте свое местоположение
  • l переместить один символ вправо
  • v$x сократить до конца линии
  • h вернуться в исходное положение
  • <c-a> увеличение (или уменьшение)
  • p приклеить свой разрез
  • `` вернуться к своей отметке

Перейти к следующему номеру

Если вы хотите перейти к следующему номеру (или остаться в текущей позиции, если находитесь на номере), вам нужна функция, которая проверяет текущий курсорный символ и, возможно, переходит на следующий номер.

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

NextNumполучает символ под курсором, проверяет, является ли его число, а если нет, ищет следующий номер. После этого все остальное тоже самое. Если вы хотите, чтобы отображение было другим, просто измените то, nnoremap <leader>aчто вы хотите, например nnoremap <c-a>.

Игнорирование негативов и чисел выше 9

Если вы хотите просто циклически перебирать цифры и не использовать их в качестве целых чисел со знаком, следующие функции будут увеличиваться и уменьшаться и переходить в 0 и 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>

Теперь, когда вы находитесь 8и печатаете, <leader>aвы получаете 9. Выполнение этого снова приводит к 0. Если вы нажмете <leader>xна 0вы получите 9. То же самое касается отрицательных чисел. Функции обрезают один символ, увеличивают, уменьшают или переворачивают, а затем вставляют на место.

jecxjo
источник
Что-то здесь не так, но я буду помнить об этой идее, возможно, ее можно улучшить. Следует перейти к первой цифре в текущей строке, если она есть, и работать с ней. Предпочтительно быть сопоставимым <c-a>/<c-x>также.
firedev
Обновленная версия. Теперь переходит к следующему числу или, если вы находитесь над цифрой, вы можете увеличить ее.
Jecxjo
Да! Это потрясающе, спасибо! Я не понимаю, почему вопрос был отклонен, хотя, это раздражало меня с самого первого дня, и, очевидно, многие люди переопределяют <c-a>и <c-x>что-то еще, потому что поведение по умолчанию не так полезно.
firedev
Я мог видеть, что это получает пониженное голосование, потому что вопрос был для чего-то очень определенного, и первоначальный вопрос вроде изменился на этом пути ... необходимость перейти к первому номеру. Что в стороне, я на самом деле использую <c-a>и <c-x>много. Каждый раз, когда я обновляю версию или увеличиваю переменную диапазона, я просто [N]<c-a>вместо удаления и замены.
Jecxjo
1
Это было бы возможно, но было бы гораздо большим набором функций. Текущая реализация использует преимущества <c-a>и <c-x>которые должны быть отброшена для функции , которая делает то же самое , но игнорирует тир.
Jecxjo
5

Вот версия, которую я написал, используя выражение замены:

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>

Каждый из них просто ищет первый символ цифры в строке и добавляет или вычитает его, если он находится в диапазоне [0-8] или [1-9], соответственно. У него есть три проблемы:

  1. В основном это манипуляции с текстом, и он смотрит только на первый символ, поэтому он не знает, является ли число отрицательным. Это поправимо, но мне нравится текущее поведение как есть.
  2. Он заклинивает регистр поиска: "/и если у вас включен hlsearch, то все числа в текущем буфере будут подсвечены при использовании этого. Вы можете добавить :noh<CR>к каждой из вышеперечисленных mapкоманд, чтобы остановить выделение, но я не знаю, как правильно предотвратить засорение регистра.
  3. Он работает с первым номером в строке, а не с первым номером после курсора.

Кроме того, если бы это был я, я бы сопоставил вышесказанное с <leader>aи <leader>x, а не с CTRL-A/X. Таким образом, вам доступны оба варианта поведения. <leader>по умолчанию это ключ обратной косой черты ( \).

Cookyt
источник
То, что он игнорирует отрицательное число, прекрасно, на самом деле поведение по умолчанию показалось мне странным. Я думаю, что это выглядит намного лучше с :noh. Но реальная проблема заключается в том, что он не может использовать позицию курсора в качестве основы, и, следовательно, вы можете увеличивать только первую цифру в строке.
firedev
Это останавливается на числе 9, и выше 10 оно увеличивается на 11, а не на 10 ... Я думаю, что это неумышленно (то есть ошибка)? Кроме того, вы всегда хотите использовать нерекурсивное отображение ( noremap) и никогда map . Смотрите эту страницу для более подробного объяснения этого.
Мартин Турной