0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

Add the 'undoreload' option to be able to undo a file reload.

This commit is contained in:
Bram Moolenaar
2010-07-24 20:27:03 +02:00
parent 72ada0f8c2
commit 59f931ef54
16 changed files with 167 additions and 79 deletions

View File

@@ -7361,6 +7361,8 @@ A jump table for the options with a short description can be found at |Q_op|.
file on buffer read.
The directory where the undo file is stored is specified by 'undodir'.
For more information about this feature see |undo-persistence|.
The undo file is not read when 'undoreload' causes the buffer from
before a reload to be saved for undo.
WARNING: this is a very new feature. Use at your own risk!
*'undolevels'* *'ul'*
@@ -7382,6 +7384,22 @@ A jump table for the options with a short description can be found at |Q_op|.
< This helps when you run out of memory for a single change.
Also see |clear-undo|.
*'undoreload'* *'ur'*
'undoreload' 'ur' number (default 10000)
global
{not in Vi}
Save the whole buffer for undo when reloading it. This applies to the
":e!" command and reloading for when the buffer changed outside of
Vim. |FileChangedShell|
The save only happens when this options is negative or when the number
of lines is smaller than the value of this option.
Set this option to zero to disable undo for a reload.
When saving undo for a reload, any undo file is not read.
Note that this causes the whole buffer to be stored in memory. Set
this option to a lower value if you run out of memory.
*'updatecount'* *'uc'*
'updatecount' 'uc' number (default: 200)
global

View File

@@ -1029,8 +1029,10 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME*
'undodir' options.txt /*'undodir'*
'undofile' options.txt /*'undofile'*
'undolevels' options.txt /*'undolevels'*
'undoreload' options.txt /*'undoreload'*
'updatecount' options.txt /*'updatecount'*
'updatetime' options.txt /*'updatetime'*
'ur' options.txt /*'ur'*
'ut' options.txt /*'ut'*
'vb' options.txt /*'vb'*
'vbs' options.txt /*'vbs'*
@@ -6081,6 +6083,7 @@ hl-Directory syntax.txt /*hl-Directory*
hl-ErrorMsg syntax.txt /*hl-ErrorMsg*
hl-FoldColumn syntax.txt /*hl-FoldColumn*
hl-Folded syntax.txt /*hl-Folded*
hl-Ignore syntax.txt /*hl-Ignore*
hl-IncSearch syntax.txt /*hl-IncSearch*
hl-LineNr syntax.txt /*hl-LineNr*
hl-MatchParen syntax.txt /*hl-MatchParen*

View File

@@ -40,9 +40,6 @@ Add documentation for Python 3 support.
New patch 2010 Jul 24
Docs patch by Dominique Pelle, Mar 25 included?
'undoreload' option: when fewer lines than these consider a reload as a change
action and save the text before the reload, don't clear undo info.
Patch for :find completion. (Nazri Ramliy)
But I prefer to keep term.h and include/term.h He will work on it.

View File

@@ -1,4 +1,4 @@
*version7.txt* For Vim version 7.3b. Last change: 2010 Jul 20
*version7.txt* For Vim version 7.3b. Last change: 2010 Jul 24
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -7171,6 +7171,9 @@ Added ":earlier 1f" and ":later 1f".
Add file save counter to undo information.
Added the |undotree()| and |undofile()| functions.
Also added the 'undoreload' option. This makes it possible to save the
current text when reloading the buffer, so that it can be undone.
More encryption *new-more-encryption*
---------------

View File

@@ -722,6 +722,8 @@ call <SID>OptionG("km", &km)
call <SID>Header("editing text")
call append("$", "undolevels\tmaximum number of changes that can be undone")
call append("$", " \tset ul=" . &ul)
call append("$", "undoreload\tmaximum number lines to save for undo on a buffer reload")
call append("$", " \tset ur=" . &ur)
call append("$", "modified\tchanges have been made and not written to a file")
call append("$", "\t(local to buffer)")
call <SID>BinOptionL("mod")

View File

@@ -66,9 +66,10 @@ static void buf_delete_signs __ARGS((buf_T *buf));
* Return FAIL for failure, OK otherwise.
*/
int
open_buffer(read_stdin, eap)
open_buffer(read_stdin, eap, flags)
int read_stdin; /* read file from stdin */
exarg_T *eap; /* for forced 'ff' and 'fenc' or NULL */
int flags; /* extra flags for readfile() */
{
int retval = OK;
#ifdef FEAT_AUTOCMD
@@ -130,7 +131,8 @@ open_buffer(read_stdin, eap)
netbeansFireChanges = 0;
#endif
retval = readfile(curbuf->b_ffname, curbuf->b_fname,
(linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, eap, READ_NEW);
(linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, eap,
flags | READ_NEW);
#ifdef FEAT_NETBEANS_INTG
netbeansFireChanges = oldFire;
#endif
@@ -151,13 +153,15 @@ open_buffer(read_stdin, eap)
*/
curbuf->b_p_bin = TRUE;
retval = readfile(NULL, NULL, (linenr_T)0,
(linenr_T)0, (linenr_T)MAXLNUM, NULL, READ_NEW + READ_STDIN);
(linenr_T)0, (linenr_T)MAXLNUM, NULL,
flags | (READ_NEW + READ_STDIN));
curbuf->b_p_bin = save_bin;
if (retval == OK)
{
line_count = curbuf->b_ml.ml_line_count;
retval = readfile(NULL, NULL, (linenr_T)line_count,
(linenr_T)0, (linenr_T)MAXLNUM, eap, READ_BUFFER);
(linenr_T)0, (linenr_T)MAXLNUM, eap,
flags | READ_BUFFER);
if (retval == OK)
{
/* Delete the binary lines. */
@@ -412,7 +416,7 @@ close_buffer(win, buf, action)
buf->b_nwindows = nwindows;
#endif
buf_freeall(buf, del_buf, wipe_buf);
buf_freeall(buf, (del_buf ? BFA_DEL : 0) + (wipe_buf ? BFA_WIPE : 0));
#ifdef FEAT_AUTOCMD
/* Autocommands may have deleted the buffer. */
@@ -511,13 +515,15 @@ buf_clear_file(buf)
/*
* buf_freeall() - free all things allocated for a buffer that are related to
* the file.
* the file. flags:
* BFA_DEL buffer is going to be deleted
* BFA_WIPE buffer is going to be wiped out
* BFA_KEEP_UNDO do not free undo information
*/
void
buf_freeall(buf, del_buf, wipe_buf)
buf_freeall(buf, flags)
buf_T *buf;
int del_buf UNUSED; /* buffer is going to be deleted */
int wipe_buf UNUSED; /* buffer is going to be wiped out */
int flags;
{
#ifdef FEAT_AUTOCMD
int is_curbuf = (buf == curbuf);
@@ -525,13 +531,13 @@ buf_freeall(buf, del_buf, wipe_buf)
apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf);
if (!buf_valid(buf)) /* autocommands may delete the buffer */
return;
if (del_buf && buf->b_p_bl)
if ((flags & BFA_DEL) && buf->b_p_bl)
{
apply_autocmds(EVENT_BUFDELETE, buf->b_fname, buf->b_fname, FALSE, buf);
if (!buf_valid(buf)) /* autocommands may delete the buffer */
return;
}
if (wipe_buf)
if (flags & BFA_WIPE)
{
apply_autocmds(EVENT_BUFWIPEOUT, buf->b_fname, buf->b_fname,
FALSE, buf);
@@ -576,10 +582,13 @@ buf_freeall(buf, del_buf, wipe_buf)
#ifdef FEAT_TCL
tcl_buffer_free(buf);
#endif
u_blockfree(buf); /* free the memory allocated for undo */
ml_close(buf, TRUE); /* close and delete the memline/memfile */
buf->b_ml.ml_line_count = 0; /* no lines in buffer */
if ((flags & BFA_KEEP_UNDO) == 0)
{
u_blockfree(buf); /* free the memory allocated for undo */
u_clearall(buf); /* reset all undo information */
}
#ifdef FEAT_SYN_HL
syntax_clear(&buf->b_s); /* reset syntax info */
#endif
@@ -1423,7 +1432,7 @@ enter_buffer(buf)
did_filetype = FALSE;
#endif
open_buffer(FALSE, NULL);
open_buffer(FALSE, NULL, 0);
}
else
{
@@ -1625,7 +1634,7 @@ buflist_new(ffname, sfname, lnum, flags)
if (buf == curbuf)
{
/* free all things allocated for this buffer */
buf_freeall(buf, FALSE, FALSE);
buf_freeall(buf, 0);
if (buf != curbuf) /* autocommands deleted the buffer! */
return NULL;
#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)

View File

@@ -3144,6 +3144,7 @@ do_ecmd(fnum, ffname, sfname, eap, newlnum, flags, oldwin)
#ifdef FEAT_SPELL
int did_get_winopts = FALSE;
#endif
int readfile_flags = 0;
if (eap != NULL)
command = eap->do_ecmd_cmd;
@@ -3570,7 +3571,22 @@ do_ecmd(fnum, ffname, sfname, eap, newlnum, flags, oldwin)
else
new_name = NULL;
#endif
buf_freeall(curbuf, FALSE, FALSE); /* free all things for buffer */
if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur)
{
/* Save all the text, so that the reload can be undone.
* Sync first so that this is a separate undo-able action. */
u_sync(FALSE);
if (u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, TRUE)
== FAIL)
goto theend;
u_unchanged(curbuf);
buf_freeall(curbuf, BFA_KEEP_UNDO);
/* tell readfile() not to clear or reload undo info */
readfile_flags = READ_KEEP_UNDO;
}
else
buf_freeall(curbuf, 0); /* free all things for buffer */
#ifdef FEAT_AUTOCMD
/* If autocommands deleted the buffer we were going to re-edit, give
* up and jump to the end. */
@@ -3667,10 +3683,10 @@ do_ecmd(fnum, ffname, sfname, eap, newlnum, flags, oldwin)
* Open the buffer and read the file.
*/
#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
if (should_abort(open_buffer(FALSE, eap)))
if (should_abort(open_buffer(FALSE, eap, readfile_flags)))
retval = FAIL;
#else
(void)open_buffer(FALSE, eap);
(void)open_buffer(FALSE, eap, readfile_flags);
#endif
#if defined(HAS_SWAP_EXISTS_ACTION)

View File

@@ -219,6 +219,7 @@ filemess(buf, name, s, attr)
* READ_BUFFER read from curbuf instead of a file (converting after reading
* stdin)
* READ_DUMMY read into a dummy buffer (to check if file contents changed)
* READ_KEEP_UNDO don't clear undo info or read it from a file
*
* return FAIL for failure, OK otherwise
*/
@@ -1195,8 +1196,12 @@ retry:
conv_restlen = 0;
#endif
#ifdef FEAT_PERSISTENT_UNDO
read_undo_file = (newfile && curbuf->b_ffname != NULL && curbuf->b_p_udf
&& !filtering && !read_stdin && !read_buffer);
read_undo_file = (newfile && (flags & READ_KEEP_UNDO) == 0
&& curbuf->b_ffname != NULL
&& curbuf->b_p_udf
&& !filtering
&& !read_stdin
&& !read_buffer);
if (read_undo_file)
sha256_start(&sha_ctx);
#endif
@@ -7077,6 +7082,7 @@ buf_reload(buf, orig_mode)
buf_T *savebuf;
int saved = OK;
aco_save_T aco;
int flags = READ_NEW;
/* set curwin/curbuf for "buf" and save some things */
aucmd_prepbuf(&aco, buf);
@@ -7089,6 +7095,15 @@ buf_reload(buf, orig_mode)
old_cursor = curwin->w_cursor;
old_topline = curwin->w_topline;
if (saved == OK && (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur))
{
/* Save all the text, so that the reload can be undone.
* Sync first so that this is a separate undo-able action. */
u_sync(FALSE);
saved = u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, TRUE);
flags |= READ_KEEP_UNDO;
}
/*
* To behave like when a new file is edited (matters for
* BufReadPost autocommands) we first need to delete the current
@@ -7096,7 +7111,7 @@ buf_reload(buf, orig_mode)
* the old contents. Can't use memory only, the file might be
* too big. Use a hidden buffer to move the buffer contents to.
*/
if (bufempty())
if (bufempty() || saved == FAIL)
savebuf = NULL;
else
{
@@ -7128,7 +7143,7 @@ buf_reload(buf, orig_mode)
#endif
if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
(linenr_T)0,
(linenr_T)MAXLNUM, &ea, READ_NEW) == FAIL)
(linenr_T)MAXLNUM, &ea, flags) == FAIL)
{
#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
if (!aborting())
@@ -7144,13 +7159,19 @@ buf_reload(buf, orig_mode)
(void)move_lines(savebuf, buf);
}
}
else if (buf == curbuf)
else if (buf == curbuf) /* "buf" still valid */
{
/* Mark the buffer as unmodified and free undo info. */
unchanged(buf, TRUE);
if ((flags & READ_KEEP_UNDO) == 0)
{
u_blockfree(buf);
u_clearall(buf);
}
else
/* Mark all undo states as changed. */
u_unchanged(curbuf);
}
}
vim_free(ea.cmd);

View File

@@ -2470,7 +2470,7 @@ read_stdin()
no_wait_return = TRUE;
i = msg_didany;
set_buflisted(TRUE);
(void)open_buffer(TRUE, NULL); /* create memfile and read file */
(void)open_buffer(TRUE, NULL, 0); /* create memfile and read file */
no_wait_return = FALSE;
msg_didany = i;
TIME_MSG("reading stdin");
@@ -2591,7 +2591,9 @@ create_windows(parmp)
swap_exists_action = SEA_DIALOG;
#endif
set_buflisted(TRUE);
(void)open_buffer(FALSE, NULL); /* create memfile, read file */
/* create memfile, read file */
(void)open_buffer(FALSE, NULL, 0);
#if defined(HAS_SWAP_EXISTS_ACTION)
if (swap_exists_action == SEA_QUIT)

View File

@@ -2529,7 +2529,7 @@ ml_append(lnum, line, len, newfile)
int newfile; /* flag, see above */
{
/* When starting up, we might still need to create the memfile */
if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL) == FAIL)
if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL, 0) == FAIL)
return FAIL;
if (curbuf->b_ml.ml_line_lnum != 0)
@@ -3078,7 +3078,7 @@ ml_replace(lnum, line, copy)
return FAIL;
/* When starting up, we might still need to create the memfile */
if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL) == FAIL)
if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL, 0) == FAIL)
return FAIL;
if (copy && (line = vim_strsave(line)) == NULL) /* allocate memory */

View File

@@ -2655,6 +2655,9 @@ static struct vimoption
(char_u *)100L,
#endif
(char_u *)0L} SCRIPTID_INIT},
{"undoreload", "ur", P_NUM|P_VI_DEF,
(char_u *)&p_ur, PV_NONE,
{ (char_u *)10000L, (char_u *)0L} SCRIPTID_INIT},
{"updatecount", "uc", P_NUM|P_VI_DEF,
(char_u *)&p_uc, PV_NONE,
{(char_u *)200L, (char_u *)0L} SCRIPTID_INIT},

View File

@@ -826,6 +826,7 @@ static char *(p_ttym_values[]) = {"xterm", "xterm2", "dec", "netterm", "jsbterm"
#endif
EXTERN char_u *p_udir; /* 'undodir' */
EXTERN long p_ul; /* 'undolevels' */
EXTERN long p_ur; /* 'undoreload' */
EXTERN long p_uc; /* 'updatecount' */
EXTERN long p_ut; /* 'updatetime' */
#if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING)

View File

@@ -1,9 +1,9 @@
/* buffer.c */
int open_buffer __ARGS((int read_stdin, exarg_T *eap));
int open_buffer __ARGS((int read_stdin, exarg_T *eap, int flags));
int buf_valid __ARGS((buf_T *buf));
void close_buffer __ARGS((win_T *win, buf_T *buf, int action));
void buf_clear_file __ARGS((buf_T *buf));
void buf_freeall __ARGS((buf_T *buf, int del_buf, int wipe_buf));
void buf_freeall __ARGS((buf_T *buf, int flags));
void goto_buffer __ARGS((exarg_T *eap, int start, int dir, int count));
void handle_swap_exists __ARGS((buf_T *old_curbuf));
char_u *do_bufdel __ARGS((int command, char_u *arg, int addr_count, int start_bnr, int end_bnr, int forceit));

View File

@@ -5,6 +5,7 @@ int u_savesub __ARGS((linenr_T lnum));
int u_inssub __ARGS((linenr_T lnum));
int u_savedel __ARGS((linenr_T lnum, long nlines));
int undo_allowed __ARGS((void));
int u_savecommon __ARGS((linenr_T top, linenr_T bot, linenr_T newbot, int reload));
void u_compute_hash __ARGS((char_u *hash));
char_u *u_get_undo_file_name __ARGS((char_u *buf_ffname, int reading));
void u_write_undo __ARGS((char_u *name, int forceit, buf_T *buf, char_u *hash));

View File

@@ -90,7 +90,6 @@
static void u_unch_branch __ARGS((u_header_T *uhp));
static u_entry_T *u_get_headentry __ARGS((void));
static void u_getbot __ARGS((void));
static int u_savecommon __ARGS((linenr_T, linenr_T, linenr_T));
static void u_doit __ARGS((int count));
static void u_undoredo __ARGS((int undo));
static void u_undo_end __ARGS((int did_undo, int absolute));
@@ -250,7 +249,7 @@ u_save(top, bot)
if (top + 2 == bot)
u_saveline((linenr_T)(top + 1));
return (u_savecommon(top, bot, (linenr_T)0));
return (u_savecommon(top, bot, (linenr_T)0, FALSE));
}
/*
@@ -266,7 +265,7 @@ u_savesub(lnum)
if (undo_off)
return OK;
return (u_savecommon(lnum - 1, lnum + 1, lnum + 1));
return (u_savecommon(lnum - 1, lnum + 1, lnum + 1, FALSE));
}
/*
@@ -282,7 +281,7 @@ u_inssub(lnum)
if (undo_off)
return OK;
return (u_savecommon(lnum - 1, lnum, lnum + 1));
return (u_savecommon(lnum - 1, lnum, lnum + 1, FALSE));
}
/*
@@ -301,7 +300,7 @@ u_savedel(lnum, nlines)
return OK;
return (u_savecommon(lnum - 1, lnum + nlines,
nlines == curbuf->b_ml.ml_line_count ? 2 : lnum));
nlines == curbuf->b_ml.ml_line_count ? 2 : lnum, FALSE));
}
/*
@@ -342,13 +341,16 @@ undo_allowed()
* Common code for various ways to save text before a change.
* "top" is the line above the first changed line.
* "bot" is the line below the last changed line.
* "newbot" is the new bottom line. Use zero when not known.
* "reload" is TRUE when saving for a buffer reload.
* Careful: may trigger autocommands that reload the buffer.
* Returns FAIL when lines could not be saved, OK otherwise.
*/
static int
u_savecommon(top, bot, newbot)
int
u_savecommon(top, bot, newbot, reload)
linenr_T top, bot;
linenr_T newbot;
int reload;
{
linenr_T lnum;
long i;
@@ -358,14 +360,13 @@ u_savecommon(top, bot, newbot)
u_entry_T *prev_uep;
long size;
/* When making changes is not allowed return FAIL. It's a crude way to
* make all change commands fail. */
if (!reload)
{
/* When making changes is not allowed return FAIL. It's a crude way
* to make all change commands fail. */
if (!undo_allowed())
return FAIL;
#ifdef U_DEBUG
u_check(FALSE);
#endif
#ifdef FEAT_NETBEANS_INTG
/*
* Netbeans defines areas that cannot be modified. Bail out here when
@@ -396,12 +397,17 @@ u_savecommon(top, bot, newbot)
change_warning(0);
if (bot > curbuf->b_ml.ml_line_count + 1)
{
/* This happens when the FileChangedRO autocommand changes the file in
* a way it becomes shorter. */
/* This happens when the FileChangedRO autocommand changes the
* file in a way it becomes shorter. */
EMSG(_("E834: Line count changed unexpectedly"));
return FAIL;
}
#endif
}
#ifdef U_DEBUG
u_check(FALSE);
#endif
size = bot - top - 1;
@@ -2905,7 +2911,7 @@ ex_undojoin(eap)
}
/*
* Called after writing the file and setting b_changed to FALSE.
* Called after writing or reloading the file and setting b_changed to FALSE.
* Now an undo means that the buffer is modified.
*/
void
@@ -3197,7 +3203,7 @@ u_undoline()
/* first save the line for the 'u' command */
if (u_savecommon(curbuf->b_u_line_lnum - 1,
curbuf->b_u_line_lnum + 1, (linenr_T)0) == FAIL)
curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL)
return;
oldp = u_save_line(curbuf->b_u_line_lnum);
if (oldp == NULL)

View File

@@ -953,6 +953,7 @@ extern char *(*dyn_libintl_textdomain)(const char *domainname);
#define READ_STDIN 0x04 /* read from stdin */
#define READ_BUFFER 0x08 /* read from curbuf (converting stdin) */
#define READ_DUMMY 0x10 /* reading into a dummy buffer */
#define READ_KEEP_UNDO 0x20 /* keep undo info*/
/* Values for change_indent() */
#define INDENT_SET 1 /* set indent */
@@ -2174,4 +2175,9 @@ typedef int VimClipboard; /* This is required for the prototypes. */
#define VIF_FORCEIT 4 /* overwrite info already read */
#define VIF_GET_OLDFILES 8 /* load v:oldfiles */
/* flags for buf_freeall() */
#define BFA_DEL 1 /* buffer is going to be deleted */
#define BFA_WIPE 2 /* buffer is going to be wiped out */
#define BFA_KEEP_UNDO 4 /* do not free undo information */
#endif /* VIM__H */