How do you create a binding that behaves like yy but doesn't yank the leading white spaces?
nnoremap <leader>f ^v$y
Yanks one line and the ^J. Which is what I want but how do I add a [count] to do mulitple lines?
Vi and Vim Stack Exchange is a question and answer site for people using the vi and Vim families of text editors. It only takes a minute to sign up.Sign up to join this community
Your mapping is tricky because you don't want to yank the leading whitespaces. You cannot simply supply a count to your map as you would do for an operator. You need to define a new
command with the
-count attribute, or a new function and bind it using
I came up with this :
command! -count=1 YY let @"=join(map(getline(line('.'), line('.')+<count>-1), 'substitute(v:val, "^\\s*", "", "")'),"\<nl>")."\<nl>" nnoremap <silent> <leader>f :<c-u>execute v:count1 . 'YY'<CR>
which get the list of the current line and the
<count>-1 ones below (default is 1); removes their leading whitespaces; and join them in a single string with
^J) between and after; finally setting the result to the unnamed register
For a more "intuitive" solution without using Vimscript functions, you could do the following. It is more incremental, like if you were in normal mode.
function! YY(count) let l:s=@s " save register 's' let @s='' " empty register 's' let l:curpos = getcurpos() " save cursor position for l:i in range(a:count) " do your mapping but *append* to register 's' normal! ^v$"Syj endfor " and move down one line. repeat call setpos('.', l:curpos) " restore cursor position let @"=@s " set unnamed register to register 's' let @s=l:s " restore register 's' endfunction nnoremap <silent> <leader>f :<c-u>call YY(v:count1)<CR>
Maybe someone has a better solution, this is all I got...
:h command-countand more generally
You can use the
v:count variable to access the count passed to a mapping.
If you don't pass any count, the
v:count variable will evaluate to zero. If you prefer something that evaluates to 1 instead, you can use
v:count1 which does just that.
For your particular use case, yanking without leading whitespace, my suggestion is to just yank the contents normally, then process the yank contents using
substitute() to strip leading whitespace.
When writing a mapping that does yanks, puts or deletes, you might also want to consider
v:register, in case the user specifies a non-default register when calling your mapping. You need to evaluate it early on in the mapping, since it may be overwritten by other commands you run, so best to pass it as an argument. You can then use
setreg() to set the register's contents.
Assuming you want to save the yank on the specified register only and not overwrite the default register (this is not how the
yy command works, but is a useful behavior), then this should work:
function! YankTrimLeadingSpace(register) let saved_unnamed_register = @@ execute 'normal!' v:count1.'yy' let @@ = substitute(@@, '\v(^|\n)\zs\s+', '', 'g') if a:register != '"' call setreg(a:register, @@) let @@ = saved_unnamed_register endif endfunction nnoremap <silent> <leader>f :<c-u>call YankTrimLeadingSpace(v:register)<cr>
It also works with uppercase register specifications, which will append to the existing registers. Works with and without a count.