Vim Tips Wiki
Advertisement

Previous TipNext Tip

Tip: #315 - Smart home

Created: August 14, 2002 16:46 Complexity: advanced Author: Alex A. Naanou Version: 5.7 Karma: 35/22 Imported from: Tip#315

to make it faster to navigate through indented code here is a common way to "go home"...

fun! s:SmartHome() 
 if col('.') != match(getline('.'), '\S')+1 
 norm ^ 
 else 
 :call cursor(line('.'),2) 
 norm h 
 endif 
endfun
inoremap <silent><home> C-O > :call <SID>SmartHome()<CR>
nnoremap <silent><home> :call <SID>SmartHome()<CR> 
vnoremap <silent><home> :call <SID>SmartHome()<CR> 

what this snippet does is make the <home> key behave as it does in such IDEs as PythonWin or MSVisualStudio, and that is first go to the first non whitespace, and then to the first char on the line.

Comments

What's the point of this tip? I'm happy using ^ and 0 (zero).


Anonymous , August 15, 2002 1:16


nmap <HOME> ^ But, I agree with the previous comment, 0 and ^ are within finger reach.

Anonymous , August 15, 2002 4:33


This tip does have a point -- it's helpful for those who are transitioning from their favorite IDEs to Vim. I use 0 and ^ because I have them memorized, but others might not...

For those who spend a lot of time in their text editors, it's worth a few hours of learning up-front -- certainly, the time spent learning shortcuts like "*" and "t" pays for itself many times over. For others, who might spend only a little while with their editor, it might not. For them, it's useful to know that a few lines of code can make Vim behave like what they already know. And if you happen be such a person, you may wish to check out Cream, which makes Vim much easier to use for beginners: http://cream.sourceforge.net/

And, while I'm being unorthodox, I may as well add a question to my note: In some IDEs, the behavior of Home varies depending on how many times you press it. The first time, it goes to the beginning of the line; the second, to the top of the screen; and the third, to the top of the file. This is trivial to accomplish in Vim -- something like

map <HOME> ^ map <HOME><HOME> H map <HOME><HOME><HOME> gg

But Vim will hesitate after the first Home press to see if you are going to press Home again (and likewise for the second Home). This interval can be adjusted with the (t)timeoutlen option, but it is difficult to select a value that makes <HOME> near-instantaneous and still make the whole sequence easy to enter without hand spasms.

Is there any way to see what the last few keypresses were? If so, it'd be fairly simple to check them and behave correctly. Or, I suppose, you could check and see if the cursor was _already_ at the beginning of the line (or at the top of the screen) and behave correctly. Hmmm.

jmcpherson--AT--softhome.net , August 15, 2002 10:38


"Banging" the "normal" calls could be useful.

Otherwise, here is another way to do the same thing : http://hermitte.free.fr/vim/ressources/vimfiles/plugin/homeLikeVC++.vim

hermitte at free.fr , August 15, 2002 13:29


indeed '0' and '^' are the natural and fast way to use, unless you are in insert mode, and then it turns into '<home>' and '<C-O>^'. the later takes two keystrokes "longer" to type, and is used more often (at least by me)! 'imap <home> <C-O>^' would have been easier to write, but my goal was to make it both as simple (from the users' point of view) and as fast as possible.. the perfect solution in my opinion was the way it was done by the packages I mentioned in the tip.


P.S. I'm on vim since version 4.3a3 (WVim to be exact) :)

Best Regards... Alex.

Alex A. Naanou <alex_nanou--AT--yahoo.com> , August 15, 2002 15:56


I don't own a keyboard where the home key is any near my fingers, so I prefer to use '^' and the like. Considering the time it takes to go into normal mode, do my thing and then return to insert mode rather than using home, this function is useless; to me, anyway.

Simon Shine <simon at blueshell.dk> , August 19, 2002 11:13


Unless I'm confused, why not just use the function like so:

fun! s:SmartHome()

if col('.') == 1 
norm ^ 
else 
norm 0 
endif 

endfun

Please send me email in this regard...

lailoken--AT--freeshell.org , August 26, 2002 9:17


Thanks for the remark!!!

The function mentioned above is OK, but the thing I wanted is to do '^' if we are not on the first non-whitespace else do '0'. the proposed above function does the opposite (first '0' then '^') 

// And I must admit that my original else clause is over-complicated!! (using norm 0 is sufficient) :)

and here we have the new and improved version:

fun! s:SmartHome() 
 " this line checks if we are not on the first whitespace. 
 if col('.') != match(getline('.'), '\S')+1 
 norm ^ 
 else 
 norm 0 
 endif 
endfun 
inoremap <silent><home> <C-O>:call <SID>SmartHome()<CR> 
nnoremap <silent><home> :call <SID>SmartHome()<CR> 
vnoremap <silent><home> :call <SID>SmartHome()<CR> 

Thanks again!

Alex A. Naanou <alex_nanou--AT--yahoo.com> , August 28, 2002 16:23


Great tip! I prefer it to only go to first column when current column is between first column and second character:

function SmartHome() 
 if col(".") == 1 || col(".") > match(getline("."), '\S') + 1 
 normal g^ 
 else 
 normal g0 
 endif 
endfunction

Gerald Lai , May 4, 2005 18:38


Thankyou very much for the tip. It is very useful, both for the code, and the knowledge of the "^" and "0" keys.

jhales.perth--AT--gmail.com , June 13, 2006 7:12


Advertisement