Wie Strg-A und Strg-X, jedoch nur die erste Ziffer ändern

10

Gibt es eine Möglichkeit, die erste Ziffer nach / unter dem Cursor zu erhöhen / zu verringern, nicht die ganze Zahl?

Ich weiß, dass vim nicht so funktioniert, aber gibt es ein Plugin, das das macht? Ich konnte es nicht finden.

Dies ist sehr nützlich beim Bearbeiten von CSS und in anderen Fällen auch.

Gegeben:

▐margin: 10px

Wenn ich drücke, CTRL-Amöchte ich sehen:

▐margin: 20px

Tatsächlich:

▐margin: 11px
Firedev
quelle
10
Sie können auch 10<C-a>10 hinzufügen oder r2die 1 durch eine 2 ersetzen.
jamessan

Antworten:

6

Dies scheint recht gut zu funktionieren und macht ziemlich vernünftige Dinge, wenn Sie <C-a>eine 9 verwenden (95 wird 105) oder wenn Sie <C-x>eine 0 verwenden (105 wird 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
  • Zunächst suchen wir nach einer beliebigen Ziffer, search()die den Vorteil hat, dass sie nicht zurückgesetzt wird @/.
  • a <Esc>h - Wechseln Sie in den Einfügemodus, fügen Sie nach der Ziffer ein Leerzeichen ein und gehen Sie nach links, sodass sich der Cursor über der Ziffer befindet.
  • Wir können jetzt <C-a>oder verwenden <C-x>.
  • Wir verwenden lxh, um den hinzugefügten Speicherplatz zu entfernen.

Ich habe dies auf g<C-a>und abgebildet g<C-x>, sodass Sie das Original weiterhin aufrufen können.

Eine etwas andere Version, die nur nach Zahlen in der aktuellen Zeile sucht (aber ein baumelndes Leerzeichen lässt, wenn in der aktuellen Zeile keine Nummer vorhanden ist):

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

Und hier ist eine andere Version, die das gleiche Konzept wie zuvor verwendet, aber auch ein Leerzeichen vor der Ziffer hinzufügt . Dadurch wird g<C-a>jedes munis Zeichen vor der Nummer ignorieren (standardmäßig <C-a>auf -42Willen ‚increment‘ es -41.

Es akzeptiert auch eine Zählung, so dass 5g<C-a>die Zahl um 5 erhöht wird:

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
quelle
9

Grundlegendes Inkrement

Hier ist ein einfaches Makro, um die Aktion auszuführen:

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

Im normalen Modus Sie

  • m` Markieren Sie Ihren Standort
  • l Bewegen Sie ein Zeichen nach rechts
  • v$x bis zum Ende der Linie schneiden
  • h Gehen Sie zurück in die ursprüngliche Position
  • <c-a> Inkrementieren (oder Dekrementieren)
  • p Fügen Sie Ihren Schnitt zurück
  • `` gehe zurück zu deiner Marke

Zur nächsten Nummer springen

Wenn Sie zur nächsten Nummer springen möchten (oder an Ihrer aktuellen Position bleiben möchten, wenn Sie eine Nummer haben), benötigen Sie eine Funktion, die das aktuelle verfluchte Zeichen überprüft und möglicherweise zur nächsten Nummer springt.

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

NextNumRuft das Zeichen unter den Cursor, prüft, ob es eine Zahl ist und sucht nicht nach der nächsten Zahl. Danach ist der Rest der gleiche. Wenn Sie die Zuordnung verschiedener wollen ändern , nur das nnoremap <leader>a, was Sie wollen, zum Beispiel nnoremap <c-a>.

Negative und Zahlen über 9 ignorieren

Wenn Sie nur durch Ziffern blättern möchten und diese nicht als vorzeichenbehaftete Ganzzahlen fungieren möchten, werden die folgenden Funktionen inkrementiert und dekrementiert und bei 0 und 9 verschoben.

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>

Jetzt, wenn Sie eingeschaltet sind 8und tippen, erhalten <leader>aSie 9. Wenn Sie es erneut tun, erhalten Sie 0. Wenn Sie drücken <leader>xauf 0Sie bekommen 9. Gleiches gilt für negative Zahlen. Die Funktionen schneiden ein einzelnes Zeichen aus, erhöhen, verringern oder verschieben es und fügen es dann ein.

jecxjo
quelle
Hier stimmt etwas nicht, aber ich werde diese Idee im Hinterkopf behalten, vielleicht kann sie verbessert werden. Es sollte zur ersten Ziffer in der aktuellen Zeile springen, falls vorhanden, und daran arbeiten. Vorzugsweise auch abbildbar sein <c-a>/<c-x>.
Firedev
Die aktualisierte Version. Springt jetzt vorwärts zur nächsten Zahl oder wenn Sie sich gerade über einer Ziffer befinden, können Sie diese erhöhen.
Jecxjo
Ja! Das ist unglaublich, danke! Ich verstehe nicht, warum die Frage abgelehnt wurde, das hat mich seit dem ersten Tag geärgert und anscheinend viele Leute neu definiert <c-a>und <c-x>zu etwas anderem, weil das Standardverhalten nicht so nützlich ist.
Firedev
Ich konnte sehen, dass es herabgestimmt wird, weil die Frage für etwas sehr Spezifisches war und sich die ursprüngliche Frage auf dem Weg irgendwie geändert hat ... die Notwendigkeit, zur ersten Nummer zu springen. Davon abgesehen benutze ich tatsächlich <c-a>und <c-x>viel. Jedes Mal, wenn ich eine Version aktualisiere oder eine Bereichsvariable erhöhe, [N]<c-a>lösche und ersetze ich sie einfach .
Jecxjo
1
Es wäre möglich, wäre aber ein viel größerer Satz von Funktionen. Die aktuelle Implementierung nutzt <c-a>und <c-x>muss für eine Funktion gelöscht werden, die dasselbe tut, aber den Bindestrich ignoriert.
Jecxjo
5

Hier ist eine Version, die ich mit einem Ersatzausdruck geschrieben habe:

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>

Jeder sucht nur nach der ersten Ziffer in der Zeile und addiert oder subtrahiert eine, wenn sie im Bereich [0-8] bzw. [1-9] liegt. Es hat drei Probleme:

  1. Es handelt sich hauptsächlich um Textmanipulationen, bei denen nur das erste Zeichen betrachtet wird, sodass nicht bekannt ist, ob eine Zahl negativ ist. Dies ist behebbar, aber ich mag das aktuelle Verhalten wie es ist.
  2. Es durchsucht das Suchregister: "/und wenn Sie hlsearch aktiviert haben, werden alle Zahlen im aktuellen Puffer hervorgehoben, wenn Sie dies verwenden. Sie können :noh<CR>an jeden der oben genannten mapBefehle anhängen , um die Hervorhebung zu stoppen, aber ich weiß nicht, wie ich verhindern kann, dass das Register blockiert wird.
  3. Es funktioniert mit der ersten Zahl in der Zeile, nicht mit der ersten Zahl nach dem Cursor.

Wenn ich es wäre, würde ich das Obige eher auf <leader>aund <leader>xals auf abbilden CTRL-A/X. Auf diese Weise stehen Ihnen beide Verhaltensweisen zur Verfügung. <leader>ist standardmäßig der Backslash-Schlüssel ( \).

Cookyt
quelle
Die Tatsache, dass negative Zahlen nicht berücksichtigt werden, ist in Ordnung. Tatsächlich schien mir das Standardverhalten seltsam. Ich denke, es sieht auch viel besser aus :noh. Das eigentliche Problem ist jedoch, dass die Cursorposition nicht als Basis verwendet werden kann und Sie daher nur die erste Ziffer in der Zeile erhöhen können.
Firedev
Dies hört bei der Zahl 9 auf und erhöht sich über 10 um 11, nicht um 10 ... Ich denke, das ist unbeabsichtigt (dh ein Fehler)? Außerdem möchten Sie immer nicht rekursives Mapping ( noremap) verwenden und niemals map . Auf dieser Seite finden Sie eine ausführlichere Erklärung.
Martin Tournoij