Как приостановить историю VIM?

8

Когда мы редактируем файл, мы обычно делаем много ОТМЕНЫ подряд, скажем, 20 раз. В VIM это обычно выполняется нажатием u20 раз, и это заставляет VIM «подниматься» в стеке истории на 20 позиций. Если вы затем определитесь change, все эти последние 20 команд истории будут потеряны и заменены на change. Я хотел бы сделать changeбез потери этих 20 позиций. Так что, я думаю, я бы хотел сказать VIM прекратить запись истории, прежде чем я это сделаю change, и возобновить историю позже (не хочу changeв истории).

РЕДАКТИРОВАТЬ Попытка быть более ясным: у меня есть функция, FFкоторая обновляет последние строки файла при записи в буфер. Итак, если я выполню 20 undos + write, последний writeоткроет новую ветку отмены. Я попытался добавить undojoinвнутрь FF(пытаясь следовать предложению jlmg ниже), но последовательность write-undo-write выдает ошибку: отмена не разрешена после отмены . Вместо этого я мог бы сделать некоторые sed ....после ухода vim, но так как я использую это через, SSHя предпочитаю решение только для vim (выполнение команды после выгрузки буфера не записывает в файл).

РЕДАКТИРОВАТЬ 2 Попробуйте сделать это в VIM: откройте пустой файл и выполните:

i1<ESC>:wa2<ESC>:wa3<ESC>:wa4<ESC>uu:w

Если сейчас вы сделаете a <CTRL>R, VIM напишет «3» обратно, а дальше <CTRL>Rвы получите 4. Это происходит ДАЖЕ, если вы делаете :wпосле каждого <CTRL>R. Тем не менее, если каждый раз, когда вы делаете a, :wвы выполняете функцию через BufWritePre, the <CTRL>Rне будет писать 3обратно. И это то, что я хочу сделать, именно поэтому я написал, чтобы «приостановить его», но, возможно, то, что я спрашиваю, не возможно, кроме работы с полной undotree().

Луис А. Флорит
источник
1
Этот вопрос относится к теме этого сайта, но поскольку он относится к довольно эзотерической потенциальной функции VIM, вы рассматривали возможность попробовать vim.stackexchange.com? Я имею в виду, я знаю UNIX и знаю vi, но для меня viкоманда отмены отменяется один раз, а затем при uповторном нажатии отменяет отмену («повторить»). Это настоящий ви. Поэтому я и другие пользователи этого сайта могут не знать ответа на ваш вопрос.
Селада
2
@Celada Я считаю, что это vi.stackexchange.com , или Ви и Вим .
Satō Katsura
@SatoKatsura ты абсолютно прав!
Селада
1
@Celada: я не знал о vim.se, я бы попробовал это. Во всяком случае, кажется, Сато знает, как помочь.
Луис А. Флорит
Проблема, которую вы задаете «все последние 20 команд истории потеряны», устраняется с помощью существования ветвей отмены, поэтому сбивает с толку то, что вы затем хотите исправить свою проблему, избегая их создания. Вы говорите, что можете получить sedжелаемый результат , но sed не может отменить ваши действия, так как же это сработает? Если бы вы смогли «приостановить историю», какое поведение вы бы ожидали от vim, когда вы потом отмените действия? Единственное поведение, которое я мог визуализировать, - это сгруппировать эти изменения (вместе с отменами) в один блок отмены, отсюда и мой ответ. Но если это не так, то что?
JoL

Ответы:

12

Вам не нужно приостанавливать историю Vim. Фактические данные образуют дерево, и вы можете получить его с помощью undotree()функции. Есть, конечно, несколько плагинов, которые превращают это в нечто более удобное для пользователя, например , gundo , mundo и undotree . Если вы также включите отмену сохранения (ср. :h undo-persistence), Вы можете легко перемещаться по всей истории изменений файла.

Сату Кацура
источник
Интересно, я не знал, что отмена была фактически деревом. В моем случае я хочу вернуться только один раз, то есть к предыдущей ветке отмены. Ты знаешь как это сделать? Кажется, undotree()должно помочь?
Луис А. Флорит
На самом деле, в этом конкретном случае, который мотивировал мой вопрос, я хочу, чтобы он changeвообще не появлялся нигде, ни в дереве history, ни в undoдереве. Вот почему мой вопрос был «приостановить историю».
Луис А. Флорит
@ LuisA.Florit: быстрый и простой способ сделать это с помощью :earlier, который принимает единицу времени и пересечет ветки отмены при необходимости (например, :earlier 1hзаставляет буфер выглядеть так, как это делал час назад). Если вы не можете использовать единицу времени (потому что изменения были слишком близко друг к другу?), Вам придется использовать g-для обхода дерева отмены несколько шагов за раз.
Кевин
0

Если я вас правильно понимаю, то вы хотите, чтобы после этого отмена changeотменяла это, а 20 отмен.

Когда vim выполняет функцию или команду, все ее действия отменяются вместе. Я не уверен, что эти действия могут включать отмены. Может быть, эта часть документации может помочь:

3. Undo blocks                      *undo-blocks*

One undo command normally undoes a typed command, no matter how many changes
that command makes.  This sequence of undo-able changes forms an undo block.
Thus if the typed key(s) call a function, all the commands in the function are
undone together.

If you want to write a function or script that doesn't create a new undoable
change but joins in with the previous change use this command:

                        *:undoj* *:undojoin* *E790*
:undoj[oin]     Join further changes with the previous undo block.
            Warning: Use with care, it may prevent the user from
            properly undoing changes.  Don't use this after undo
            or redo.
            {not in Vi}

This is most useful when you need to prompt the user halfway through a change.
For example in a function that calls |getchar()|.  Do make sure that there was
a related change before this that you must join with.

This doesn't work by itself, because the next key press will start a new
change again.  But you can do something like this: >

    :undojoin | delete

After this an "u" command will undo the delete command and the previous
change.

To do the opposite, break a change into two undo blocks, in Insert mode use
CTRL-G u.  This is useful if you want an insert command to be undoable in
parts.  E.g., for each sentence.  |i_CTRL-G_u|
Setting the value of 'undolevels' also breaks undo.  Even when the new value
is equal to the old value.

Увы, я пытался использовать :undo 2 | undojoin | normal ohi, но я получил сообщение об ошибке E790: undojoin is not allowed after undo.

Однако, если действия выполняются в такой функции:

function F()
  undo 2
  normal ohi
endfunction

затем вызов его с помощью :call F()выполняет undoи другие действия в одном блоке отмены. Обратите внимание: поскольку вы используете отмену, вы создаете новую ветку отмены. После этого вы можете использовать команду обычного режима g-, чтобы отменить F(); использование uбудет как :undo 3в начале.

Йол
источник
Не уверен, что это работает ... Я хочу, чтобы после того, как вы что-то сделали undo, все, что вы делаете в своей функции F(), не открывало новую ветку отмены. В моем случае F()выполняется каждый раз, когда я записываю файл, и если я делаю, undoа затем записываю файл, F()открывается новая ветвь отмены. Я попытался с undojoinв начале F(), но последовательность записи уничтожьте-записи выдает ошибку: undojoint not allowed after undo.
Луис А. Флорит
Обновил мой вопрос, пытаясь быть более понятным.
Луис А. Флорит
@ LuisA.Florit Я написал в ответе, что :undojoinне сработало для того, что вы хотели, упомянув ту же ошибку, и я не предлагал использовать :undojoinв начале F(). F()предназначен для того, чтобы делать то, что :undojoinне мог, то есть объединять отмены и другие команды в одном блоке отмены.
JoL
@ LuisA.Florit Вы говорите, что хотите избежать создания ветки отмены, но я не могу найти причину, почему вы этого хотите. Я думал, что смысл вашего вопроса в том, чтобы иметь возможность отменить команды и множественные отмены за один раз. Оглядываясь назад, я думаю, что ваша цель - не потерять изменения, которые вы отменили. Если это так, то существование дерева отмены - именно то, что вы хотите. Вы можете перемещаться с помощью g-и g+.
JoL
Да, кажется, дерево отмены - это то, что мне нужно.
Луис А. Флорит