Восстановление реестра после вызова функции ‹C-r›

В настоящее время я пишу плагин для Vim, и мне хотелось бы, чтобы он восстанавливал регистр по умолчанию после того, как я его запустил. Однако рассматриваемая функция вызывается через конструкцию <C-r>=Myfunction()<CR>, что означает, что мне нужно восстановить ее после возврата из функции. Я пробовал сделать это так:

inoremap <silent> <Space> <C-r>=Myfunction()<CR>
function! Myfunction()
    let oldreg      = getreg('"')
    let oldregtype  = getregtype('"')
    let restore     = "\<ESC>:call setreg('\"','".oldreg."','".oldregtype."')\<CR>a"

    let @" = "whatever"

    return "\<ESC>yya ".restore
endfunction

Как видите, на регистр " влияет возвращаемая строка, поэтому я не могу вызвать setreg напрямую. Очевидно, что эта функция на самом деле ничего не делает, но фактическая функция, которую я использую, довольно длинная. Кроме того, я прошу прощения, если эта строка немного трудна для чтения, но я не совсем уверен в другом способе сделать это. В общем, кажется, что функция работает, когда регистр содержит слово, но не работает всякий раз, когда что-то с новой строкой находится в регистре. (Конкретная ошибка - E115: Missing quote по отношению к аргументу oldreg.) Я попытался исправить это, предварительно сняв оболочку oldreg; однако это приводит к ошибке E121: Undefined Variable, где неопределенная переменная - это то, что было в моем регистре. Есть мысли о том, что здесь может быть не так?

РЕДАКТИРОВАТЬ: Я нашел решение. Это довольно сложно, но пока работает отлично. Вот как применить решение к моему примеру кода, на случай, если оно кому-то поможет.

inoremap <silent> <Space> <C-r>=Myfunction()<CR>
function! Myfunction()
    let oldreg      = substitute(escape(getreg('"'), '\\'), '\n', '\\n', 'g')
    let oldregtype  = getregtype('"')
    let restore     = "\<ESC>:call setreg('\"',\"".oldreg."\",'".oldregtype."')\<CR>a"

    let @" = "whatever"

    return "\<ESC>yya ".restore
endfunction

person Bennett Rennier    schedule 06.03.2017    source источник
comment
Проверьте Как создать минимальный, полный и проверяемый вопрос.   -  person Meninx - メネンックス    schedule 06.03.2017
comment
В настоящее время ваш пример не имеет для меня особого смысла, потому что я не вижу, что мешает вам просто вызвать setreg непосредственно в конце вашей функции. Что этому мешает? Зачем нужно сбросить его обратно после вызова функции? Если функция возвращает только строку? Вам нужно использовать "@ где-то еще? Это будет иметь смысл только в том случае, если вам нужно использовать его между концом MyFunction и <CR> в вашем вызове, чего в любом случае не произойдет. Извините, что мой комментарий не отвечает на вопрос, я просто пытаюсь понять вашу цель, так как кажется, что есть другой способ сделать это. :)   -  person sidyll    schedule 07.03.2017
comment
@sidyll в vim нет реестра с именем @.   -  person Meninx - メネンックス    schedule 07.03.2017
comment
Так что лучше поставить вопрос [отложить] до дальнейшего прояснения.   -  person Meninx - メネンックス    schedule 07.03.2017
comment
@sidyll регистр @ является псевдонимом для безымянного регистра. Я забыл, что " - обычно более условный символ для регистра. Я отредактировал функцию, чтобы показать, что регистр используется в возвращаемой строке, поэтому, к сожалению, я не могу просто вызвать setreg в обычном режиме.   -  person Bennett Rennier    schedule 07.03.2017
comment
@ Meninx- メ ネ ン ッ ク ス :h :let-@   -  person sidyll    schedule 07.03.2017
comment
@sidyll Я имею в виду :h registers, где его можно было бы заменить на {regname} в руководстве.   -  person Meninx - メネンックス    schedule 07.03.2017
comment
@ Meninx- メ ネ ン ッ ク ス Простите, я не понимаю, о чем вы. Я сам до сих пор не знал о @ как псевдониме ".   -  person sidyll    schedule 07.03.2017
comment
В некоторых случаях вместо " можно использовать @sidyll @. Как тот, который вы уже сказали.   -  person Meninx - メネンックス    schedule 07.03.2017


Ответы (2)


Вот способ продолжить: Vim: как выполнить вставку без перезаписи реестра

С тех пор нам подарили setreg(), и я также разработал более общее решение, упрощающее восстановление наиболее полезных вещей (_ 2_).

Во всех случаях решением будет вернуть @=FunctionToExecute(), и восстановление произойдет в этой функции.

Но, как говорили другие, вам, возможно, потребуется более четко указать свои потребности, поскольку могут существовать более конкретные решения для их удовлетворения. Например, вместо того, чтобы дергать с помощью yy или :yank, вы можете просто использовать getline() функцию, которая оставит все регистры неизменными. Для изменения строки есть setline(), но это нарушит повтор и другие вещи.

person Luc Hermitte    schedule 06.03.2017
comment
Ваши предложения работают, поэтому я отмечаю это как правильное. Однако я нашел немного другое решение, которое лучше работало со структурой моей программы. - person Bennett Rennier; 07.03.2017

Вместо того, чтобы переходить в нормальный режим после возврата функции, я думаю, вам следует войти в нее. Таким образом, вы можете нормально вызывать setreg(). Например:

function! Myfunction()
    let oldreg      = getreg('"')
    let oldregtype  = getregtype('"')

    let @" = "whatever"

    normal! yya 

    setreg('"', oldreg, oldregtype)
endfunction
person sidyll    schedule 06.03.2017