aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/autocmd.c1
-rw-r--r--src/nvim/buffer.c2
-rw-r--r--src/nvim/buffer_defs.h6
-rw-r--r--src/nvim/change.c4
-rw-r--r--src/nvim/change.h7
-rw-r--r--src/nvim/eval.c25
-rw-r--r--src/nvim/eval.h7
-rw-r--r--src/nvim/eval/typval.c1
-rw-r--r--src/nvim/event/rstream.c1
-rw-r--r--src/nvim/ex_cmds2.c1
-rw-r--r--src/nvim/ex_docmd.c1
-rw-r--r--src/nvim/fold.c1
-rw-r--r--src/nvim/main.c44
-rw-r--r--src/nvim/memline.c11
-rw-r--r--src/nvim/misc1.c204
-rw-r--r--src/nvim/misc1.h7
-rw-r--r--src/nvim/option.c2
-rw-r--r--src/nvim/os/input.c34
-rw-r--r--src/nvim/path.c11
-rw-r--r--src/nvim/regexp.c1
-rw-r--r--src/nvim/regexp_nfa.c1
-rw-r--r--src/nvim/screen.c13
-rw-r--r--src/nvim/search.c1
-rw-r--r--src/nvim/spellfile.c1
-rw-r--r--src/nvim/state.c32
-rw-r--r--src/nvim/syntax.c1
-rw-r--r--src/nvim/undo.c35
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));
}