diff options
-rw-r--r-- | src/nvim/autocmd.c | 1 | ||||
-rw-r--r-- | src/nvim/buffer.c | 2 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 6 | ||||
-rw-r--r-- | src/nvim/change.c | 4 | ||||
-rw-r--r-- | src/nvim/change.h | 7 | ||||
-rw-r--r-- | src/nvim/eval.c | 25 | ||||
-rw-r--r-- | src/nvim/eval.h | 7 | ||||
-rw-r--r-- | src/nvim/eval/typval.c | 1 | ||||
-rw-r--r-- | src/nvim/event/rstream.c | 1 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 1 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 1 | ||||
-rw-r--r-- | src/nvim/fold.c | 1 | ||||
-rw-r--r-- | src/nvim/main.c | 44 | ||||
-rw-r--r-- | src/nvim/memline.c | 11 | ||||
-rw-r--r-- | src/nvim/misc1.c | 204 | ||||
-rw-r--r-- | src/nvim/misc1.h | 7 | ||||
-rw-r--r-- | src/nvim/option.c | 2 | ||||
-rw-r--r-- | src/nvim/os/input.c | 34 | ||||
-rw-r--r-- | src/nvim/path.c | 11 | ||||
-rw-r--r-- | src/nvim/regexp.c | 1 | ||||
-rw-r--r-- | src/nvim/regexp_nfa.c | 1 | ||||
-rw-r--r-- | src/nvim/screen.c | 13 | ||||
-rw-r--r-- | src/nvim/search.c | 1 | ||||
-rw-r--r-- | src/nvim/spellfile.c | 1 | ||||
-rw-r--r-- | src/nvim/state.c | 32 | ||||
-rw-r--r-- | src/nvim/syntax.c | 1 | ||||
-rw-r--r-- | src/nvim/undo.c | 35 |
27 files changed, 227 insertions, 228 deletions
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 9044657358..0248230e15 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -17,6 +17,7 @@ #include "nvim/getchar.h" #include "nvim/misc1.h" #include "nvim/option.h" +#include "nvim/os/input.h" #include "nvim/regexp.h" #include "nvim/search.h" #include "nvim/state.h" diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index f2f4950e58..297d9743df 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -2719,7 +2719,7 @@ void buflist_list(exarg_T *eap) IObuff[len++] = ' '; } while (--i > 0 && len < IOSIZE - 18); if (vim_strchr(eap->arg, 't') && buf->b_last_used) { - add_time(IObuff + len, (size_t)(IOSIZE - len), buf->b_last_used); + undo_fmt_time(IObuff + len, (size_t)(IOSIZE - len), buf->b_last_used); } else { vim_snprintf((char *)IObuff + len, (size_t)(IOSIZE - len), _("line %" PRId64), diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index e53b2d1dfa..49e527e98b 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1116,12 +1116,6 @@ typedef struct { pos_T w_cursor_corr; // corrected cursor position } pos_save_T; -// Struct passed to get_v_event() and restore_v_event(). -typedef struct { - bool sve_did_save; - hashtab_T sve_hashtab; -} save_v_event_T; - /// Indices into vimmenu_T->strings[] and vimmenu_T->noremap[] for each mode /// \addtogroup MENU_INDEX /// @{ diff --git a/src/nvim/change.c b/src/nvim/change.c index ef771125f1..96fbaa9166 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -131,7 +131,7 @@ void changed_internal(void) curbuf->b_changed = true; curbuf->b_changed_invalid = true; ml_setflags(curbuf); - check_status(curbuf); + redraw_buf_status_later(curbuf); redraw_tabline = true; need_maketitle = true; // set window title later } @@ -517,7 +517,7 @@ void unchanged(buf_T *buf, int ff, bool always_inc_changedtick) if (ff) { save_file_ff(buf); } - check_status(buf); + redraw_buf_status_later(buf); redraw_tabline = true; need_maketitle = true; // set window title later buf_inc_changedtick(buf); diff --git a/src/nvim/change.h b/src/nvim/change.h index e1a1bfba17..e7c8a2b031 100644 --- a/src/nvim/change.h +++ b/src/nvim/change.h @@ -4,6 +4,13 @@ #include "nvim/buffer_defs.h" // for buf_T #include "nvim/pos.h" // for linenr_T +// flags for open_line() +#define OPENLINE_DELSPACES 1 // delete spaces after cursor +#define OPENLINE_DO_COM 2 // format comments +#define OPENLINE_KEEPTRAIL 4 // keep trailing spaces +#define OPENLINE_MARKFIX 8 // fix mark positions +#define OPENLINE_COM_LIST 16 // format comments with list/2nd line indent + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "change.h.generated.h" #endif diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 85e81ee975..d45aa8194c 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -303,6 +303,31 @@ const list_T *eval_msgpack_type_lists[] = { [kMPExt] = NULL, }; +dict_T *get_v_event(save_v_event_T *sve) +{ + dict_T *v_event = get_vim_var_dict(VV_EVENT); + + if (v_event->dv_hashtab.ht_used > 0) { + // recursive use of v:event, save, make empty and restore later + sve->sve_did_save = true; + sve->sve_hashtab = v_event->dv_hashtab; + hash_init(&v_event->dv_hashtab); + } else { + sve->sve_did_save = false; + } + return v_event; +} + +void restore_v_event(dict_T *v_event, save_v_event_T *sve) +{ + tv_dict_free_contents(v_event); + if (sve->sve_did_save) { + v_event->dv_hashtab = sve->sve_hashtab; + } else { + hash_init(&v_event->dv_hashtab); + } +} + // Return "n1" divided by "n2", taking care of dividing by zero. varnumber_T num_divide(varnumber_T n1, varnumber_T n2) FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT diff --git a/src/nvim/eval.h b/src/nvim/eval.h index 3b3a68bd29..a9ec5d47a6 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -193,6 +193,13 @@ extern const list_T *eval_msgpack_type_lists[LAST_MSGPACK_TYPE + 1]; #undef LAST_MSGPACK_TYPE +// Struct passed to get_v_event() and restore_v_event(). +typedef struct { + bool sve_did_save; + hashtab_T sve_hashtab; +} save_v_event_T; + + /// trans_function_name() flags typedef enum { TFN_INT = 1, ///< May use internal function name diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 3e37e8cbb6..dfb2500b49 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -28,6 +28,7 @@ #include "nvim/mbyte.h" #include "nvim/memory.h" #include "nvim/message.h" +#include "nvim/os/input.h" #include "nvim/pos.h" #include "nvim/types.h" #include "nvim/vim.h" diff --git a/src/nvim/event/rstream.c b/src/nvim/event/rstream.c index f070c8179f..755307781c 100644 --- a/src/nvim/event/rstream.c +++ b/src/nvim/event/rstream.c @@ -12,6 +12,7 @@ #include "nvim/event/rstream.h" #include "nvim/log.h" #include "nvim/memory.h" +#include "nvim/main.h" #include "nvim/misc1.h" #include "nvim/vim.h" diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 449e6f7bf5..2dc098df8c 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -41,6 +41,7 @@ #include "nvim/ops.h" #include "nvim/option.h" #include "nvim/os/fs_defs.h" +#include "nvim/os/input.h" #include "nvim/os/shell.h" #include "nvim/os_unix.h" #include "nvim/path.h" diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 77cd50ecb7..4c040bff7f 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -68,6 +68,7 @@ #include "nvim/spell.h" #include "nvim/spellfile.h" #include "nvim/strings.h" +#include "nvim/state.h" #include "nvim/syntax.h" #include "nvim/tag.h" #include "nvim/terminal.h" diff --git a/src/nvim/fold.c b/src/nvim/fold.c index 4a8be7a31b..7806d3eada 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -32,6 +32,7 @@ #include "nvim/move.h" #include "nvim/ops.h" #include "nvim/option.h" +#include "nvim/os/input.h" #include "nvim/plines.h" #include "nvim/screen.h" #include "nvim/strings.h" diff --git a/src/nvim/main.c b/src/nvim/main.c index 921bc883cf..29510e26ff 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -696,6 +696,50 @@ void getout(int exitval) os_exit(exitval); } +/// Preserve files and exit. +/// @note IObuff must contain a message. +/// @note This may be called from deadly_signal() in a signal handler, avoid +/// unsafe functions, such as allocating memory. +void preserve_exit(void) + FUNC_ATTR_NORETURN +{ + // 'true' when we are sure to exit, e.g., after a deadly signal + static bool really_exiting = false; + + // Prevent repeated calls into this method. + if (really_exiting) { + if (input_global_fd() >= 0) { + // normalize stream (#2598) + stream_set_blocking(input_global_fd(), true); + } + exit(2); + } + + really_exiting = true; + // Ignore SIGHUP while we are already exiting. #9274 + signal_reject_deadly(); + mch_errmsg(IObuff); + mch_errmsg("\n"); + ui_flush(); + + ml_close_notmod(); // close all not-modified buffers + + FOR_ALL_BUFFERS(buf) { + if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL) { + mch_errmsg("Vim: preserving files...\r\n"); + ui_flush(); + ml_sync_all(false, false, true); // preserve all swap files + break; + } + } + + ml_close_all(false); // close all memfiles, without deleting + + mch_errmsg("Vim: Finished.\r\n"); + + getout(1); +} + /// Gets the integer value of a numeric command line argument if given, /// such as '-o10'. /// diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 08202a6d5c..40da4b48f8 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -1841,6 +1841,17 @@ char_u *ml_get_pos(const pos_T *pos) return ml_get_buf(curbuf, pos->lnum, false) + pos->col; } +/// get codepoint at pos. pos must be either valid or have col set to MAXCOL! +int gchar_pos(pos_T *pos) + FUNC_ATTR_NONNULL_ARG(1) +{ + // When searching columns is sometimes put at the end of a line. + if (pos->col == MAXCOL) { + return NUL; + } + return utf_ptr2char(ml_get_pos(pos)); +} + /// Return a pointer to a line in a specific buffer /// /// @param will_change true mark the buffer dirty (chars in the line will be changed) diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index 872a2c58e3..3873a5c49a 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -373,32 +373,6 @@ int get_last_leader_offset(char_u *line, char_u **flags) return result; } -int gchar_pos(pos_T *pos) - FUNC_ATTR_NONNULL_ARG(1) -{ - // When searching columns is sometimes put at the end of a line. - if (pos->col == MAXCOL) { - return NUL; - } - return utf_ptr2char(ml_get_pos(pos)); -} - -/* - * check_status: called when the status bars for the buffer 'buf' - * need to be updated - */ -void check_status(buf_T *buf) -{ - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if (wp->w_buffer == buf && wp->w_status_height) { - wp->w_redr_status = TRUE; - if (must_redraw < VALID) { - must_redraw = VALID; - } - } - } -} - /// Ask for a reply from the user, 'y' or 'n' /// /// No other characters are accepted, the message is repeated until a valid @@ -814,91 +788,6 @@ int match_user(char_u *name) return result; } -/// Preserve files and exit. -/// @note IObuff must contain a message. -/// @note This may be called from deadly_signal() in a signal handler, avoid -/// unsafe functions, such as allocating memory. -void preserve_exit(void) - FUNC_ATTR_NORETURN -{ - // 'true' when we are sure to exit, e.g., after a deadly signal - static bool really_exiting = false; - - // Prevent repeated calls into this method. - if (really_exiting) { - if (input_global_fd() >= 0) { - // normalize stream (#2598) - stream_set_blocking(input_global_fd(), true); - } - exit(2); - } - - really_exiting = true; - // Ignore SIGHUP while we are already exiting. #9274 - signal_reject_deadly(); - mch_errmsg(IObuff); - mch_errmsg("\n"); - ui_flush(); - - ml_close_notmod(); // close all not-modified buffers - - FOR_ALL_BUFFERS(buf) { - if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL) { - mch_errmsg("Vim: preserving files...\r\n"); - ui_flush(); - ml_sync_all(false, false, true); // preserve all swap files - break; - } - } - - ml_close_all(false); // close all memfiles, without deleting - - mch_errmsg("Vim: Finished.\r\n"); - - getout(1); -} - -/* - * Check for CTRL-C pressed, but only once in a while. - * Should be used instead of os_breakcheck() for functions that check for - * each line in the file. Calling os_breakcheck() each time takes too much - * time, because it can be a system call. - */ - -#ifndef BREAKCHECK_SKIP -# define BREAKCHECK_SKIP 1000 -#endif - -static int breakcheck_count = 0; - -void line_breakcheck(void) -{ - if (++breakcheck_count >= BREAKCHECK_SKIP) { - breakcheck_count = 0; - os_breakcheck(); - } -} - -/* - * Like line_breakcheck() but check 10 times less often. - */ -void fast_breakcheck(void) -{ - if (++breakcheck_count >= BREAKCHECK_SKIP * 10) { - breakcheck_count = 0; - os_breakcheck(); - } -} - -// Like line_breakcheck() but check 100 times less often. -void veryfast_breakcheck(void) -{ - if (++breakcheck_count >= BREAKCHECK_SKIP * 100) { - breakcheck_count = 0; - os_breakcheck(); - } -} - /// os_call_shell() wrapper. Handles 'verbose', :profile, and v:shell_error. /// Invalidates cached tags. /// @@ -1013,21 +902,6 @@ done: } /* - * Free the list of files returned by expand_wildcards() or other expansion - * functions. - */ -void FreeWild(int count, char_u **files) -{ - if (count <= 0 || files == NULL) { - return; - } - while (count--) { - xfree(files[count]); - } - xfree(files); -} - -/* * Return TRUE when need to go to Insert mode because of 'insertmode'. * Don't do this when still processing a command or a mapping. * Don't do this when inside a ":normal" command. @@ -1036,81 +910,3 @@ int goto_im(void) { return p_im && stuff_empty() && typebuf_typed(); } - -/// Put the timestamp of an undo header in "buf[buflen]" in a nice format. -void add_time(char_u *buf, size_t buflen, time_t tt) -{ - struct tm curtime; - - if (time(NULL) - tt >= 100) { - os_localtime_r(&tt, &curtime); - if (time(NULL) - tt < (60L * 60L * 12L)) { - // within 12 hours - (void)strftime((char *)buf, buflen, "%H:%M:%S", &curtime); - } else { - // longer ago - (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", &curtime); - } - } else { - int64_t seconds = time(NULL) - tt; - vim_snprintf((char *)buf, buflen, - NGETTEXT("%" PRId64 " second ago", - "%" PRId64 " seconds ago", (uint32_t)seconds), - seconds); - } -} - -dict_T *get_v_event(save_v_event_T *sve) -{ - dict_T *v_event = get_vim_var_dict(VV_EVENT); - - if (v_event->dv_hashtab.ht_used > 0) { - // recursive use of v:event, save, make empty and restore later - sve->sve_did_save = true; - sve->sve_hashtab = v_event->dv_hashtab; - hash_init(&v_event->dv_hashtab); - } else { - sve->sve_did_save = false; - } - return v_event; -} - -void restore_v_event(dict_T *v_event, save_v_event_T *sve) -{ - tv_dict_free_contents(v_event); - if (sve->sve_did_save) { - v_event->dv_hashtab = sve->sve_hashtab; - } else { - hash_init(&v_event->dv_hashtab); - } -} - -/// Fires a ModeChanged autocmd. -void trigger_modechanged(void) -{ - if (!has_event(EVENT_MODECHANGED)) { - return; - } - - char *mode = get_mode(); - if (STRCMP(mode, last_mode) == 0) { - xfree(mode); - return; - } - - save_v_event_T save_v_event; - dict_T *v_event = get_v_event(&save_v_event); - tv_dict_add_str(v_event, S_LEN("new_mode"), mode); - tv_dict_add_str(v_event, S_LEN("old_mode"), last_mode); - - char_u *pat_pre = concat_str((char_u *)last_mode, (char_u *)":"); - char_u *pat = concat_str(pat_pre, (char_u *)mode); - xfree(pat_pre); - - apply_autocmds(EVENT_MODECHANGED, pat, NULL, false, curbuf); - xfree(last_mode); - last_mode = mode; - - xfree(pat); - restore_v_event(v_event, &save_v_event); -} diff --git a/src/nvim/misc1.h b/src/nvim/misc1.h index 4ce142c4c5..14ca361073 100644 --- a/src/nvim/misc1.h +++ b/src/nvim/misc1.h @@ -4,13 +4,6 @@ #include "nvim/os/shell.h" #include "nvim/vim.h" -// flags for open_line() -#define OPENLINE_DELSPACES 1 // delete spaces after cursor -#define OPENLINE_DO_COM 2 // format comments -#define OPENLINE_KEEPTRAIL 4 // keep trailing spaces -#define OPENLINE_MARKFIX 8 // fix mark positions -#define OPENLINE_COM_LIST 16 // format comments with list/2nd line indent - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "misc1.h.generated.h" #endif diff --git a/src/nvim/option.c b/src/nvim/option.c index 92c27378ee..05929193b8 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -7899,7 +7899,7 @@ void set_fileformat(int eol_style, int opt_flags) } // This may cause the buffer to become (un)modified. - check_status(curbuf); + redraw_buf_status_later(curbuf); redraw_tabline = true; need_maketitle = true; // Set window title later. } diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index 5b231f205b..fc9bbbc8b0 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -183,6 +183,40 @@ void os_breakcheck(void) updating_screen = save_us; } +#define BREAKCHECK_SKIP 1000 +static int breakcheck_count = 0; + +/// Check for CTRL-C pressed, but only once in a while. +/// +/// Should be used instead of os_breakcheck() for functions that check for +/// each line in the file. Calling os_breakcheck() each time takes too much +/// time, because it will use system calls to check for input. +void line_breakcheck(void) +{ + if (++breakcheck_count >= BREAKCHECK_SKIP) { + breakcheck_count = 0; + os_breakcheck(); + } +} + +/// Like line_breakcheck() but check 10 times less often. +void fast_breakcheck(void) +{ + if (++breakcheck_count >= BREAKCHECK_SKIP * 10) { + breakcheck_count = 0; + os_breakcheck(); + } +} + +/// Like line_breakcheck() but check 100 times less often. +void veryfast_breakcheck(void) +{ + if (++breakcheck_count >= BREAKCHECK_SKIP * 100) { + breakcheck_count = 0; + os_breakcheck(); + } +} + /// Test whether a file descriptor refers to a terminal. /// diff --git a/src/nvim/path.c b/src/nvim/path.c index 7b9081eafa..01ac88d537 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -1337,6 +1337,17 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***fil return ((flags & EW_EMPTYOK) || ga.ga_data != NULL) ? OK : FAIL; } +/// Free the list of files returned by expand_wildcards() or other expansion functions. +void FreeWild(int count, char_u **files) +{ + if (count <= 0 || files == NULL) { + return; + } + while (count--) { + xfree(files[count]); + } + xfree(files); +} /* * Return TRUE if we can expand this backtick thing here. diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index e67efb8ea0..aa8d1503fc 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -65,6 +65,7 @@ #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/misc1.h" +#include "nvim/os/input.h" #include "nvim/plines.h" #include "nvim/garray.h" #include "nvim/strings.h" diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index 5df5cc5975..3e7306bad3 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -16,6 +16,7 @@ #include "nvim/ascii.h" #include "nvim/garray.h" +#include "nvim/os/input.h" /* * Logging of NFA engine. diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 6d3142451f..0d06c45229 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -314,6 +314,19 @@ void update_curbuf(int type) update_screen(type); } +/// called when the status bars for the buffer 'buf' need to be updated +void redraw_buf_status_later(buf_T *buf) +{ + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + if (wp->w_buffer == buf && wp->w_status_height) { + wp->w_redr_status = true; + if (must_redraw < VALID) { + must_redraw = VALID; + } + } + } +} + /// Redraw the parts of the screen that is marked for redraw. /// /// Most code shouldn't call this directly, rather use redraw_later() and diff --git a/src/nvim/search.c b/src/nvim/search.c index f47315705c..f45d709b91 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -36,6 +36,7 @@ #include "nvim/move.h" #include "nvim/normal.h" #include "nvim/option.h" +#include "nvim/os/input.h" #include "nvim/os/time.h" #include "nvim/path.h" #include "nvim/regexp.h" diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index ae4514dd30..c65fcc1180 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -239,6 +239,7 @@ #include "nvim/memory.h" #include "nvim/misc1.h" #include "nvim/option.h" +#include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/path.h" #include "nvim/regexp.h" diff --git a/src/nvim/state.c b/src/nvim/state.c index 71db25664f..68bc76660d 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -4,7 +4,9 @@ #include <assert.h> #include "nvim/ascii.h" +#include "nvim/autocmd.h" #include "nvim/edit.h" +#include "nvim/eval.h" #include "nvim/ex_docmd.h" #include "nvim/getchar.h" #include "nvim/lib/kvec.h" @@ -202,3 +204,33 @@ char *get_mode(void) return buf; } + +/// Fires a ModeChanged autocmd. +void trigger_modechanged(void) +{ + if (!has_event(EVENT_MODECHANGED)) { + return; + } + + char *mode = get_mode(); + if (STRCMP(mode, last_mode) == 0) { + xfree(mode); + return; + } + + save_v_event_T save_v_event; + dict_T *v_event = get_v_event(&save_v_event); + tv_dict_add_str(v_event, S_LEN("new_mode"), mode); + tv_dict_add_str(v_event, S_LEN("old_mode"), last_mode); + + char_u *pat_pre = concat_str((char_u *)last_mode, (char_u *)":"); + char_u *pat = concat_str(pat_pre, (char_u *)mode); + xfree(pat_pre); + + apply_autocmds(EVENT_MODECHANGED, pat, NULL, false, curbuf); + xfree(last_mode); + last_mode = mode; + + xfree(pat); + restore_v_event(v_event, &save_v_event); +} diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 9a133eeadf..a39f78b751 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -34,6 +34,7 @@ #include "nvim/message.h" #include "nvim/misc1.h" #include "nvim/option.h" +#include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/os/time.h" #include "nvim/os_unix.h" diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 8161fce9f4..3e7eb6d01e 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -100,6 +100,7 @@ #include "nvim/message.h" #include "nvim/misc1.h" #include "nvim/option.h" +#include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/os/time.h" #include "nvim/os_unix.h" @@ -2621,7 +2622,7 @@ static void u_undo_end(bool did_undo, bool absolute, bool quiet) if (uhp == NULL) { *msgbuf = NUL; } else { - add_time(msgbuf, sizeof(msgbuf), uhp->uh_time); + undo_fmt_time(msgbuf, sizeof(msgbuf), uhp->uh_time); } { @@ -2641,6 +2642,29 @@ static void u_undo_end(bool did_undo, bool absolute, bool quiet) msgbuf); } +/// Put the timestamp of an undo header in "buf[buflen]" in a nice format. +void undo_fmt_time(char_u *buf, size_t buflen, time_t tt) +{ + struct tm curtime; + + if (time(NULL) - tt >= 100) { + os_localtime_r(&tt, &curtime); + if (time(NULL) - tt < (60L * 60L * 12L)) { + // within 12 hours + (void)strftime((char *)buf, buflen, "%H:%M:%S", &curtime); + } else { + // longer ago + (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", &curtime); + } + } else { + int64_t seconds = time(NULL) - tt; + vim_snprintf((char *)buf, buflen, + NGETTEXT("%" PRId64 " second ago", + "%" PRId64 " seconds ago", (uint32_t)seconds), + seconds); + } +} + /// u_sync: stop adding to the current entry list /// /// @param force if true, also sync when no_u_sync is set. @@ -2683,16 +2707,13 @@ void ex_undolist(exarg_T *eap) while (uhp != NULL) { if (uhp->uh_prev.ptr == NULL && uhp->uh_walk != nomark && uhp->uh_walk != mark) { - vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7d ", - uhp->uh_seq, changes); - add_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), - uhp->uh_time); + vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7d ", uhp->uh_seq, changes); + undo_fmt_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), uhp->uh_time); if (uhp->uh_save_nr > 0) { while (STRLEN(IObuff) < 33) { STRCAT(IObuff, " "); } - vim_snprintf_add((char *)IObuff, IOSIZE, - " %3ld", uhp->uh_save_nr); + vim_snprintf_add((char *)IObuff, IOSIZE, " %3ld", uhp->uh_save_nr); } GA_APPEND(char_u *, &ga, vim_strsave(IObuff)); } |