4

I would like to map H to execute a function, which does the following:

  • If cursor on first column: Wrap around/Move cursor to end of the current line
  • If cursor before/on first non-whitespace character of line: Move cursor to first column
  • If cursor after first non-whitespace character of line:
    • If cursor less then five columns to the right of the first non-whitespace character of line: Move cursor to first non-whitespace character of line.
    • Otherwise: Move cursor five columns to the left.

Sadly I never wrote a single function in vimscript and have no idea how to translate this idea into real code. Does anyone have an idea where I should look into to learn how to create this function?

3
  • 1
    These functions I wrote could give you some inspiration. The H one makes h go to the beginning of the line when the cursor is on the first non white character and go one character to the left if the cursor is anywhere else.
    – statox
    Sep 21, 2016 at 12:43
  • @statox Thank you! I'll definitely take a look :)
    – user9334
    Sep 21, 2016 at 12:48
  • Here's a similar question
    – Tumbler41
    Sep 21, 2016 at 15:17

1 Answer 1

4

You could try to add this to your .vimrc I didn't tested it extensively but it looks like it is working.

function! MyHMotion()
    " Get the position of the cursor and of the first non white character
    let cursorPosition=getpos(".")
    normal! ^
    let firstChar=getpos(".")

    if cursorPosition[2] == 1
        " Cursor on first column : go to the end of line
        normal! $
    elseif cursorPosition[2] <= firstChar[2]
        " Cursor before/on first non-whitespace character: go to first column
        normal! 0    
    elseif cursorPosition[2] <= firstChar[2]+5
        " cursor less than five columns after the first non-whitespace character: go to first non-white character
        normal! ^
    else
        " Move normally
        call setpos('.', cursorPosition)
        normal! h
    endif
endfunction

nnoremap <silent> h :call MyHMotion()<CR>

The function is commented and its behavior should be pretty clear. Here are some additional information:

  • The ! following normal is here so that the command will not use user-defined mappings. More info at :h normal
  • The last line nnoremap <silent> h :call MyHMotion()<CR> is here to map h so that the function MyHMotion() is called each time you press the key.
  • The <silent> argument is here so that nothing is echoed on the command line when the function is called. See :h :map-silent

I used these functions of mine as inspiration. They override h and l to skip the whitespaces at the beginning of a line:

" make h and l skip indentation white spaces {{{
    function! MyLMotion()
        let cursorPosition=getpos(".")
        normal! ^
        let firstChar=getpos(".")

        if cursorPosition[2] < firstChar[2]
            normal! ^
        else
            call setpos('.', cursorPosition)
            normal! l
        endif
    endfunction

    function! MyHMotion()
        let cursorPosition=getpos(".")
        normal! ^
        let firstChar=getpos(".")

        if cursorPosition[2] <= firstChar[2]
            normal! 0
        else
            call setpos('.', cursorPosition)
            normal! h
        endif
    endfunction

    nnoremap <silent> h :call MyHMotion()<CR>
    nnoremap <silent> l :call MyLMotion()<CR>
"}}}
10
  • Thank you really much. Your code makes sense to me. I'll play around with it a bit and accept the answer later :)
    – user9334
    Sep 21, 2016 at 13:00
  • @Herickson you're welcome, if you encounter a problem don't hesitate to let me know I'll see how to fix it.
    – statox
    Sep 21, 2016 at 13:01
  • I'm currently wondering, what the exclamation mark after the normal means. Sometimes it's there, sometimes it's not.
    – user9334
    Sep 21, 2016 at 13:02
  • It should be always there (I'll correct that) it makes normal use the default action of the key. For example if you had used nnoremap 0 :echo "foo"<CR> using normal 0 would output "foo" as your mapping defined it but using normal! 0 would go to the beginning of the line no matter what mapping you created.
    – statox
    Sep 21, 2016 at 13:06
  • 1
    Ok, I understood "Wrap around" to be go to the end of the previous line.
    – Tumbler41
    Sep 21, 2016 at 15:48

Your Answer

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