As a general advice I would recommend to get used to the built-in behavior. I strongly believe that if you want to avoid any trouble your customization should extend vim's features and not modify them. However here is a solution:
There is no built-in mechanism to prevent these motions from changing lines, but you could hack something yourself! For example your can create a function like this:
function! MyMotion(motion)
let pos=getpos('.')
execute 'normal! ' . a:motion
if (pos[1] != getcurpos()[1])
call setpos('.', pos)
endif
endfunction
The function takes one motion (w
, ge
, ...) as argument. It saves the current position of the cursor with :h getpos()
, executes the motion and if the cursor is on a different line then it moves back the cursor to the previous position.
Now you will also need to create mappings like these:
nnoremap <silent> w :call MyMotion('w')<CR>
nnoremap <silent> W :call MyMotion('W')<CR>
nnoremap <silent> e :call MyMotion('e')<CR>
...
This way w
and W
will call your new function.
But since there is a lot of mappings to create you can use the following code:
let motions = ['w', 'W', 'b', 'B', 'e', 'E', 'ge', 'gE']
for motion in motions
execute "nnoremap <silent> " . motion . " :call MyMotion('" . motion . "')<CR>"
endfor
You create a list of the keys you want to remap and with a simple loop and the help of :h :execute
you create the relevant mappings.
I tested this solution very quickly and at first sight it seems to work but maybe there are some edge cases I didn't see.
Edit
I read your question again and realized that you want the cursor to end up on the beginning or end of the line rather than staying in the same position. You could easily do that by replacing the call to setpos
by normal! k$
or normal! j0
depending on the value of pos[1] - getcurpos()[1]
. That will be left as an exercise for the reader :)