aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZyX <kp-pav@yandex.ru>2015-07-07 23:49:22 +0300
committerZyX <kp-pav@yandex.ru>2015-10-08 22:00:09 +0300
commit1d3823a5c9c7b7494966d4e0851e2c1decbed76c (patch)
treebb1c55526b3e84adcbc04095d05e3c7269c84177
parentf43a5e692647de81a692e537f1e748667ff84fb4 (diff)
downloadrneovim-1d3823a5c9c7b7494966d4e0851e2c1decbed76c.tar.gz
rneovim-1d3823a5c9c7b7494966d4e0851e2c1decbed76c.tar.bz2
rneovim-1d3823a5c9c7b7494966d4e0851e2c1decbed76c.zip
shada: Populate v:oldfiles
-rw-r--r--src/nvim/shada.c107
-rw-r--r--test/functional/shada/marks_spec.lua15
2 files changed, 101 insertions, 21 deletions
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index 6cbaf110c6..3dbd24b7ea 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -60,6 +60,7 @@ KHASH_SET_INIT_INT64(bufset)
# error Not a 64- or 32-bit architecture
#endif
KHASH_MAP_INIT_STR(fnamebufs, buf_T *)
+KHASH_SET_INIT_STR(strset)
#define copy_option_part(src, dest, ...) \
((char *) copy_option_part((char_u **) src, (char_u *) dest, __VA_ARGS__))
@@ -171,11 +172,16 @@ enum SRNIFlags {
kSDReadUnknown = (1 << (SHADA_LAST_ENTRY + 1)), ///< Determines whether
///< unknown items should be
///< read (usually disabled).
- kSDReadLocalMarks = (
- (1 << kSDItemLocalMark)
- | (1 << kSDItemChange)
- ), ///< Determines whether local marks and change list should be read. Can
- ///< only be disabled by disabling &shada or putting '0 there.
+ kSDReadLocalMarks = (1 << kSDItemLocalMark), ///< Determines whether local
+ ///< marks should be read. Can
+ ///< only be disabled by
+ ///< disabling &shada or putting
+ ///< '0 there. Is also used for
+ ///< v:oldfiles.
+ kSDReadChanges = (1 << kSDItemChange), ///< Determines whether change list
+ ///< should be read. Can only be
+ ///< disabled by disabling &shada or
+ ///< putting '0 there.
};
// Note: SRNIFlags enum name was created only to make it possible to reference
// it. This name is not actually used anywhere outside of the documentation.
@@ -475,6 +481,18 @@ static inline bool in_bufset(const khash_t(bufset) *const set, const buf_T *buf)
return kh_get(bufset, set, (uintptr_t) buf) != kh_end(set);
}
+/// Check whether string is in the given set
+///
+/// @param[in] set Set to check within.
+/// @param[in] buf Buffer to find.
+///
+/// @return true or false.
+static inline bool in_strset(const khash_t(strset) *const set, char *str)
+ FUNC_ATTR_PURE
+{
+ return kh_get(strset, set, str) != kh_end(set);
+}
+
/// Check whether buffer is on removable media
///
/// Uses pre-populated set with buffers on removable media named removable_bufs.
@@ -673,8 +691,10 @@ static inline bool marks_equal(const pos_T a, const pos_T b)
static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
FUNC_ATTR_NONNULL_ALL
{
- // TODO(ZyX-I): Also load v:oldfiles.
unsigned srni_flags = 0;
+ const bool force = flags & kShaDaForceit;
+ const bool get_old_files = flags & (kShaDaGetOldfiles | kShaDaForceit);
+ const bool want_marks = flags & kShaDaWantMarks;
if (flags & kShaDaWantInfo) {
srni_flags |= kSDReadUndisableableData | kSDReadRegisters;
if (p_hi) {
@@ -687,16 +707,18 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
srni_flags |= kSDReadBufferList;
}
}
- if (flags & kShaDaWantMarks) {
+ if (want_marks) {
if (get_shada_parameter('\'') > 0) {
- srni_flags |= kSDReadLocalMarks;
+ srni_flags |= kSDReadLocalMarks | kSDReadChanges;
}
}
+ if (get_old_files) {
+ srni_flags |= kSDReadLocalMarks;
+ }
if (srni_flags == 0) {
// Nothing to do.
return;
}
- const bool force = flags & kShaDaForceit;
HistoryMergerState hms[HIST_COUNT];
if (srni_flags & kSDReadHistory) {
for (uint8_t i = 0; i < HIST_COUNT; i++) {
@@ -707,8 +729,23 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
}
}
ShadaEntry cur_entry;
- khash_t(bufset) *cl_bufs = kh_init(bufset);
- khash_t(fnamebufs) *fname_bufs = kh_init(fnamebufs);
+ khash_t(bufset) *cl_bufs = NULL;
+ if (srni_flags & kSDReadChanges) {
+ cl_bufs = kh_init(bufset);
+ }
+ khash_t(fnamebufs) *fname_bufs = NULL;
+ if (srni_flags & (kSDReadUndisableableData
+ | kSDReadChanges
+ | kSDReadLocalMarks)) {
+ fname_bufs = kh_init(fnamebufs);
+ }
+ khash_t(strset) *oldfiles_set = NULL;
+ list_T *oldfiles_list = NULL;
+ if (get_old_files) {
+ oldfiles_set = kh_init(strset);
+ oldfiles_list = list_alloc();
+ set_vim_var_list(VV_OLDFILES, oldfiles_list);
+ }
while (shada_read_next_item(sd_reader, &cur_entry, srni_flags) == NOTDONE) {
switch (cur_entry.type) {
case kSDItemMissing: {
@@ -904,6 +941,27 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
}
case kSDItemChange:
case kSDItemLocalMark: {
+ if (oldfiles_set != NULL
+ && !in_strset(oldfiles_set, cur_entry.data.filemark.fname)) {
+ char *fname = cur_entry.data.filemark.fname;
+ if (want_marks) {
+ // Do not bother with allocating memory for the string if already
+ // allocated string from cur_entry can be used. It cannot be used if
+ // want_marks is set because this way it may be used for a mark.
+ fname = xstrdup(fname);
+ }
+ int kh_ret;
+ (void) kh_put(strset, oldfiles_set, fname, &kh_ret);
+ list_append_allocated_string(oldfiles_list, fname);
+ if (!want_marks) {
+ // Avoid free because this string was already used.
+ cur_entry.data.filemark.fname = NULL;
+ }
+ }
+ if (!want_marks) {
+ shada_free_shada_entry(&cur_entry);
+ break;
+ }
buf_T *buf = find_buffer(fname_bufs, cur_entry.data.filemark.fname);
if (buf == NULL) {
shada_free_shada_entry(&cur_entry);
@@ -1015,18 +1073,25 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
hm_rb_dealloc(&(hms[i].hmrb));
}
}
- FOR_ALL_TAB_WINDOWS(tp, wp) {
- (void) tp;
- if (in_bufset(cl_bufs, wp->w_buffer)) {
- wp->w_changelistidx = wp->w_buffer->b_changelistlen;
+ if (cl_bufs != NULL) {
+ FOR_ALL_TAB_WINDOWS(tp, wp) {
+ (void) tp;
+ if (in_bufset(cl_bufs, wp->w_buffer)) {
+ wp->w_changelistidx = wp->w_buffer->b_changelistlen;
+ }
}
+ kh_destroy(bufset, cl_bufs);
+ }
+ if (fname_bufs != NULL) {
+ const char *key;
+ kh_foreach_key(fname_bufs, key, {
+ xfree((void *) key);
+ })
+ kh_destroy(fnamebufs, fname_bufs);
+ }
+ if (oldfiles_set != NULL) {
+ kh_destroy(strset, oldfiles_set);
}
- kh_destroy(bufset, cl_bufs);
- const char *key;
- kh_foreach_key(fname_bufs, key, {
- xfree((void *) key);
- })
- kh_destroy(fnamebufs, fname_bufs);
}
/// Get the ShaDa file name to use
diff --git a/test/functional/shada/marks_spec.lua b/test/functional/shada/marks_spec.lua
index b69477b6ed..4909ae608e 100644
--- a/test/functional/shada/marks_spec.lua
+++ b/test/functional/shada/marks_spec.lua
@@ -95,6 +95,21 @@ describe('ShaDa support code', function()
eq(2, nvim_current_line())
end)
+ it('is able to populate v:oldfiles', function()
+ nvim_command('edit ' .. testfilename)
+ local tf_full = nvim_eval('fnamemodify(bufname("%"), ":p")')
+ nvim_command('edit ' .. testfilename_2)
+ local tf_full_2 = nvim_eval('fnamemodify(bufname("%"), ":p")')
+ nvim_command('qall')
+ reset()
+ local oldfiles = nvim('get_vvar', 'oldfiles')
+ eq(2, #oldfiles)
+ eq(testfilename, oldfiles[1]:sub(-#testfilename))
+ eq(testfilename_2, oldfiles[2]:sub(-#testfilename_2))
+ eq(tf_full, oldfiles[1])
+ eq(tf_full_2, oldfiles[2])
+ end)
+
it('is able to dump and restore jump list', function()
nvim_command('edit ' .. testfilename_2)
nvim_feed('G')