summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/cmdline.txt1
-rw-r--r--runtime/doc/eval.txt1
-rw-r--r--runtime/doc/options.txt27
-rw-r--r--runtime/doc/tags19
-rw-r--r--runtime/doc/todo.txt56
-rw-r--r--runtime/doc/undo.txt90
-rw-r--r--runtime/doc/various.txt1
-rw-r--r--runtime/doc/version7.txt4
-rw-r--r--runtime/optwin.vim4
-rw-r--r--runtime/tutor/tutor.it2
-rw-r--r--runtime/tutor/tutor.it.utf-82
-rw-r--r--src/buffer.c5
-rw-r--r--src/eval.c3
-rw-r--r--src/ex_cmds.h4
-rw-r--r--src/ex_docmd.c30
-rw-r--r--src/feature.h8
-rw-r--r--src/fileio.c71
-rw-r--r--src/memline.c37
-rw-r--r--src/option.c28
-rw-r--r--src/option.h2
-rw-r--r--src/os_mac.h2
-rw-r--r--src/proto/memline.pro1
-rw-r--r--src/proto/sha256.pro3
-rw-r--r--src/proto/spell.pro5
-rw-r--r--src/proto/undo.pro3
-rw-r--r--src/sha256.c27
-rw-r--r--src/spell.c15
-rw-r--r--src/structs.h9
-rw-r--r--src/testdir/Makefile2
-rw-r--r--src/testdir/test61.in47
-rw-r--r--src/testdir/test61.ok9
-rw-r--r--src/undo.c803
-rw-r--r--src/version.c5
-rw-r--r--src/vim.h3
34 files changed, 1232 insertions, 97 deletions
diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt
index 318c699925..8abb16b8c4 100644
--- a/runtime/doc/cmdline.txt
+++ b/runtime/doc/cmdline.txt
@@ -805,6 +805,7 @@ Note: these are typed literally, they are not special keys!
*filename-modifiers*
*:_%:* *::8* *::p* *::.* *::~* *::h* *::t* *::r* *::e* *::s* *::gs*
+ *%:8* *%:p* *%:.* *%:~* *%:h* *%:t* *%:r* *%:e* *%:s* *%:gs*
The file name modifiers can be used after "%", "#", "#n", "<cfile>", "<sfile>",
"<afile>" or "<abuf>". They are also used with the |fnamemodify()| function.
These are not available when Vim has been compiled without the |+modify_fname|
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 5b5e8fa00d..2a2d601551 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -6053,6 +6053,7 @@ os2 OS/2 version of Vim.
osfiletype Compiled with support for osfiletypes |+osfiletype|
path_extra Compiled with up/downwards search in 'path' and 'tags'
perl Compiled with Perl interface.
+persistent_undo Compiled with support for persistent undo history.
postscript Compiled with PostScript file printing.
printer Compiled with |:hardcopy| support.
profile Compiled with |:profile| support.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 0bdde3a556..9c9d584155 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -7220,6 +7220,33 @@ A jump table for the options with a short description can be found at |Q_op|.
global
Alias for 'term', see above.
+ *'undodir'* *'udir'*
+'undodir' 'udir' string (default ".")
+ global
+ {not in Vi}
+ {only when compiled with the +persistent_undo feature}
+ List of directory names for undo files, separated with commas.
+ See |'backupdir'| for the format. Specifically, "." means using the
+ directory of the file.
+ When writing: The first directory that exists is used. "." always
+ works, no directories after "." will be used for writing.
+ When reading all entries are tried to find an undo file. The first
+ undo file that exists is used. When it cannot be read an error is
+ given, no further entry is used.
+ See |undo-persistence|.
+
+ *'undofile'* *'udf'*
+'undofile' 'udf' boolean (default off)
+ local to buffer
+ {not in Vi}
+ {only when compiled with the +persistent_undo feature}
+ When on, Vim automatically saves undo history to an undo file when
+ writing a buffer to a file, and restores undo history from the same
+ file on buffer read.
+ The name of the undo file is specified by 'undodir'.
+ See |undo-persistence|.
+ WARNING: this is a very new feature. Use at your own risc!
+
*'undolevels'* *'ul'*
'undolevels' 'ul' number (default 100, 1000 for Unix, VMS,
Win32 and OS/2)
diff --git a/runtime/doc/tags b/runtime/doc/tags
index 259933eaae..9e2dac5655 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -10,6 +10,16 @@ $VIM starting.txt /*$VIM*
$VIM-use version5.txt /*$VIM-use*
$VIMRUNTIME starting.txt /*$VIMRUNTIME*
% motion.txt /*%*
+%:. cmdline.txt /*%:.*
+%:8 cmdline.txt /*%:8*
+%:e cmdline.txt /*%:e*
+%:gs cmdline.txt /*%:gs*
+%:h cmdline.txt /*%:h*
+%:p cmdline.txt /*%:p*
+%:r cmdline.txt /*%:r*
+%:s cmdline.txt /*%:s*
+%:t cmdline.txt /*%:t*
+%:~ cmdline.txt /*%:~*
& change.txt /*&*
' motion.txt /*'*
'' motion.txt /*''*
@@ -1005,7 +1015,11 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME*
'tw' options.txt /*'tw'*
'tx' options.txt /*'tx'*
'uc' options.txt /*'uc'*
+'udf' options.txt /*'udf'*
+'udir' options.txt /*'udir'*
'ul' options.txt /*'ul'*
+'undodir' options.txt /*'undodir'*
+'undofile' options.txt /*'undofile'*
'undolevels' options.txt /*'undolevels'*
'updatecount' options.txt /*'updatecount'*
'updatetime' options.txt /*'updatetime'*
@@ -1163,6 +1177,7 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME*
+path_extra various.txt /*+path_extra*
+perl various.txt /*+perl*
+perl/dyn various.txt /*+perl\/dyn*
++persistent_undo various.txt /*+persistent_undo*
+postscript various.txt /*+postscript*
+printer various.txt /*+printer*
+profile various.txt /*+profile*
@@ -2582,6 +2597,7 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME*
:rubydo if_ruby.txt /*:rubydo*
:rubyf if_ruby.txt /*:rubyf*
:rubyfile if_ruby.txt /*:rubyfile*
+:rundo undo.txt /*:rundo*
:runtime repeat.txt /*:runtime*
:rv starting.txt /*:rv*
:rviminfo starting.txt /*:rviminfo*
@@ -2964,6 +2980,7 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME*
:write_f editing.txt /*:write_f*
:ws workshop.txt /*:ws*
:wsverb workshop.txt /*:wsverb*
+:wundo undo.txt /*:wundo*
:wv starting.txt /*:wv*
:wviminfo starting.txt /*:wviminfo*
:x editing.txt /*:x*
@@ -6913,6 +6930,7 @@ perl-overview if_perl.txt /*perl-overview*
perl-patterns pattern.txt /*perl-patterns*
perl-using if_perl.txt /*perl-using*
perl.vim syntax.txt /*perl.vim*
+persistent-undo undo.txt /*persistent-undo*
pexpr-option print.txt /*pexpr-option*
pfn-option print.txt /*pfn-option*
pheader-option print.txt /*pheader-option*
@@ -7835,6 +7853,7 @@ undo undo.txt /*undo*
undo-blocks undo.txt /*undo-blocks*
undo-branches undo.txt /*undo-branches*
undo-commands undo.txt /*undo-commands*
+undo-persistence undo.txt /*undo-persistence*
undo-redo undo.txt /*undo-redo*
undo-remarks undo.txt /*undo-remarks*
undo-tree undo.txt /*undo-tree*
diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt
index a109c2ea06..49fc70a4d5 100644
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -30,6 +30,9 @@ be worked on, but only if you sponsor Vim development. See |sponsor|.
*known-bugs*
-------------------- Known bugs and current work -----------------------
+When Vim crashes it may run out of stack while executing autocommands. Patch
+to not run autocommands when leaving Vim? (James Vega, 2010 May 23)
+
Cursor positioning wrong with 0x200e character. (John Becket, 2010 May 6)
E315 when trying to change a file in FileChangedRO autocommand event.
@@ -1082,6 +1085,18 @@ restored. (Luc St-Louis)
Vim 7.3:
Patches to include:
+8 Persistent undo bugs / fixes:
+ - Add tests. Also with different 'enc'
+ - Add undofile(name): get undo file name for buffer "name".
+- Extend test62 for gettabvar() and settabvar(). (Yegappan Lakshmanan, 2010
+ May 23)
+- Also crypt the undo file.
+- Also crypt the swap file, each block separately. Change mf_write() and
+ mf_read(). How to get b_p_key to these functions?
+- Do profiling on sha256 code to find obvious bottlenecks.
+- Do profiling on crypt code to find obvious bottlenecks.
+- Use off_t instead of long for bytes in a buffer. (James Vega, 2010 May 22,
+ update next day)
- Include conceal patch?
http://vince.negri.googlepages.com/
http://vim.wikia.com/wiki/Patch_to_conceal_parts_of_lines
@@ -1150,42 +1165,17 @@ Needs some work:
Needs some more testing.
Update 2010 Apr 20, patch by Andy Kittner, May 16
- Easier/standard way to disable default plugins.
-8 Persistent undo: store undo in a file. Patch by Jordan Lewis, 2009 Feb
- 20. Repost 2009 Nov 16.
- Get tar file from: http://repo.or.cz/w/vim_extended.git/tree/feat/persistent-undo
- -> disable by default and add remark that it's new and may fail.
- Testing remarks by Christian Brabandt, 2010 May 1:
- - doesn't work well with symlinks (Jordan will look into it)
- - old undo files tend to pile up
- - :rundo should output a message (Jordan will fix this)
- Bugs / fixes:
- - Undo file should be stored with the original file by default, the undo
- directory doesn't handle remote files or directory renames.
- Use same mechanism as for swap files? But only with one file name.
- - Read coladd depending on FEAT_VIRTUALEDIT, should always read/write it
- - invoke u_wundo() inside buf_write()
- - invoke u_rundo() inside readfile()
- - Document that ":wundo" and ":rundo" should only be used in autocommands.
- - unserialize_pos() does not need a return value
- - function comments go before the function, not inside
- - u_get_undofile() changes its argument ffname
- - make magic four bytes.
- - errors need numbers "E000:"
- - also put 'enc' in undo file.
- - don't use timestamp, "touch file" or dir copy may change it and undo
- still works.
- Older ideas:
- - Use timestamps, so that a version a certain time ago can be found and
- info before some time/date can be flushed. 'undopersist' gives maximum
- time to keep undo: "3h", "1d", "2w", "1y", etc. For the file use dot
- and extension: ".filename.un~" (like swapfile but "un~" instead of
- "swp").
- ":{range}source": source the lines from the current file.
You can already yank lines and use :@" to execute them.
Most of do_source() would not be used, need a new function.
It's easy when not doing breakpoints or profiling.
+Probably not now:
+- Use timestamps for undo, so that a version a certain time ago can be found
+ and info before some time/date can be flushed. 'undopersist' gives maximum
+ time to keep undo: "3h", "1d", "2w", "1y", etc.
Before (beta) release:
- Add fixes for 7.2 to version7.txt
+- Rename vim73 branch to default (hints: Xavier de Gaye, 2010 May 23)
More patches:
@@ -1292,7 +1282,6 @@ Awaiting updated patches:
to left as well? See patch of Dec 26. (Nadim Shaikli)
8 Option to lock all used memory so that it doesn't get swapped to disk
(uncrypted). Patch by Jason Holt, 2003 May 23. Uses mlock.
-7 Support a stronger encryption. Jason Holt implemented AES (May 6 2003).
7 Add ! register, for shell commands. (patch from Grenie)
8 In the gzip plugin, also recognize *.gz.orig, *.gz.bak, etc. Like it's
done for filetype detection. Patch from Walter Briscoe, 2003 Jul 1.
@@ -4320,11 +4309,6 @@ Mouse support:
- When mouse click after 'r' command, get character that was pointed to.
-Crypt and security:
-8 Also crypt the swapfile, each block separately. Change mf_write() and
- mf_read(). How to get b_p_key to these functions?
-
-
Argument list:
6 Add command to put all filenames from the tag files in the argument list.
When given an argument, only use the files where that argument matches
diff --git a/runtime/doc/undo.txt b/runtime/doc/undo.txt
index 2c8c60c9aa..05e5555b77 100644
--- a/runtime/doc/undo.txt
+++ b/runtime/doc/undo.txt
@@ -12,7 +12,8 @@ The basics are explained in section |02.5| of the user manual.
2. Two ways of undo |undo-two-ways|
3. Undo blocks |undo-blocks|
4. Undo branches |undo-branches|
-5. Remarks about undo |undo-remarks|
+5. Undo persistence |undo-persistence|
+6. Remarks about undo |undo-remarks|
==============================================================================
1. Undo and redo commands *undo-commands*
@@ -22,7 +23,7 @@ u Undo [count] changes. {Vi: only one level}
*:u* *:un* *:undo*
:u[ndo] Undo one change. {Vi: only one level}
-
+ *E830*
:u[ndo] {N} Jump to after change number {N}. See |undo-branches|
for the meaning of {N}. {not in Vi}
@@ -109,6 +110,8 @@ 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.
==============================================================================
4. Undo branches *undo-branches* *undo-tree*
@@ -201,7 +204,88 @@ Note that using "u" and CTRL-R will not get you to all possible text states
while repeating "g-" and "g+" does.
==============================================================================
-5. Remarks about undo *undo-remarks*
+5. Undo persistence *undo-persistence* *persistent-undo*
+
+When unloading a buffer Vim normally destroys the tree of undos created for
+that buffer. By setting the 'undofile' option, Vim will automatically save
+your undo history when you write a file and restore undo history when you edit
+the file again.
+
+The 'undofile' option is checked after writing a file, before the BufWritePost
+autocommands. If you want to control what files to write undo information
+for, you can use a BufWritePre autocommand: >
+ au BufWritePre /tmp/* setlocal noundofile
+
+Vim saves undo trees in a separate undo file, one for each edited file, using
+a simple scheme that maps filesystem paths directly to undo files. Vim will
+detect if an undo file is no longer synchronized with the file it was written
+for (with a hash of the file contents) and ignore it when the file was changed
+after the undo file was written, to prevent corruption.
+
+Undo files are normally saved in the same directory as the file. This can be
+changed with the 'undodir' option.
+
+You can also save and restore undo histories by using ":wundo" and ":rundo"
+respectively:
+ *:wundo* *:rundo*
+:wundo[!] {file}
+ Write undo history to {file}.
+ When {file} exists and it does not look like an undo file
+ (the magic number at the start of the file is wrong), then
+ this fails, unless the ! was added.
+ If it exists and does look like an undo file it is
+ overwritten.
+ {not in Vi}
+
+:rundo {file} Read undo history from {file}.
+ {not in Vi}
+
+You can use these in autocommands to explicitly specify the name of the
+history file. E.g.: >
+
+ au BufReadPost * rundo %:h/UNDO/%:t
+ au BufWritePost * wundo %:h/UNDO/%:t
+
+You should keep 'undofile' off, otherwise you end up with two undo files for
+every write.
+Note: I did not verify this always works!
+
+Note that while reading/writing files and 'undofile' is set most errors will
+be silent, unless 'verbose' is set. With :wundo and :rundo you will get more
+error messages, e.g., when the file cannot be read or written.
+
+NOTE: undo files are never deleted by Vim. You need to delete them yourself.
+
+Reading an existing undo file may fail for several reasons:
+*E822* It cannot be opened, because the file permissions don't allow it.
+*E823* The magic number at the start of the file doesn't match. This usually
+ means it is not an undo file.
+*E824* The version number of the undo file indicates that it's written by a
+ newer version of Vim. You need that newer version to open it. Don't
+ write the buffer if you want to keep the undo info in the file.
+"Undo file contents changed"
+ The file text differs from when the undo file was written. This means
+ the undo file cannot be used, it would corrupt the text.
+*E825* *E826* The undo file does not contain valid contents and cannot be
+ used.
+*E827* The magic number at the end of the file was not found. This usually
+ means the file was truncated.
+
+Writing an undo file may fail for these reasons:
+*E828* The file to be written cannot be created. Perhaps you do not have
+ write permissions in the directory.
+"Will not overwrite with undo file, cannot read"
+ A file exists with the name of the undo file to be written, but it
+ cannot be read. You may want to delete this file or rename it.
+"Will not overwrite, this is not an undo file"
+ A file exists with the name of the undo file to be written, but it
+ does not start with the right magic number. You may want to delete
+ this file or rename it.
+*E829* An error occurred while writing the undo file. You may want to try
+ again.
+
+==============================================================================
+6. Remarks about undo *undo-remarks*
The number of changes that are remembered is set with the 'undolevels' option.
If it is zero, the Vi-compatible way is always used. If it is negative no
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index cfadfd629b..65688eead7 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -359,6 +359,7 @@ m *+ole* Win32 GUI only: |ole-interface|
N *+path_extra* Up/downwards search in 'path' and 'tags'
m *+perl* Perl interface |perl|
m *+perl/dyn* Perl interface |perl-dynamic| |/dyn|
+H *+persistent_undo* Persistent undo |undo-persistence|
*+postscript* |:hardcopy| writes a PostScript file
N *+printer* |:hardcopy| command
H *+profile* |:profile| command
diff --git a/runtime/doc/version7.txt b/runtime/doc/version7.txt
index a6e1f61754..d59b622649 100644
--- a/runtime/doc/version7.txt
+++ b/runtime/doc/version7.txt
@@ -7170,6 +7170,10 @@ the buffer is marked as modified.
Added *added-7.3*
-----
+Persistent undo: store undo information in a file. Can undo to before when
+the file was read, also for unloaded buffers. |undo-persistence|
+(partly by Jordan Lewis)
+
Added the 'relativenumber' option. (Markus Heidelberg)
Support for Blowfish encryption. Added the 'cryptmethod' option.
diff --git a/runtime/optwin.vim b/runtime/optwin.vim
index 06a76624d7..0ace4cc6d4 100644
--- a/runtime/optwin.vim
+++ b/runtime/optwin.vim
@@ -1032,6 +1032,10 @@ if has("vertsplit")
call append("$", "cmdwinheight\theight of the command-line window")
call <SID>OptionG("cwh", &cwh)
endif
+call append("$", "undofile\tautomatically save and restore undo history")
+call <SID>BinOptionG("udf", &udf)
+call append("$", "undodir\tlist of directories for undo files")
+call <SID>OptionG("udir", &udir)
call <SID>Header("executing external commands")
diff --git a/runtime/tutor/tutor.it b/runtime/tutor/tutor.it
index b1f6798d01..69e83eb03d 100644
--- a/runtime/tutor/tutor.it
+++ b/runtime/tutor/tutor.it
@@ -288,7 +288,7 @@ NOTA: Se batti solo il movimento mentre sei in Modalità Normale, senza
2. Batti d2w per cancellare le due parole MAIUSCOLE
- 3. Ripeti i passi 1 e 2 con un contatore diverso per cancellare la parole
+ 3. Ripeti i passi 1 e 2 con un contatore diverso per cancellare le parole
MAIUSCOLE consecutive con un solo comando
---> questa ABC DE linea FGHI JK LMN OP di parole è Q RS TUV ora ripulita.
diff --git a/runtime/tutor/tutor.it.utf-8 b/runtime/tutor/tutor.it.utf-8
index 051b51bbea..bee3f6d8f2 100644
--- a/runtime/tutor/tutor.it.utf-8
+++ b/runtime/tutor/tutor.it.utf-8
@@ -288,7 +288,7 @@ NOTA: Se batti solo il movimento mentre sei in Modalità Normale, senza
2. Batti d2w per cancellare le due parole MAIUSCOLE
- 3. Ripeti i passi 1 e 2 con un contatore diverso per cancellare la parole
+ 3. Ripeti i passi 1 e 2 con un contatore diverso per cancellare le parole
MAIUSCOLE consecutive con un solo comando
---> questa ABC DE linea FGHI JK LMN OP di parole è Q RS TUV ora ripulita.
diff --git a/src/buffer.c b/src/buffer.c
index 531e4b9a29..5ecb638727 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -61,8 +61,9 @@ static void buf_delete_signs __ARGS((buf_T *buf));
#endif
/*
- * Open current buffer, that is: open the memfile and read the file into memory
- * return FAIL for failure, OK otherwise
+ * Open current buffer, that is: open the memfile and read the file into
+ * memory.
+ * Return FAIL for failure, OK otherwise.
*/
int
open_buffer(read_stdin, eap)
diff --git a/src/eval.c b/src/eval.c
index 446df8ed3f..3c238fcbec 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -11869,6 +11869,9 @@ f_has(argvars, rettv)
"perl",
#endif
#endif
+#ifdef FEAT_PERSISTENT_UNDO
+ "persistent_undo",
+#endif
#ifdef FEAT_PYTHON
#ifndef DYNAMIC_PYTHON
"python",
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index 1ef885acdd..f41e0f449d 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -773,6 +773,8 @@ EX(CMD_rubydo, "rubydo", ex_rubydo,
RANGE|DFLALL|EXTRA|NEEDARG|CMDWIN),
EX(CMD_rubyfile, "rubyfile", ex_rubyfile,
RANGE|FILE1|NEEDARG|CMDWIN),
+EX(CMD_rundo, "rundo", ex_rundo,
+ NEEDARG|EXTRA|XFILE),
EX(CMD_rviminfo, "rviminfo", ex_viminfo,
BANG|FILE1|TRLBAR|CMDWIN),
EX(CMD_substitute, "substitute", do_sub,
@@ -1061,6 +1063,8 @@ EX(CMD_wqall, "wqall", do_wqall,
BANG|FILE1|ARGOPT|DFLALL|TRLBAR),
EX(CMD_wsverb, "wsverb", ex_wsverb,
EXTRA|NOTADR|NEEDARG),
+EX(CMD_wundo, "wundo", ex_wundo,
+ BANG|NEEDARG|EXTRA|XFILE),
EX(CMD_wviminfo, "wviminfo", ex_viminfo,
BANG|FILE1|TRLBAR|CMDWIN),
EX(CMD_xit, "xit", ex_exit,
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index ff39040cf7..4097f1d8f2 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -243,6 +243,10 @@ static void ex_popup __ARGS((exarg_T *eap));
# define ex_spellinfo ex_ni
# define ex_spellrepall ex_ni
#endif
+#ifndef FEAT_PERSISTENT_UNDO
+# define ex_rundo ex_ni
+# define ex_wundo ex_ni
+#endif
#ifndef FEAT_MZSCHEME
# define ex_mzscheme ex_script_ni
# define ex_mzfile ex_ni
@@ -298,6 +302,10 @@ static void ex_join __ARGS((exarg_T *eap));
static void ex_at __ARGS((exarg_T *eap));
static void ex_bang __ARGS((exarg_T *eap));
static void ex_undo __ARGS((exarg_T *eap));
+#ifdef FEAT_PERSISTENT_UNDO
+static void ex_wundo __ARGS((exarg_T *eap));
+static void ex_rundo __ARGS((exarg_T *eap));
+#endif
static void ex_redo __ARGS((exarg_T *eap));
static void ex_later __ARGS((exarg_T *eap));
static void ex_redir __ARGS((exarg_T *eap));
@@ -8452,6 +8460,28 @@ ex_undo(eap)
u_undo(1);
}
+#ifdef FEAT_PERSISTENT_UNDO
+ void
+ex_wundo(eap)
+ exarg_T *eap;
+{
+ char_u hash[UNDO_HASH_SIZE];
+
+ u_compute_hash(hash);
+ u_write_undo(eap->arg, eap->forceit, curbuf, hash);
+}
+
+ void
+ex_rundo(eap)
+ exarg_T *eap;
+{
+ char_u hash[UNDO_HASH_SIZE];
+
+ u_compute_hash(hash);
+ u_read_undo(eap->arg, hash);
+}
+#endif
+
/*
* ":redo".
*/
diff --git a/src/feature.h b/src/feature.h
index 6b8f600ec0..61fe3345bb 100644
--- a/src/feature.h
+++ b/src/feature.h
@@ -1275,3 +1275,11 @@
|| defined(FEAT_BIG)
# define FEAT_AUTOCHDIR
#endif
+
+/*
+ * +persistent_undo 'undofile', 'undodir' options, :wundo and :rundo, and
+ * implementation.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_PERSISTENT_UNDO
+#endif
diff --git a/src/fileio.c b/src/fileio.c
index 7a697ee020..b7c86af7ef 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -253,6 +253,10 @@ readfile(fname, sfname, from, lines_to_skip, lines_to_read, eap, flags)
char_u *cryptkey = NULL;
int did_ask_for_key = FALSE;
#endif
+#ifdef FEAT_PERSISTENT_UNDO
+ context_sha256_T sha_ctx;
+ int read_undo_file = FALSE;
+#endif
int split = 0; /* number of split lines */
#define UNKNOWN 0x0fffffff /* file size is unknown */
linenr_T linecnt;
@@ -1178,6 +1182,12 @@ retry:
#ifdef FEAT_MBYTE
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);
+ if (read_undo_file)
+ sha256_start(&sha_ctx);
+#endif
}
while (!error && !got_int)
@@ -2133,6 +2143,10 @@ rewind_retry:
error = TRUE;
break;
}
+#ifdef FEAT_PERSISTENT_UNDO
+ if (read_undo_file)
+ sha256_update(&sha_ctx, line_start, len);
+#endif
++lnum;
if (--read_count == 0)
{
@@ -2197,6 +2211,10 @@ rewind_retry:
error = TRUE;
break;
}
+#ifdef FEAT_PERSISTENT_UNDO
+ if (read_undo_file)
+ sha256_update(&sha_ctx, line_start, len);
+#endif
++lnum;
if (--read_count == 0)
{
@@ -2237,11 +2255,17 @@ failed:
if (set_options)
curbuf->b_p_eol = FALSE;
*ptr = NUL;
- if (ml_append(lnum, line_start,
- (colnr_T)(ptr - line_start + 1), newfile) == FAIL)
+ len = (colnr_T)(ptr - line_start + 1);
+ if (ml_append(lnum, line_start, len, newfile) == FAIL)
error = TRUE;
else
+ {
+#ifdef FEAT_PERSISTENT_UNDO
+ if (read_undo_file)
+ sha256_update(&sha_ctx, line_start, len);
+#endif
read_no_eol_lnum = ++lnum;
+ }
}
if (set_options)
@@ -2555,6 +2579,19 @@ failed:
*/
write_no_eol_lnum = read_no_eol_lnum;
+#ifdef FEAT_PERSISTENT_UNDO
+ /*
+ * When opening a new file locate undo info and read it.
+ */
+ if (read_undo_file)
+ {
+ char_u hash[UNDO_HASH_SIZE];
+
+ sha256_finish(&sha_ctx, hash);
+ u_read_undo(NULL, hash);
+ }
+#endif
+
#ifdef FEAT_AUTOCMD
if (!read_stdin && !read_buffer)
{
@@ -3038,6 +3075,10 @@ buf_write(buf, fname, sfname, start, end, eap, append, forceit,
vim_acl_T acl = NULL; /* ACL copied from original file to
backup or new file */
#endif
+#ifdef FEAT_PERSISTENT_UNDO
+ int write_undo_file = FALSE;
+ context_sha256_T sha_ctx;
+#endif
if (fname == NULL || *fname == NUL) /* safety check */
return FAIL;
@@ -4344,6 +4385,14 @@ restore_backup:
write_info.bw_start_lnum = start;
#endif
+#ifdef FEAT_PERSISTENT_UNDO
+ write_undo_file = (buf->b_p_udf && overwriting && !append
+ && !filtering && reset_changed);
+ if (write_undo_file)
+ /* Prepare for computing the hash value of the text. */
+ sha256_start(&sha_ctx);
+#endif
+
write_info.bw_len = bufsize;
#ifdef HAS_BW_FLAGS
write_info.bw_flags = wb_flags;
@@ -4358,6 +4407,10 @@ restore_backup:
* Keep it fast!
*/
ptr = ml_get_buf(buf, lnum, FALSE) - 1;
+#ifdef FEAT_PERSISTENT_UNDO
+ if (write_undo_file)
+ sha256_update(&sha_ctx, ptr + 1, STRLEN(ptr + 1) + 1);
+#endif
while ((c = *++ptr) != NUL)
{
if (c == NL)
@@ -4886,6 +4939,20 @@ nofail:
}
msg_scroll = msg_save;
+#ifdef FEAT_PERSISTENT_UNDO
+ /*
+ * When writing the whole file and 'undofile' is set, also write the undo
+ * file.
+ */
+ if (retval == OK && write_undo_file)
+ {
+ char_u hash[UNDO_HASH_SIZE];
+
+ sha256_finish(&sha_ctx, hash);
+ u_write_undo(NULL, FALSE, buf, hash);
+ }
+#endif
+
#ifdef FEAT_AUTOCMD
#ifdef FEAT_EVAL
if (!should_abort(retval))
diff --git a/src/memline.c b/src/memline.c
index b3c1727335..c3fdba3137 100644
--- a/src/memline.c
+++ b/src/memline.c
@@ -245,9 +245,6 @@ static char_u *make_percent_swname __ARGS((char_u *dir, char_u *name));
#ifdef FEAT_BYTEOFF
static void ml_updatechunk __ARGS((buf_T *buf, long line, long len, int updtype));
#endif
-#ifdef HAVE_READLINK
-static int resolve_symlink __ARGS((char_u *fname, char_u *buf));
-#endif
/*
* Open a new memline for "buf".
@@ -3559,7 +3556,7 @@ ml_lineadd(buf, count)
}
}
-#ifdef HAVE_READLINK
+#if defined(HAVE_READLINK) || defined(PROTO)
/*
* Resolve a symlink in the last component of a file name.
* Note that f_resolve() does it for every part of the path, we don't do that
@@ -3567,7 +3564,7 @@ ml_lineadd(buf, count)
* If it worked returns OK and the resolved link in "buf[MAXPATHL]".
* Otherwise returns FAIL.
*/
- static int
+ int
resolve_symlink(fname, buf)
char_u *fname;
char_u *buf;
@@ -3862,7 +3859,7 @@ do_swapexists(buf, fname)
* Returns the name in allocated memory or NULL.
*
* Note: If BASENAMELEN is not correct, you will get error messages for
- * not being able to open the swapfile
+ * not being able to open the swap or undo file
* Note: May trigger SwapExists autocmd, pointers may change!
*/
static char_u *
@@ -3886,29 +3883,29 @@ findswapname(buf, dirp, old_fname)
# define CREATE_DUMMY_FILE
FILE *dummyfd = NULL;
-/*
- * If we start editing a new file, e.g. "test.doc", which resides on an MSDOS
- * compatible filesystem, it is possible that the file "test.doc.swp" which we
- * create will be exactly the same file. To avoid this problem we temporarily
- * create "test.doc".
- * Don't do this when the check below for a 8.3 file name is used.
- */
+ /*
+ * If we start editing a new file, e.g. "test.doc", which resides on an
+ * MSDOS compatible filesystem, it is possible that the file
+ * "test.doc.swp" which we create will be exactly the same file. To avoid
+ * this problem we temporarily create "test.doc". Don't do this when the
+ * check below for a 8.3 file name is used.
+ */
if (!(buf->b_p_sn || buf->b_shortname) && buf->b_fname != NULL
&& mch_getperm(buf->b_fname) < 0)
dummyfd = mch_fopen((char *)buf->b_fname, "w");
#endif
-/*
- * Isolate a directory name from *dirp and put it in dir_name.
- * First allocate some memory to put the directory name in.
- */
+ /*
+ * Isolate a directory name from *dirp and put it in dir_name.
+ * First allocate some memory to put the directory name in.
+ */
dir_name = alloc((unsigned)STRLEN(*dirp) + 1);
if (dir_name != NULL)
(void)copy_option_part(dirp, dir_name, 31000, ",");
-/*
- * we try different names until we find one that does not exist yet
- */
+ /*
+ * we try different names until we find one that does not exist yet
+ */
if (dir_name == NULL) /* out of memo