0

I am trying to write a function that will only let me call nmap b when the cursor is not on the first column in the current window. This is to make b only work on the current line and encourage more efficient navigation bindings.

I wrote a function which does what I want:

function CurrentLineB() 
  let column = getcurpos()[2]
 echo column
 if column != 1
   normal b%
 endif
endfunction

When I call it with :call CurrentLineB() without binding it to b, it works as expected. When I map the function with nnoremap b :call CurrentLineB() the function keeps recurring without exiting.

How can I avoid this recursion, and make the function work as it did when it was not bound to b?

4
  • 1
    You need to use normal! instead of normal to make that call non-recursive. (I don't get the % there, is that a typo?)
    – filbranden
    Commented Apr 20, 2020 at 13:38
  • Perhaps much simpler as a one-liner: nnoremap <expr> b col('.') > 1 ? 'b' : ''
    – filbranden
    Commented Apr 20, 2020 at 13:39
  • Perfect, thank you!!
    – LUD
    Commented Apr 20, 2020 at 14:03
  • 1
    Posted an answer... There's more to it, actually. If the % is indeed a typo, can you please edit your question to remove it? (If it's not a typo, can you explain why you had it?)
    – filbranden
    Commented Apr 20, 2020 at 14:18

1 Answer 1

2

The issue with your function is that you're using plain normal, when you need normal! to make it non-recursive, which you need to ignore the b mapping you created. That should be enough to fix the problem.

But a simpler way to implement what you're trying to accomplish is to use an <expr> mapping and the ternary operator, to expand to b when on a column after 1, or to an empty string otherwise.

nnoremap <expr> b col('.') > 1 ? 'b' : ''

I also used col(), which is a more direct way to get the column.

Note that this mapping still doesn't work if you have a line with indentation, in which case it will move to the preceding line when sitting on the first character of the first indented word, or on an indentation character other than the first... You can use indent() to check for the indentation of the current line and compare it to virtcol() (to properly account for tabs):

nnoremap <expr> b virtcol('.') > indent('.') + 1 ? 'b' : ''

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.