summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2010-07-24 20:27:03 +0200
committerBram Moolenaar <Bram@vim.org>2010-07-24 20:27:03 +0200
commit59f931ef54d143eb92f9b9168eb74fb061c39294 (patch)
treebb0116b64dbebf8a2c4f442a0514e8d2ec6f2d26 /src
parent72ada0f8c2655e365d9284bcc9243e29e5951f04 (diff)
Add the 'undoreload' option to be able to undo a file reload.
Diffstat (limited to 'src')
-rw-r--r--src/buffer.c39
-rw-r--r--src/ex_cmds.c22
-rw-r--r--src/fileio.c35
-rw-r--r--src/main.c6
-rw-r--r--src/memline.c4
-rw-r--r--src/option.c3
-rw-r--r--src/option.h1
-rw-r--r--src/proto/buffer.pro4
-rw-r--r--src/proto/undo.pro1
-rw-r--r--src/undo.c92
-rw-r--r--src/vim.h6
11 files changed, 139 insertions, 74 deletions
diff --git a/src/buffer.c b/src/buffer.c
index a8808d396d..94e0b2e0b9 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -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 */
- u_clearall(buf); /* reset all undo information */
+ 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)
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 602c340da4..20a39ffffa 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -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)
diff --git a/src/fileio.c b/src/fileio.c
index aa3143efb3..1c0ac85806 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -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,12 +7159,18 @@ 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);
- u_blockfree(buf);
- u_clearall(buf);
+ 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);
diff --git a/src/main.c b/src/main.c
index d94b32a38a..4ccf356286 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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)
diff --git a/src/memline.c b/src/memline.c
index 0f7b1d11c7..9fe9439ae2 100644
--- a/src/memline.c
+++ b/src/memline.c
@@ -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 */
diff --git a/src/option.c b/src/option.c
index 8a3f6b59b6..2c5e88bfbd 100644
--- a/src/option.c
+++ b/src/option.c
@@ -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},
diff --git a/src/option.h b/src/option.h
index 5e8574d828..78560c6979 100644
--- a/src/option.h
+++ b/src/option.h
@@ -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)
diff --git a/src/proto/buffer.pro b/src/proto/buffer.pro
index a5fe42ff83..df9c0b478a 100644
--- a/src/proto/buffer.pro
+++ b/src/proto/buffer.pro
@@ -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));
diff --git a/src/proto/undo.pro b/src/proto/undo.pro
index a914c4925c..2cb149f42f 100644
--- a/src/proto/undo.pro
+++ b/src/proto/undo.pro
@@ -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));
diff --git a/src/undo.c b/src/undo.c
index 58b55babbe..6d50cc839e 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -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,49 +360,53 @@ 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 (!undo_allowed())
- return 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
- * trying to change text in a guarded area.
- */
- if (netbeans_active())
- {
- if (netbeans_is_guarded(top, bot))
+ /*
+ * Netbeans defines areas that cannot be modified. Bail out here when
+ * trying to change text in a guarded area.
+ */
+ if (netbeans_active())
{
- EMSG(_(e_guarded));
- return FAIL;
+ if (netbeans_is_guarded(top, bot))
+ {
+ EMSG(_(e_guarded));
+ return FAIL;
+ }
+ if (curbuf->b_p_ro)
+ {
+ EMSG(_(e_nbreadonly));
+ return FAIL;
+ }
}
- if (curbuf->b_p_ro)
+#endif
+
+#ifdef FEAT_AUTOCMD
+ /*
+ * Saving text for undo means we are going to make a change. Give a
+ * warning for a read-only file before making the change, so that the
+ * FileChangedRO event can replace the buffer with a read-write version
+ * (e.g., obtained from a source control system).
+ */
+ change_warning(0);
+ if (bot > curbuf->b_ml.ml_line_count + 1)
{
- EMSG(_(e_nbreadonly));
+ /* 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 FEAT_AUTOCMD
- /*
- * Saving text for undo means we are going to make a change. Give a
- * warning for a read-only file before making the change, so that the
- * FileChangedRO event can replace the buffer with a read-write version
- * (e.g., obtained from a source control system).
- */
- 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. */
- EMSG(_("E834: Line count changed unexpectedly"));
- return FAIL;
}
+
+#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)
diff --git a/src/vim.h b/src/vim.h
index ce55514387..6790a48c94 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -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 */