Takes you to the first character of the line, unless you're already between 0 and ^; if so, move to 0. The EoL movement is sensitive to the &virtualedit state. (Less useful if you don't toggle virtualedit often)
" SoL-EoL motion
noremap <expr><A-h>
\ (col('.') - 1) &&
\ match(getline('.'), '\S') >= col('.') - 1
\ ? '0' : '^'
map <A-l> $
xnoremap <expr>$ (&ve=~#'onemore'<Bar><Bar>&ve==#'all') ? '$h' : '$'
" Or just use them as your zero/dollar:
"
" noremap <expr>0 (col('.') - 1) && match(getline('.'),'\S')>= col('.')-1
" \ ? '0' : '^'
" xnoremap <expr>$ (&ve=~#'onemore'<Bar><Bar>&ve==#'all') ? '$h' : '$'