I had the following mapping to go to the 1st non blank character of a line

nnoremap M ^

I then decided that if I was already at the 1st non blank character I wanted M to take me to the absolute 1st character of the line.
I was able to hack together the following vimscript function to do this.

func Mbehaviour()
    let origPos = getcurpos()
    normal! ^
    let newPos = getcurpos()
    call setpos('.', origPos)
    if newPos == origPos
        execute "normal! \<Home>"
        normal! ^

& then map this to M with

nnoremap M :call Mbehaviour()<CR>  

My question is how can I get the same thing to work in visual mode?


In lh-cpp, I have a single (old) function that can be used from all three modes.

inoremap <silent> <Home> <c-o>@=<SID>HomeLikeVCpp()<cr>
nnoremap <silent> <Home> @=<SID>HomeLikeVCpp()<cr>
vnoremap <silent> <Home> @=<SID>HomeLikeVCpp()<cr>

function! s:HomeLikeVCpp()
  let ll = strpart(getline('.'), -1, col('.'))
  if ll =~ '^\s\+$' | return '0'
  else              | return '^'

I guess it could be rewritten as a :map-<expr> now.

Years later, I'm wondering why I was bothering to test a substring against a regex, while testing the current column is more than enough -- unless we really want to start with the first non blank character.

xnoremap <expr> <home> col('.') == 1 ? '^' : '0'
nnoremap <expr> <home> col('.') == 1 ? '^' : '0'
inoremap <expr> µ col('.') == 1 ? '<c-o>^' : '<c-o>0'

Anyway, don't fight with :normal. I found best to avoid this command from functions whenever I can. Keep it simple.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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