I often work on CSS files or other files that require twiddling numbers. I would love the ability to have a key that refers to integers much in the way that w
refers to a word, or (
refers to a sentence. For example, in a css file I could navigate to the beginning of a height declaration, and change it's value without having to retype "px" a the end, which is what happens if I use w
.
Is there such a thing, but I'm missing it in the documentation, or is there a way to add this functionality to my .vimrc?
Bonus points if there were a way to use it like ci"
where I could be at the begining of the line and use the "change internal" command to jump to AND change the next integer.
More bonus points if I could do simple arithmetic. I would love to be able to issue a concise command that was short for "Add too, internal, integer, 5" and have the next integer on the current line be five grater then it was when I started.
Edit:
Some really great proposals everyone, some great ideas that are sure to improve my work. Thanks! Hassek's answer is probably the most likely to end up in my work-flow, but none of the others seem to have (fully) answered my inital question: A motion that works on integers. The proposal tracked down by romainl appears to have that goal, but I can't get it to work reliably.
For myself (and others perhaps) I will clarify my wants below:
A key that acts much in the way w
acts for words, but on integers so that I can simply add it to my mental vim vocabulary and use it seamlessly. This includes the following scenarios. (I will use d
as my example key):
d
: Jump to the next integercd
: Change to the end of the integer under the cursor (Note that cw
is a special case that SHOULD change to the NEXT word. cw
actually acts like ce
.) I would expect this special case to be implemented with integers as wellid
: Select [count] integers.ad
: Select [count] integers. Leading or trailing white space is included.Am I missing any behavior that w
has that might be expected for a new motion? Is there even a key available in both normal and visual modes?
Every motion can be used after an operator command, so the command operates on the text comprised by the movement's reach. Just like operator commands, motions can include a count, so you can move by 2w ords, for example. In Vim, normal arrow/cursor keys ( ← ↓ ↑ →) work as expected.
In Vim, these higher-level contexts are called text objects. Vim provides text objects for both plaintext and common programming language constructs. You can also define new text objects using Vim script. Learning these text objects can take your Vim editing to a whole new level of precision and speed.
Note: Vim recognizes two kinds of movement: operator movement ( :help movement) and jumps ( :help jumplist ). Movements like those executed with g ( gg, G, g,) count as jumps, as do changes. Changes get their own jumplist, which is navigable as mentioned above via g, and g; (see :help changelist ).
Just like operator commands, motions can include a count, so you can move by 2w ords, for example. In Vim, normal arrow/cursor keys ( ← ↓ ↑ →) work as expected.
you can add or substract from integers using this commands:
<num>Ctrl-a (to add)
<num>Ctrl-x (to substract)
and it will go right to the next number in line and execute the command
See this proposal. It looks good.
edit
Indeed that one is quite nice. This made me think that my habit of doing /<number><Esc>
was not very efficient so I've added these mappings (and slightly modified the mappings above for consistency) to my ~/.vimrc
. Let's see if they are useful in the long run:
nnoremap è /\v\d+<CR>
nnoremap é ?\v\d+<CR>
At first sight, èciè132<Esc>
seems to be marginally better than /2<Esc>{count}s132<Esc>
in terms of keypresses but substantially better if it allows me to skip a. checking the first digit of the value I want to change and b. counting the characters to replace.
Time will tell.
re-edit
Here are the function and its mappings:
onoremap N :<c-u>call <SID>NumberTextObject(0)<cr>
xnoremap N :<c-u>call <SID>NumberTextObject(0)<cr>
onoremap aN :<c-u>call <SID>NumberTextObject(1)<cr>
xnoremap aN :<c-u>call <SID>NumberTextObject(1)<cr>
onoremap iN :<c-u>call <SID>NumberTextObject(1)<cr>
xnoremap iN :<c-u>call <SID>NumberTextObject(1)<cr>
function! s:NumberTextObject(whole)
normal! v
while getline('.')[col('.')] =~# '\v[0-9]'
normal! l
endwhile
if a:whole
normal! o
while col('.') > 1 && getline('.')[col('.') - 2] =~# '\v[0-9]'
normal! h
endwhile
endif
endfunction
With this, I can:
vcdy
part of a number from the cursor until its end with <command>N
. Somehow similarly to <command>e
or <command>w
.
Here are some random numbers: 24 7635 1000018
^--->
It doesn't work if the cursor is not already on the number and it doesn't go backward.
vcdy
a whole number with <command>iN
.
Here are some random numbers: 24 7635 1000018
<-^--->
Again, it doesn't work if the cursor is not already on the number.
The whole thing could be improved, sure, but that's a start!
endedit
I work a lot with CSS, too.
I use two strategies to change numerical values:
{count}<C-a>
and {count}<C-x>
, as in Hassek's answer, when I know by how much I want to increment/decrement the number. Say I want to turn 20px
into 25px
, a simple 5<C-a>
does the trick without requiring me to move the cursor to the number. This is extremely cool.
/<number><CR>{count}s<new number>
when the new value is very different from the current value and I feel to lazy to calculate the delta. /2<CR>2s67<Esc>
would allow me to change 23px
into 67px
. /2<CR>R67<Esc>
is another way but it's only good if the new value as the same length as the current value. Use f<number>
if you are on the same line.
Note that you can insert the result of expressions with <C-r>=137-42<CR>
which I use it very often as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With