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 communityHow 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?
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 v:count
.
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 <NL>
(^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...
Usefull helps.
:h command-count
and more generally :h user-commands
:h v:count
and h v:count1
:h function-list
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.
range
; (2) replace the execute 'normal!'...
line with execute a:firstline.','.a:lastline.'yank'
and (3) remove <c-u>
to the mapping. We can thus create an xnoremap
mapping just like the normal one. And the normal [count]<leader>f
still works as expected.
\n
in the regex is 'portable' ? Wouldn't it be safer to use \<nl>
?
\n
in the regex portable?" Yes. See :help /\n
which will show you it matches a newline. I also tested it with ff=dos
and ff=mac
. Internally, Vim keeps a consistent representation, just converting to the final platform at the last layer.
visualmode()
as an extra argument to the function and then yank inside it, that would allow handling char-wise or block-wise visual as well. (Similar to this?) But the normal version of this one is very line oriented, so ranges are probably a great translation of it? I'll update the answer with your suggestion.
]p
&[p
puts/pastes with the current indention level. See:h ]p