Is there a way to flip the bit under your cursor in (n)vim?

95 views Asked by At

I do some low level programming which involves a decent about of bit manipulation. It would be very useful if I could somehow flip 1 to 0 and vice versa under my cursor. I couldn't find any built in function or installable plugin, and I don't really know to write a macro for that.

My go to so far is r and then typing the bit I want to flip it to, but if there is a way to do this easier (IE, without remembering the previous bit and what I want to flip it to) that would be great.

Currently I just use r and then typing the bit, which works but isn't ideal.

2

There are 2 answers

0
Hi computer On

Put this code into your vimrc file, restart Vim, put cursor where you want to change bit, and hit ` (backtick / key to the left of 1).

This code checks whether bit under cursor is '1', if it is, change it to 0 else change to 1.

function! Flip()
    if getline(".")[col(".")-1] == '1'
        normal! r0
    else
        normal! r1
    endif
endfunction
nnoremap ` :call Flip()<CR>
0
Friedrich On

The following one-liner will flip a 0's and 1's under the cursor:

nnoremap <leader>f cl<C-R>=@"=='0'?1:0<CR><Esc>

This creates a mapping for <leader>f - feel free to pick any key(s) of your choice.

In the mapping, we start with cl which will delete the next character and enter insert mode. In insert mode, we access the expression register through <C-R>= and make it evaluate a ternary expression to insert either '0' or '1'. This depends on the value of the default register " which conveniently contains the character we just cut thorugh cl. With <CR> we make the expression register evaluate and the final <Esc> will return us to normal mode.

We need cl instead of r because the latter doesn't allow us to access registers. It also does not populate the default register ".

Minor caveat compared to an r-based solution is that this will clobber your unnamed register. Most of the time we don't care about it. However, if you find that unacceptable, you could use a sacrificial register both for cl and in the ternary's condition.

For reference, see :help i_CTRL-R, :help quote= and :help ternary.