Podobnie jak Ctrl-A i Ctrl-X, ale modyfikuj tylko pierwszą cyfrę


10

Czy istnieje sposób na zwiększenie / zmniejszenie pierwszej cyfry za / pod kursorem, a nie całej liczby.

Wiem, że to nie tak działa vim, ale czy istnieje wtyczka, która to robi? Nie mogłem tego znaleźć.

Jest to bardzo przydatne podczas edycji css, a także w innych przypadkach.

Dany:

▐margin: 10px

Kiedy naciskam CTRL-A, chcę zobaczyć:

▐margin: 20px

Rzeczywisty:

▐margin: 11px

10
Możesz także 10<C-a>dodać 10 lub r2zamienić 1 na 2.
— jamessan 14.04.15

Odpowiedzi:


6

Wydaje się, że działa to całkiem dobrze i robi całkiem rozsądne rzeczy, gdy używa się <C-a>na 9 (95 staje się 105), lub używa <C-x>na 0 (105 staje się 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
  • Po pierwsze, szukamy dowolnej cyfry, search()ma tę zaletę, że nie resetuje się @/.
  • a <Esc>h - Przejdź do trybu wstawiania, dodaj spację po cyfrze i idź w lewo, aby kursor znajdował się nad cyfrą.
  • Możemy teraz użyć <C-a>lub <C-x>.
  • Używamy lxhdo usuwania dodanego miejsca.

Odwzorowałem to na g<C-a>i g<C-x>, więc nadal możesz zadzwonić do oryginału.

Nieco inna wersja, która będzie wyszukiwać tylko liczby w bieżącym wierszu (ale pozostawi wiszącą spację, jeśli w bieżącym wierszu nie ma numeru):

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

A oto kolejna wersja, która wykorzystuje tę samą koncepcję jak poprzednio, ale dodaje również spację przed cyfrą. Spowoduje to g<C-a>zignorowanie dowolnego znaku munis przed liczbą (domyślnie, <C-a>on -42„zwiększy” ją do -41.

Akceptuje również liczenie, więc 5g<C-a>zwiększy liczbę o 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

Przyrost podstawowy

Oto proste makro do wykonania akcji:

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

W trybie normalnym ty

  • m` Zaznacz swoją lokalizację
  • l przesuń jedną postać w prawo
  • v$x przeciąć do końca linii
  • h wróć do pierwotnej pozycji
  • <c-a> przyrost (lub spadek)
  • p wklej z powrotem swoje cięcie
  • `` wróć do swojego znaku

Przejdź do następnego numeru

Jeśli chcesz przeskoczyć do następnej liczby (lub pozostać w bieżącej pozycji, jeśli znajduje się na numerze), potrzebujesz funkcji, która sprawdza bieżący kursor i możliwy skok do następnej liczby.

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

NextNumumieszcza znak pod kursorem, sprawdza, czy jest to liczba, a jeśli nie, szuka następnego numeru. Potem reszta jest taka sama. Jeśli chcesz, aby mapowanie było inne, zmień na przykład nnoremap <leader>ato, co chcesz nnoremap <c-a>.

Ignorowanie negatywów i liczb wyższych niż 9

Jeśli chcesz po prostu przewijać cyfry i nie powodować, by działały one jako liczby całkowite ze znakiem, następujące funkcje będą zwiększać i zmniejszać oraz przesuwać po wartościach 0 i 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>

Teraz, gdy jesteś włączony 8i pisz <leader>a, dostajesz 9. Ponowne wykonanie spowoduje 0. Jeśli naciśniesz <leader>xna 0dostajesz 9. To samo dotyczy liczb ujemnych. Funkcje wycinają pojedynczy znak, zwiększają, zmniejszają lub przewijają, a następnie wklejają na miejscu.


Coś tu jest nie tak, ale będę pamiętać o tym pomyśle, być może można go ulepszyć. Powinien przeskakiwać do pierwszej cyfry w bieżącej linii, jeśli taka istnieje i działać na niej. Najlepiej jest <c-a>/<c-x>również odwzorować na .
— firedev

Zaktualizowana wersja. Teraz przeskakuje do przodu do następnej liczby lub jeśli aktualnie znajdujesz się powyżej cyfry, możesz ją zwiększyć.
— jecxjo

Tak! To jest niesamowite, dziękuję! Nie rozumiem, dlaczego kwestia została downvoted choć było to irytujące mnie, ponieważ jeden dzień i widocznie wiele osób przedefiniować <c-a>i <c-x>na coś innego, ponieważ domyślne zachowanie nie jest przydatna.
— firedev

Widziałem, że zostało to zanegowane, ponieważ pytanie dotyczyło czegoś bardzo konkretnego, a pierwotne pytanie zmieniło się po drodze ... potrzeba przeskoczenia do pierwszej liczby. Poza tym faktycznie używam <c-a>i <c-x>dużo. Za każdym razem, gdy aktualizuję wersję lub zwiększam zmienną zakresu, po prostu [N]<c-a>zamiast kasować i zamieniać.
— jecxjo 15.04.15

1
Byłoby to możliwe, ale byłby to znacznie większy zestaw funkcji. Obecna implementacja wykorzystuje <c-a>i <c-x>które musiałyby zostać usunięte za pomocą funkcji, która robi to samo, ale ignoruje kreskę.
— jecxjo

5

Oto wersja, którą napisałem, używając wyrażenia zastępczego:

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>

Każdy z nich po prostu szuka pierwszej cyfry w wierszu i dodaje lub odejmuje jeden, jeśli jest w zakresie odpowiednio [0–8] lub [1-9]. Ma trzy problemy:

  1. Chodzi głównie o manipulację tekstem i patrzy tylko na pierwszy znak, więc nie wie, czy liczba jest ujemna. Można to naprawić, ale podoba mi się obecne zachowanie.
  2. Blokuje rejestr wyszukiwania: "/a jeśli masz włączone wyszukiwanie, wówczas wszystkie liczby w bieżącym buforze zostaną podświetlone, gdy go użyjesz. Możesz dołączyć :noh<CR>do każdego z powyższych mappoleceń, aby zatrzymać podświetlanie, ale nie wiem, jak ładnie zatrzymać rejestr przed zablokowaniem.
  3. Działa na pierwszej liczbie w linii, a nie na pierwszej liczbie po kursorze.

Ponadto, gdybym to był ja, zamapowałbym powyższe na <leader>ai <leader>xzamiast na CTRL-A/X. W ten sposób masz do dyspozycji oba zachowania. <leader>jest domyślnie klawiszem ukośnika odwrotnego ( \).


Fakt, że pomija liczbę ujemną, jest w porządku, w rzeczywistości zachowanie domyślne wydawało mi się dziwne. Myślę, że z tym też wygląda znacznie lepiej :noh. Ale prawdziwym problemem jest to, że nie można użyć pozycji kursora jako podstawy, a zatem można zwiększyć tylko pierwszą cyfrę w linii.
— firedev

To kończy się na cyfrze 9, a powyżej 10 zwiększa się o 11, a nie o 10 ... Myślę, że to niezamierzone (np. Błąd)? Ponadto zawsze chcesz używać mapowania nierekurencyjnego ( noremap) i nigdy map . Zobacz tę stronę, aby uzyskać bardziej szczegółowe wyjaśnienie tego.
— Martin Tournoij
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.