Насколько я знаю, нет способа изменить поведение команды yank, чтобы она работала так, как вы хотите, чтобы она работала, поскольку значения ". + X" раскрываются до того, как они попадают в саму команду, иЯ не знаю ни одного способа изменить поведение этого.
Но, с небольшим vimscript, эта проблема разрешима.Я написал пару функций vim, которые позволят вам выполнить точную логику, которую вы хотите сделать.
Этот фрагмент кода позволит вам выполнить команду yank с относительным диапазоном относительно текущего местоположения и командубудет работать так, как вы хотите:
" This file is created to handle the case in which the y ex command behaves
" different than expected when it is run with relative line number.
" Those functions behaves a bit different than the behavior of the y command,
" the y command gets the argument as range before it, with a range relative or
" absolute. The functions in this module gets a relative range from the current
" line (they can get a negative range as well).
" Those functions have commands at the bottom of the script, they should be used
" to run the function (and can be re-mapped to different values, for shorter
" typing).
" Yank a single line, getting only the line you want to yank. The value of the
" line should be relative to the current line.
function! s:YankByEnd(end_line)
" Save the current location, to know where to return to.
let current_line = line('.')
" Copy the wanted line.
if a:end_line > 0
execute 'normal ' . string(a:end_line) . 'jyy'
elseif a:end_line < 0
let move_by = a:end_line * -1
execute 'normal ' . string(move_by) . 'kyy'
else
execute 'normal yy'
endif
" Return to the original location.
execute 'normal ' . current_line . 'gg'
endfunction
" Yank a range of lines, getting the lines you want to yank. The value of the
" lines should be relative to the current line.
function! s:YankByStartAndEnd(start_line, end_line)
" Save the current location, to know where to return to.
let current_line = line('.')
" Get the start line.
if a:start_line > 0
execute 'normal ' . string(a:start_line) . 'j'
elseif a:start_line < 0
let move_by = a:start_line * -1
execute 'normal ' . string(move_by) . 'k'
endif
let start_line = line('.')
execute 'normal ' . current_line . 'gg'
" Get the end line.
if a:end_line > 0
execute 'normal ' . string(a:end_line) . 'j'
elseif a:end_line < 0
let move_by = a:end_line * -1
execute 'normal ' . string(move_by) . 'k'
endif
let end_line = line('.')
execute 'normal ' . current_line . 'gg'
" Copy the lines
execute start_line . "," end_line . "yank"
" Return to the original location.
execute 'normal ' . current_line . 'gg'
endfunction
command! -nargs=1 YankSingleLine call <SID>YankByEnd(<f-args>)
command! -nargs=* YankMultipleLines call <SID>YankByStartAndEnd(<f-args>)
Если вы добавите этот файл и отправите его в исходный код (или добавите его непосредственно в ваш vimrc), вы сможете запускать команды так, как вы этого хотите.Например, чтобы запустить команду, которую вы хотели запустить в исходном примере, просто запустите команду:
:YankSingleLine -2
, и требуемая строка будет восстановлена.
У меня также есть скриптэто делает то же самое, но это более общий способ, позволяющий запускать больше команд, а не только конкретную команду yank.Это скрипт:
" This file is created to handle the case in which an ex command behaves
" different than expected when it is run with relative line number and folds.
" Those functions behaves a bit different than the behavior of the regular ex
" command.
" A regular ex command gets the argument as range before it, with a range
" relative or absolute. The functions in this module gets a relative range
" from the current line (they can get a negative range as well) and the command
" to run.
" Run an ex command on a single line. The value of the line should be relative
" to the current line.
function! RunByEnd(end_line, command)
" Save the current location, to know where to return to.
let current_line = line('.')
" Get the line to run the command on.
if a:end_line > 0
execute 'normal ' . string(a:end_line) . 'j'
elseif a:end_line < 0
let move_by = a:end_line * -1
execute 'normal ' . string(move_by) . 'k'
endif
let end_line = line(".")
" Get back to the original location.
execute 'normal ' . current_line . 'gg'
" Run the command.
execute end_line . a:command
endfunction
" Run an ex command on a range of lines. The value of the lines should be
" relative to the current line.
function! RunByStartAndEnd(start_line, end_line, command)
" Save the current location, to know where to return to.
let current_line = line('.')
" Get the start line.
if a:start_line > 0
execute 'normal ' . string(a:start_line) . 'j'
elseif a:start_line < 0
let move_by = a:start_line * -1
execute 'normal ' . string(move_by) . 'k'
endif
let start_line = line('.')
execute 'normal ' . current_line . 'gg'
" Get the end line.
if a:end_line > 0
execute 'normal ' . string(a:end_line) . 'j'
elseif a:end_line < 0
let move_by = a:end_line * -1
execute 'normal ' . string(move_by) . 'k'
endif
let end_line = line('.')
" Return to the original location.
execute 'normal ' . current_line . 'gg'
" Run the given command.
execute start_line . "," end_line . a:command
endfunction
Используя его, вы сможете выполнить любую команду, какую захотите, но вам нужно добавить оригинальную команду, которую вы хотели выполнить.
Исправитьу вас проблемы с использованием этого скрипта, вы можете запустить команду:
: вызов RunByEnd (-2, "y")