Vim Tips Wiki
Explore
Main Page
All Pages
Community
Interactive Maps
Community portal
To do
FANDOM
Fan Central
BETA
Games
Anime
Movies
TV
Video
Wikis
Explore Wikis
Community Central
Start a Wiki
Don't have an account?
Register
Sign In
Sign In
Register
Vim Tips Wiki
1,649
pages
Explore
Main Page
All Pages
Community
Interactive Maps
Community portal
To do
Editing
SmartHome and SmartEnd over wrapped lines
Back to page
Edit
Edit source
View history
Talk (0)
Edit Page
SmartHome and SmartEnd over wrapped lines
We recommend that you
log in
before editing. This will allow other users to leave you a message about your edit, and will let you track edits via your
Watchlist
.
Creating an account
is quick and free.
The edit appears to have already been undone.
Anti-spam check. Do
not
fill this in!
{{Duplicate|315}} <!-- both tips should be merged --> {{review}} {{TipImported |id=1061 |previous=1059 |next=1063 |created=2005 |complexity=intermediate |author=Gerald Lai |version=6.0 |rating=11/4 |category1=Moving |category2= }} The Smart Home function allows the cursor to toggle between the start position and the first non-whitespace character position of the line. This is useful for skipping past indentation, whether it be tabs or spaces. Likewise, the Smart End function toggles past trailing whitespaces at the end of a line. This topic has been discussed before, see [[VimTip315|Smart home]]. The reason I am bringing this up again is because previous implementations of the Smart Home functionality have not worked well over lines that are wrapped. The implementation below works pleasingly well even when lines are wrapped, stepping through the wrapped lines by <Home> or <End> one by one. It also solves the "<Home> for one character on a line" insert mode problem, and is Replace mode friendly. Of course, cursor positioning can be achieved via vanilla Vim way: using <code>0</code>, <code>^</code>, <code>g0</code>, <code>g$</code>, <code>g_</code>, etc, but it's easier and faster when two keys take care of all of the functions. Especially over wrapped lines. <pre> "place in vimrc nmap <silent><Home> :call SmartHome("n")<CR> nmap <silent><End> :call SmartEnd("n")<CR> imap <silent><Home> <C-r>=SmartHome("i")<CR> imap <silent><End> <C-r>=SmartEnd("i")<CR> vmap <silent><Home> <Esc>:call SmartHome("v")<CR> vmap <silent><End> <Esc>:call SmartEnd("v")<CR> function SmartHome(mode) let curcol = col(".") "gravitate towards beginning for wrapped lines if curcol > indent(".") + 2 call cursor(0, curcol - 1) endif if curcol == 1 || curcol > indent(".") + 1 if &wrap normal g^ else normal ^ endif else if &wrap normal g0 else normal 0 endif endif if a:mode == "v" normal msgv`s endif return "" endfunction function SmartEnd(mode) let curcol = col(".") let lastcol = a:mode == "i" ? col("$") : col("$") - 1 "gravitate towards ending for wrapped lines if curcol < lastcol - 1 call cursor(0, curcol + 1) endif if curcol < lastcol if &wrap normal g$ else normal $ endif else normal g_ endif "correct edit mode cursor position, put after current character if a:mode == "i" call cursor(0, col(".") + 1) endif if a:mode == "v" normal msgv`s endif return "" endfunction </pre> ==Comments== To make SmartEnd work properly with multi-byte characters, use current character's length to move cursor rightward, instead of move by 1 byte. Reason: under a multi-byte character, move cursor 1 byte further might have no effect. For example, use <code>yl</code> and <code>byteidx()</code> to get the length (this overwrites current used register) <pre>function SmartEnd(mode) let curcol = col(".") let lastcol = a:mode == "i" ? col("$") : col("$") - 1 "gravitate towards ending for wrapped lines if curcol < lastcol - 1 normal yl let l:charlen = byteidx(getreg(), 1) call cursor(0, curcol + l:charlen) endif if curcol < lastcol if &wrap normal g$ else normal $ endif else normal g_ endif "correct edit mode cursor position, put after current character if a:mode == "i" normal yl let l:charlen = byteidx(getreg(), 1) call cursor(0, col(".") + l:charlen) endif if a:mode == "v" normal msgv`s endif return "" endfunction </pre> ---- This tip and [[VimTip315]] and gave me some great ideas for my own <Home> and <End> keys. I also studied some great ideas from a URL mentioned in [[VimTip315]]: http://hermitte.free.fr/vim/ressources/vimfiles/plugin/homeLikeVC++_vim.html Try putting these in your vimrc. <pre> " map <Home> to move to first word in line " if at first word, move to beginning of line " if at beginning of line, move to beginning of window " if at beginning of window, move to beginning of file nnoremap <silent> <Home> :call SmartHome("n")<CR> inoremap <silent> <Home> <C-O>:call SmartHome("i")<CR> vnoremap <silent> <Home> <Esc>:call SmartHome("v")<CR> function! SmartHome(mode) if col('.') == 1 if line('.') == 1 return elseif winline() == &scrolloff+1 normal! m`gg else normal! m`H0 endif elseif strpart(getline('.'), -1, col('.')) =~ '^\s\+$' normal! 0 else normal! ^ endif if a:mode == "v" normal! msgv`s endif endfun " map <End> to move to end of line " if at end of line, move to end of window " if at end of window, move to end of file nnoremap <silent> <End> :call SmartEnd("n")<CR> inoremap <silent> <End> <C-O>:call SmartEnd("i")<CR> vnoremap <silent> <End> <Esc>:call SmartEnd("v")<CR> function! SmartEnd(mode) if col('.') < col('$')-1 normal! $ elseif winline() < winheight(0) - &scrolloff normal! m`L$ else normal! m`G$ endif if a:mode == "v" normal! msgv`s endif endfun </pre> ----
Summary:
Please note that all contributions to the Vim Tips Wiki are considered to be released under the CC-BY-SA
Cancel
Editing help
(opens in new window)
Templates used on this page:
Template:Duplicate
(
view source
)
Template:Navigation
(
view source
)
Template:Review
(
view source
)
Template:TipImported
(
view source
)
Follow on IG
TikTok
Join Fan Lab