70

In Vim, is there a way to move the cursor to the beginning of non-whitespace characters in a line? For instance, how can I move the cursor to the "S" in the second line below?

First line
    Second line

If it matters, I primarily use MacVim, but I'd also like to be able to do this from the console.

Thanks!

Joe Mornin
  • 1,707

9 Answers9

84

Instead of pressing ^ you can press _(underscore) to jump to the first non-whitespace character on the same line the cursor is on.

+ and - jump to the first non-whitespace character on the next / previous line.

(These commands only work in normal mode, not in insert mode.)

Ben
  • 941
81

If I understand correctly - from :h ^:

^ To the first non-blank character of the line.
  |exclusive| motion.

(in contrast to 0, which gets you to the beginning, regardless of whitespace or not)

slhck
  • 235,242
14

Also possibly useful: + and - will move the cursor up or down, respectively, to the first non-blank character.

shmup
  • 310
7

below is a snippet from by .vimrc
^[[1~ is created by pressing ctrl+v and Home

"jump to first non-whitespace on line, jump to begining of line if already at first non-whitespace
map <Home> :call LineHome()<CR>:echo<CR>
imap <Home> <C-R>=LineHome()<CR>
map ^[[1~ :call LineHome()<CR>:echo<CR>
imap ^[[1~ <C-R>=LineHome()<CR>
function! LineHome()
  let x = col('.')
  execute "normal ^"
  if x == col('.')
    execute "normal 0"
  endif
  return ""
endfunction
Andrew Sohn
  • 171
  • 1
  • 3
1

I just remap the 0 key to ^

Edit your ~/.vimrc

set visualbell t_vb=
map 0 ^
0

Expanding on Andrew Sohn's answer, if you'd like to use 0 for this behavior, just wrap it like so:

function! LineHome()
  let x = col('.')
  execute "normal ^"
  if x == col('.')
    unmap 0
    execute "normal 0"
    map 0 :call LineHome()<CR>:echo<CR>
  endif
  return ""
endfunction 
0

And just for completeness, here is the dual of Andrew Sohn's Answer:

" jump to the last non-whitespace char on line, or eol if already there
map <End> :call LineEnd()<CR>:echo<CR>
imap <End> <C-R>=LineEnd()<CR>
function! LineEnd()
  let x = col('.')
    execute "normal g_"
  if x == col('.')
    execute "normal $"
  endif
 return ""
endfunction
MERM
  • 165
0

See Vi Reference Card under Motion:

next word, blank delimited word w, W

beginning of word, of blank delimited word b, B

0

If you are in visual mode, the LineHome function others have suggested drops you into normal mode and loses any selection you have. My solution is

map <expr> <Home> col('.') == indent(line('.')) + 1 ? "0" : "^"

which keeps you in whatever mode you're already in.

cmititiuc
  • 101
  • 2