diff options
author | ZyX <kp-pav@yandex.ru> | 2015-07-07 23:49:22 +0300 |
---|---|---|
committer | ZyX <kp-pav@yandex.ru> | 2015-10-08 22:00:09 +0300 |
commit | 1d3823a5c9c7b7494966d4e0851e2c1decbed76c (patch) | |
tree | bb1c55526b3e84adcbc04095d05e3c7269c84177 | |
parent | f43a5e692647de81a692e537f1e748667ff84fb4 (diff) | |
download | rneovim-1d3823a5c9c7b7494966d4e0851e2c1decbed76c.tar.gz rneovim-1d3823a5c9c7b7494966d4e0851e2c1decbed76c.tar.bz2 rneovim-1d3823a5c9c7b7494966d4e0851e2c1decbed76c.zip |
shada: Populate v:oldfiles
-rw-r--r-- | src/nvim/shada.c | 107 | ||||
-rw-r--r-- | test/functional/shada/marks_spec.lua | 15 |
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') |