aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/CMakeLists.txt4
-rw-r--r--src/nvim/api/vim.c18
-rw-r--r--src/nvim/api/window.c5
-rw-r--r--src/nvim/buffer.c5
-rw-r--r--src/nvim/buffer_defs.h14
-rw-r--r--src/nvim/eval.c24
-rw-r--r--src/nvim/event/process.c10
-rw-r--r--src/nvim/ex_docmd.c9
-rw-r--r--src/nvim/ex_getln.c2
-rw-r--r--src/nvim/highlight.c21
-rw-r--r--src/nvim/main.c2
-rw-r--r--src/nvim/memory.c2
-rw-r--r--src/nvim/option.c10
-rw-r--r--src/nvim/option_defs.h7
-rw-r--r--src/nvim/options.lua7
-rw-r--r--src/nvim/os/pty_process_unix.c10
-rw-r--r--src/nvim/os/time.c6
-rw-r--r--src/nvim/profile.c4
-rw-r--r--src/nvim/profile.h2
-rw-r--r--src/nvim/screen.c5
-rw-r--r--src/nvim/sign.c47
-rw-r--r--src/nvim/syntax.c4
-rw-r--r--src/nvim/testdir/Makefile33
-rw-r--r--src/nvim/testdir/test_assert.vim6
-rw-r--r--src/nvim/testdir/test_diffmode.vim3
-rw-r--r--src/nvim/testdir/test_options.vim2
-rw-r--r--src/nvim/testdir/test_suspend.vim27
-rw-r--r--src/nvim/ui.c20
-rw-r--r--src/nvim/ui_compositor.c74
-rw-r--r--src/nvim/window.c77
30 files changed, 313 insertions, 147 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 7807125b92..95ca1052af 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -164,8 +164,8 @@ if(NOT MSVC)
set_source_files_properties(
${CONV_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion")
# gperf generates ANSI-C with incorrect linkage, ignore it.
- check_c_compiler_flag(-Wno-static-in-inline HAS_WNO_STATIC_IN_INLINE_FLAG)
- if(HAS_WNO_STATIC_IN_INLINE_FLAG)
+ check_c_compiler_flag(-Wstatic-in-inline HAS_WSTATIC_IN_INLINE)
+ if(HAS_WSTATIC_IN_INLINE)
set_source_files_properties(
eval.c PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-static-in-inline -Wno-conversion")
else()
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 8e5650633a..dbe3b66fd5 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -1064,6 +1064,19 @@ fail:
/// - `external`: GUI should display the window as an external
/// top-level window. Currently accepts no other positioning
/// configuration together with this.
+/// - `style`: Configure the apparance of the window. Currently only takes
+/// one non-empty value:
+/// - "minimal" Nvim will display the window with many UI options
+/// disabled. This is useful when displaing a temporary
+/// float where the text should not be edited. Disables
+/// 'number', 'relativenumber', 'cursorline', 'cursorcolumn',
+/// 'spell' and 'list' options. 'signcolumn' is changed to
+/// `auto`. The end-of-buffer region is hidden by setting
+/// `eob` flag of 'fillchars' to a space char, and clearing
+/// the |EndOfBuffer| region in 'winhighlight'.
+///
+/// top-level window. Currently accepts no other positioning
+/// configuration together with this.
/// @param[out] err Error details, if any
///
/// @return Window handle, or 0 on error
@@ -1085,6 +1098,11 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dictionary config,
if (buffer > 0) {
nvim_win_set_buf(wp->handle, buffer, err);
}
+
+ if (fconfig.style == kWinStyleMinimal) {
+ win_set_minimal_style(wp);
+ didset_window_options(wp);
+ }
return wp->handle;
}
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index 9fd1818a5c..4922dd7efc 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -13,6 +13,7 @@
#include "nvim/vim.h"
#include "nvim/buffer.h"
#include "nvim/cursor.h"
+#include "nvim/option.h"
#include "nvim/window.h"
#include "nvim/screen.h"
#include "nvim/move.h"
@@ -475,6 +476,10 @@ void nvim_win_set_config(Window window, Dictionary config, Error *err)
win_config_float(win, fconfig);
win->w_pos_changed = true;
}
+ if (fconfig.style == kWinStyleMinimal) {
+ win_set_minimal_style(win);
+ didset_window_options(win);
+ }
}
/// Return window configuration.
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 5678f518f5..cd31adbaff 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -2543,6 +2543,11 @@ void get_winopts(buf_T *buf)
} else
copy_winopt(&curwin->w_allbuf_opt, &curwin->w_onebuf_opt);
+ if (curwin->w_float_config.style == kWinStyleMinimal) {
+ didset_window_options(curwin);
+ win_set_minimal_style(curwin);
+ }
+
// Set 'foldlevel' to 'foldlevelstart' if it's not negative.
if (p_fdls >= 0) {
curwin->w_p_fdl = p_fdls;
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index ad10f6baa2..a27672488e 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -972,7 +972,6 @@ struct matchitem {
};
typedef int FloatAnchor;
-typedef int FloatRelative;
enum {
kFloatAnchorEast = 1,
@@ -985,15 +984,20 @@ enum {
// SE -> kFloatAnchorSouth | kFloatAnchorEast
EXTERN const char *const float_anchor_str[] INIT(= { "NW", "NE", "SW", "SE" });
-enum {
+typedef enum {
kFloatRelativeEditor = 0,
kFloatRelativeWindow = 1,
kFloatRelativeCursor = 2,
-};
+} FloatRelative;
EXTERN const char *const float_relative_str[] INIT(= { "editor", "window",
"cursor" });
+typedef enum {
+ kWinStyleUnused = 0,
+ kWinStyleMinimal, /// Minimal UI: no number column, eob markers, etc
+} WinStyle;
+
typedef struct {
Window window;
int height, width;
@@ -1002,12 +1006,14 @@ typedef struct {
FloatRelative relative;
bool external;
bool focusable;
+ WinStyle style;
} FloatConfig;
#define FLOAT_CONFIG_INIT ((FloatConfig){ .height = 0, .width = 0, \
.row = 0, .col = 0, .anchor = 0, \
.relative = 0, .external = false, \
- .focusable = true })
+ .focusable = true, \
+ .style = kWinStyleUnused })
// Structure to store last cursor position and topline. Used by check_lnums()
// and reset_lnums().
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 6df2b69396..418725fa44 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -7097,10 +7097,14 @@ static void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *const cmd = tv_get_string_chk(&argvars[0]);
garray_T ga;
+ int save_trylevel = trylevel;
+ // trylevel must be zero for a ":throw" command to be considered failed
+ trylevel = 0;
called_emsg = false;
suppress_errthrow = true;
emsg_silent = true;
+
do_cmdline_cmd(cmd);
if (!called_emsg) {
prepare_assert_error(&ga);
@@ -7122,6 +7126,7 @@ static void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
+ trylevel = save_trylevel;
called_emsg = false;
suppress_errthrow = false;
emsg_silent = false;
@@ -15873,11 +15878,10 @@ static void f_sign_getplaced(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
if ((di = tv_dict_find(dict, "lnum", -1)) != NULL) {
// get signs placed at this line
- lnum = (linenr_T)tv_get_number_chk(&di->di_tv, &notanum);
- if (notanum) {
+ lnum = tv_get_lnum(&di->di_tv);
+ if (lnum <= 0) {
return;
}
- lnum = tv_get_lnum(&di->di_tv);
}
if ((di = tv_dict_find(dict, "id", -1)) != NULL) {
// get sign placed with this identifier
@@ -20705,11 +20709,11 @@ void ex_echohl(exarg_T *eap)
*/
void ex_execute(exarg_T *eap)
{
- char_u *arg = eap->arg;
+ char_u *arg = eap->arg;
typval_T rettv;
int ret = OK;
garray_T ga;
- int save_did_emsg = did_emsg;
+ int save_did_emsg;
ga_init(&ga, 1, 80);
@@ -22048,6 +22052,7 @@ static bool script_autoload(const char *const name, const size_t name_len,
}
/// Return the autoload script name for a function or variable name
+/// Caller must make sure that "name" contains AUTOLOAD_CHAR.
///
/// @param[in] name Variable/function name.
/// @param[in] name_len Name length.
@@ -22236,12 +22241,9 @@ static void func_clear_items(ufunc_T *fp)
ga_clear_strings(&(fp->uf_args));
ga_clear_strings(&(fp->uf_lines));
- xfree(fp->uf_tml_count);
- fp->uf_tml_count = NULL;
- xfree(fp->uf_tml_total);
- fp->uf_tml_total = NULL;
- xfree(fp->uf_tml_self);
- fp->uf_tml_self = NULL;
+ XFREE_CLEAR(fp->uf_tml_count);
+ XFREE_CLEAR(fp->uf_tml_total);
+ XFREE_CLEAR(fp->uf_tml_self);
}
/// Free all things that a function contains. Does not free the function
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index 7a8a39dbcf..990dee0c7f 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -26,6 +26,11 @@
// For PTY processes SIGTERM is sent first (in case SIGHUP was not enough).
#define KILL_TIMEOUT_MS 2000
+/// Externally defined with gcov.
+#ifdef USE_GCOV
+void __gcov_flush(void);
+#endif
+
static bool process_is_tearing_down = false;
/// @returns zero on success, or negative error code
@@ -50,6 +55,11 @@ int process_spawn(Process *proc, bool in, bool out, bool err)
proc->err.closed = true;
}
+#ifdef USE_GCOV
+ // Flush coverage data before forking, to avoid "Merge mismatch" errors.
+ __gcov_flush();
+#endif
+
int status;
switch (proc->type) {
case kProcessTypeUv:
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index a494463f89..1d27cf338e 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -6922,16 +6922,17 @@ static void ex_resize(exarg_T *eap)
n = atol((char *)eap->arg);
if (cmdmod.split & WSP_VERT) {
- if (*eap->arg == '-' || *eap->arg == '+')
+ if (*eap->arg == '-' || *eap->arg == '+') {
n += curwin->w_width;
- else if (n == 0 && eap->arg[0] == NUL) /* default is very wide */
- n = 9999;
+ } else if (n == 0 && eap->arg[0] == NUL) { // default is very wide
+ n = Columns;
+ }
win_setwidth_win(n, wp);
} else {
if (*eap->arg == '-' || *eap->arg == '+') {
n += curwin->w_height;
} else if (n == 0 && eap->arg[0] == NUL) { // default is very high
- n = 9999;
+ n = Rows-1;
}
win_setheight_win(n, wp);
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 1f258985a6..093067894f 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -2495,7 +2495,7 @@ static void realloc_cmdbuff(int len)
static char_u *arshape_buf = NULL;
# if defined(EXITFREE)
-void free_cmdline_buf(void)
+void free_arshape_buf(void)
{
xfree(arshape_buf);
}
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c
index 15c3d0eb7b..e5cbb4f944 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -141,10 +141,12 @@ int hl_get_ui_attr(int idx, int final_id, bool optional)
HlAttrs attrs = HLATTRS_INIT;
bool available = false;
- int syn_attr = syn_id2attr(final_id);
- if (syn_attr != 0) {
- attrs = syn_attr2entry(syn_attr);
- available = true;
+ if (final_id > 0) {
+ int syn_attr = syn_id2attr(final_id);
+ if (syn_attr != 0) {
+ attrs = syn_attr2entry(syn_attr);
+ available = true;
+ }
}
if (HLF_PNI <= idx && idx <= HLF_PST) {
@@ -176,15 +178,14 @@ void update_window_hl(win_T *wp, bool invalid)
// determine window specific background set in 'winhighlight'
bool float_win = wp->w_floating && !wp->w_float_config.external;
- if (wp != curwin && wp->w_hl_ids[HLF_INACTIVE] > 0) {
+ if (wp != curwin && wp->w_hl_ids[HLF_INACTIVE] != 0) {
wp->w_hl_attr_normal = hl_get_ui_attr(HLF_INACTIVE,
wp->w_hl_ids[HLF_INACTIVE],
!has_blend);
- } else if (float_win && wp->w_hl_ids[HLF_NFLOAT] > 0) {
+ } else if (float_win && wp->w_hl_ids[HLF_NFLOAT] != 0) {
wp->w_hl_attr_normal = hl_get_ui_attr(HLF_NFLOAT,
- // 'cursorline'
wp->w_hl_ids[HLF_NFLOAT], !has_blend);
- } else if (wp->w_hl_id_normal > 0) {
+ } else if (wp->w_hl_id_normal != 0) {
wp->w_hl_attr_normal = hl_get_ui_attr(-1, wp->w_hl_id_normal, !has_blend);
} else {
wp->w_hl_attr_normal = float_win ? HL_ATTR(HLF_NFLOAT) : 0;
@@ -199,14 +200,14 @@ void update_window_hl(win_T *wp, bool invalid)
}
}
- if (wp != curwin) {
+ if (wp != curwin && wp->w_hl_ids[HLF_INACTIVE] == 0) {
wp->w_hl_attr_normal = hl_combine_attr(HL_ATTR(HLF_INACTIVE),
wp->w_hl_attr_normal);
}
for (int hlf = 0; hlf < (int)HLF_COUNT; hlf++) {
int attr;
- if (wp->w_hl_ids[hlf] > 0) {
+ if (wp->w_hl_ids[hlf] != 0) {
attr = hl_get_ui_attr(hlf, wp->w_hl_ids[hlf], false);
} else {
attr = HL_ATTR(hlf);
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 306d2f7bf5..b3654a0690 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -54,6 +54,7 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/ui.h"
+#include "nvim/ui_compositor.h"
#include "nvim/version.h"
#include "nvim/window.h"
#include "nvim/shada.h"
@@ -220,6 +221,7 @@ void early_init(void)
set_lang_var(); // set v:lang and v:ctype
init_signs();
+ ui_comp_syn_init();
}
#ifdef MAKE_LIB
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index dced03f3d5..1384aa177b 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -648,7 +648,7 @@ void free_all_mem(void)
// Free all option values. Must come after closing windows.
free_all_options();
- free_cmdline_buf();
+ free_arshape_buf();
/* Clear registers. */
clear_registers();
diff --git a/src/nvim/option.c b/src/nvim/option.c
index e8e246c277..d6dbb14653 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -2191,6 +2191,7 @@ static void didset_options(void)
(void)opt_strings_flags(p_vop, p_ssop_values, &vop_flags, true);
(void)opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, true);
(void)opt_strings_flags(p_dy, p_dy_values, &dy_flags, true);
+ (void)opt_strings_flags(p_rdb, p_rdb_values, &rdb_flags, true);
(void)opt_strings_flags(p_tc, p_tc_values, &tc_flags, false);
(void)opt_strings_flags(p_ve, p_ve_values, &ve_flags, true);
(void)opt_strings_flags(p_wop, p_wop_values, &wop_flags, true);
@@ -2650,6 +2651,10 @@ did_set_string_option(
if (opt_strings_flags(p_vop, p_ssop_values, &vop_flags, true) != OK) {
errmsg = e_invarg;
}
+ } else if (varp == &p_rdb) { // 'redrawdebug'
+ if (opt_strings_flags(p_rdb, p_rdb_values, &rdb_flags, true) != OK) {
+ errmsg = e_invarg;
+ }
} else if (varp == &p_sbo) { // 'scrollopt'
if (check_opt_strings(p_sbo, p_scbopt_values, true) != OK) {
errmsg = e_invarg;
@@ -3762,7 +3767,8 @@ static bool parse_winhl_opt(win_T *wp)
size_t nlen = (size_t)(colon-p);
char *hi = colon+1;
char *commap = xstrchrnul(hi, ',');
- int hl_id = syn_check_group((char_u *)hi, (int)(commap-hi));
+ int len = (int)(commap-hi);
+ int hl_id = len ? syn_check_group((char_u *)hi, len) : -1;
if (strncmp("Normal", p, nlen) == 0) {
w_hl_id_normal = hl_id;
@@ -4274,7 +4280,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
} else if (pp == &curwin->w_p_nuw || pp == &curwin->w_allbuf_opt.wo_nuw) {
if (value < 1) {
errmsg = e_positive;
- } else if (value > 10) {
+ } else if (value > 20) {
errmsg = e_invarg;
}
} else if (pp == &curbuf->b_p_iminsert || pp == &p_iminsert) {
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 35fe3b5b00..a480de735d 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -511,6 +511,13 @@ EXTERN char_u *p_pm; // 'patchmode'
EXTERN char_u *p_path; // 'path'
EXTERN char_u *p_cdpath; // 'cdpath'
EXTERN long p_pyx; // 'pyxversion'
+EXTERN char_u *p_rdb; // 'redrawdebug'
+EXTERN unsigned rdb_flags;
+# ifdef IN_OPTION_C
+static char *(p_rdb_values[]) = { "compositor", NULL };
+# endif
+# define RDB_COMPOSITOR 0x001
+
EXTERN long p_rdt; // 'redrawtime'
EXTERN int p_remap; // 'remap'
EXTERN long p_re; // 'regexpengine'
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 27f72f6441..c48366e205 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -1848,6 +1848,13 @@ return {
defaults={if_true={vi=false}}
},
{
+ full_name='redrawdebug', abbreviation='rdb',
+ type='string', list='onecomma', scope={'global'},
+ vi_def=true,
+ varname='p_rdb',
+ defaults={if_true={vi=''}}
+ },
+ {
full_name='redrawtime', abbreviation='rdt',
type='number', scope={'global'},
vi_def=true,
diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c
index 97545a6cb1..5fdf0e6181 100644
--- a/src/nvim/os/pty_process_unix.c
+++ b/src/nvim/os/pty_process_unix.c
@@ -36,11 +36,6 @@
# include "os/pty_process_unix.c.generated.h"
#endif
-/// Externally defined with gcov.
-#ifdef USE_GCOV
-void __gcov_flush(void);
-#endif
-
/// termios saved at startup (for TUI) or initialized by pty_process_spawn().
static struct termios termios_default;
@@ -64,11 +59,6 @@ int pty_process_spawn(PtyProcess *ptyproc)
init_termios(&termios_default);
}
-#ifdef USE_GCOV
- // Flush coverage data before forking, to avoid "Merge mismatch" errors.
- __gcov_flush();
-#endif
-
int status = 0; // zero or negative error code (libuv convention)
Process *proc = (Process *)ptyproc;
assert(proc->err.closed);
diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c
index 18239c5566..1094fbc946 100644
--- a/src/nvim/os/time.c
+++ b/src/nvim/os/time.c
@@ -39,7 +39,7 @@ void time_init(void)
/// @see gettimeofday(2)
///
/// @return Current time in microseconds.
-uint64_t os_utime(void)
+int64_t os_utime(void)
FUNC_ATTR_WARN_UNUSED_RESULT
{
uv_timeval64_t tm;
@@ -47,8 +47,8 @@ uint64_t os_utime(void)
if (e != 0 || tm.tv_sec < 0 || tm.tv_usec < 0) {
return 0;
}
- uint64_t rv = (uint64_t)tm.tv_sec * 1000 * 1000; // s => μs
- STRICT_ADD(rv, tm.tv_usec, &rv, uint64_t);
+ int64_t rv = tm.tv_sec * 1000 * 1000; // s => μs
+ STRICT_ADD(rv, tm.tv_usec, &rv, int64_t);
return rv;
}
diff --git a/src/nvim/profile.c b/src/nvim/profile.c
index cc12e00396..ae3f1d9b5e 100644
--- a/src/nvim/profile.c
+++ b/src/nvim/profile.c
@@ -61,7 +61,7 @@ proftime_T profile_setlimit(int64_t msec) FUNC_ATTR_WARN_UNUSED_RESULT
}
assert(msec <= (INT64_MAX / 1000LL) - 1);
- proftime_T usec = (proftime_T)msec * 1000ULL;
+ proftime_T usec = msec * 1000;
return os_utime() + usec;
}
@@ -111,7 +111,7 @@ proftime_T profile_add(proftime_T tm1, proftime_T tm2) FUNC_ATTR_CONST
/// @return `tm1` - `tm2`
proftime_T profile_sub(proftime_T tm1, proftime_T tm2) FUNC_ATTR_CONST
{
- return tm1 > tm2 ? tm1 - tm2 : 0; // os_utime() may go backwards.
+ return tm1 - tm2;
}
/// Adds the `self` time from the total time and the `children` time.
diff --git a/src/nvim/profile.h b/src/nvim/profile.h
index 7b378577ce..2608514313 100644
--- a/src/nvim/profile.h
+++ b/src/nvim/profile.h
@@ -4,7 +4,7 @@
#include <stdint.h>
#include <time.h>
-typedef uint64_t proftime_T;
+typedef int64_t proftime_T;
#define TIME_MSG(s) do { \
if (time_fd != NULL) time_msg(s, NULL); \
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index acff44164f..a007aa9a47 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -1612,7 +1612,8 @@ static void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row,
}
}
- int attr = hl_combine_attr(wp->w_hl_attr_normal, win_hl_attr(wp, hl));
+ int attr = hl_combine_attr(wp->w_hl_attr_normal,
+ hl ? win_hl_attr(wp, hl) : 0);
if (wp->w_p_rl) {
grid_fill(&wp->w_grid, row, endrow, wp->w_wincol, W_ENDCOL(wp) - 1 - n,
@@ -2085,7 +2086,7 @@ win_line (
int lcs_eol_one = wp->w_p_lcs_chars.eol; // 'eol' until it's been used
int lcs_prec_todo = wp->w_p_lcs_chars.prec; // 'prec' until it's been used
- /* saved "extra" items for when draw_state becomes WL_LINE (again) */
+ // saved "extra" items for when draw_state becomes WL_LINE (again)
int saved_n_extra = 0;
char_u *saved_p_extra = NULL;
int saved_c_extra = 0;
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index 8c85fbdaa7..9c391428ca 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -83,11 +83,8 @@ static signgroup_T * sign_group_ref(const char_u *groupname)
hi = hash_lookup(&sg_table, (char *)groupname, STRLEN(groupname), hash);
if (HASHITEM_EMPTY(hi)) {
// new group
- group = (signgroup_T *)xmalloc(
- (unsigned)(sizeof(signgroup_T) + STRLEN(groupname)));
- if (group == NULL) {
- return NULL;
- }
+ group = xmalloc((unsigned)(sizeof(signgroup_T) + STRLEN(groupname)));
+
STRCPY(group->sg_name, groupname);
group->refcount = 1;
group->next_sign_id = 1;
@@ -188,10 +185,6 @@ static void insert_sign(
newsign->typenr = typenr;
if (group != NULL) {
newsign->group = sign_group_ref(group);
- if (newsign->group == NULL) {
- xfree(newsign);
- return;
- }
} else {
newsign->group = NULL;
}
@@ -1347,8 +1340,8 @@ static void sign_getinfo(sign_T *sp, dict_T *retdict)
/// Otherwise, return information about the specified sign.
void sign_getlist(const char_u *name, list_T *retlist)
{
- sign_T *sp = first_sign;
- dict_T *dict;
+ sign_T *sp = first_sign;
+ dict_T *dict;
if (name != NULL) {
sp = sign_find(name, NULL);
@@ -1358,9 +1351,7 @@ void sign_getlist(const char_u *name, list_T *retlist)
}
for (; sp != NULL && !got_int; sp = sp->sn_next) {
- if ((dict = tv_dict_alloc()) == NULL) {
- return;
- }
+ dict = tv_dict_alloc();
tv_list_append_dict(retlist, dict);
sign_getinfo(sp, dict);
@@ -1374,14 +1365,13 @@ void sign_getlist(const char_u *name, list_T *retlist)
list_T *get_buffer_signs(buf_T *buf)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
- signlist_T *sign;
- dict_T *d;
+ signlist_T *sign;
+ dict_T *d;
list_T *const l = tv_list_alloc(kListLenMayKnow);
FOR_ALL_SIGNS_IN_BUF(buf, sign) {
- if ((d = sign_get_info(sign)) != NULL) {
- tv_list_append_dict(l, d);
- }
+ d = sign_get_info(sign);
+ tv_list_append_dict(l, d);
}
return l;
}
@@ -1394,21 +1384,16 @@ static void sign_get_placed_in_buf(
const char_u *sign_group,
list_T *retlist)
{
- dict_T *d;
- list_T *l;
- signlist_T *sign;
- dict_T *sdict;
+ dict_T *d;
+ list_T *l;
+ signlist_T *sign;
- if ((d = tv_dict_alloc()) == NULL) {
- return;
- }
+ d = tv_dict_alloc();
tv_list_append_dict(retlist, d);
tv_dict_add_nr(d, S_LEN("bufnr"), (long)buf->b_fnum);
- if ((l = tv_list_alloc(kListLenMayKnow)) == NULL) {
- return;
- }
+ l = tv_list_alloc(kListLenMayKnow);
tv_dict_add_list(d, S_LEN("signs"), l);
FOR_ALL_SIGNS_IN_BUF(buf, sign) {
@@ -1419,9 +1404,7 @@ static void sign_get_placed_in_buf(
|| (sign_id == 0 && lnum == sign->lnum)
|| (lnum == 0 && sign_id == sign->id)
|| (lnum == sign->lnum && sign_id == sign->id)) {
- if ((sdict = sign_get_info(sign)) != NULL) {
- tv_list_append_dict(l, sdict);
- }
+ tv_list_append_dict(l, sign_get_info(sign));
}
}
}
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 354590b9ec..e39075739c 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -5970,6 +5970,10 @@ static const char *highlight_init_both[] = {
"default link Whitespace NonText",
"default link MsgSeparator StatusLine",
"default link NormalFloat Pmenu",
+ "RedrawDebugNormal cterm=reverse gui=reverse",
+ "RedrawDebugClear ctermbg=Yellow guibg=Yellow",
+ "RedrawDebugComposed ctermbg=Green guibg=Green",
+ "RedrawDebugRecompose ctermbg=Red guibg=Red",
NULL
};
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index fe9e0bc9c8..8b43d91e25 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -99,23 +99,24 @@ RM_ON_RUN := test.out X* viminfo
RM_ON_START := test.ok
RUN_VIM := $(TOOL) $(NVIM_PRG) -u unix.vim -U NONE -i viminfo --headless --noplugin -s dotest.in
+CLEAN_FILES := *.out \
+ *.failed \
+ *.res \
+ *.rej \
+ *.orig \
+ *.tlog \
+ test.log \
+ messages \
+ $(RM_ON_RUN) \
+ $(RM_ON_START) \
+ valgrind.* \
+ .*.swp \
+ .*.swo \
+ .gdbinit \
+ $(TMPDIR) \
+ del
clean:
- -rm -rf *.out \
- *.failed \
- *.res \
- *.rej \
- *.orig \
- *.tlog \
- test.log \
- messages \
- $(RM_ON_RUN) \
- $(RM_ON_START) \
- valgrind.* \
- .*.swp \
- .*.swo \
- .gdbinit \
- $(TMPDIR) \
- del
+ $(RM) -rf $(CLEAN_FILES)
test1.out: .gdbinit test1.in
@echo "[OLDTEST-PREP] Running test1"
diff --git a/src/nvim/testdir/test_assert.vim b/src/nvim/testdir/test_assert.vim
index fe87bd6ef5..a4c8ce7e43 100644
--- a/src/nvim/testdir/test_assert.vim
+++ b/src/nvim/testdir/test_assert.vim
@@ -1,5 +1,11 @@
" Test that the methods used for testing work.
+func Test_assert_fails_in_try_block()
+ try
+ call assert_equal(0, assert_fails('throw "error"'))
+ endtry
+endfunc
+
" Must be last.
func Test_zz_quit_detected()
" Verify that if a test function ends Vim the test script detects this.
diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim
index 00f4563f3d..1ba36ca8e9 100644
--- a/src/nvim/testdir/test_diffmode.vim
+++ b/src/nvim/testdir/test_diffmode.vim
@@ -752,6 +752,9 @@ func Test_diff_of_diff()
if !CanRunVimInTerminal()
return
endif
+ if !has("rightleft")
+ throw 'Skipped: rightleft not supported'
+ endif
call writefile([
\ 'call setline(1, ["aa","bb","cc","@@ -3,2 +5,7 @@","dd","ee","ff"])',
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index 28576709a3..a6ebd7b023 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -231,7 +231,7 @@ func Test_set_errors()
call assert_fails('set backupcopy=', 'E474:')
call assert_fails('set regexpengine=3', 'E474:')
call assert_fails('set history=10001', 'E474:')
- call assert_fails('set numberwidth=11', 'E474:')
+ call assert_fails('set numberwidth=21', 'E474:')
call assert_fails('set colorcolumn=-a')
call assert_fails('set colorcolumn=a')
call assert_fails('set colorcolumn=1,')
diff --git a/src/nvim/testdir/test_suspend.vim b/src/nvim/testdir/test_suspend.vim
index e569e49055..efda68de9b 100644
--- a/src/nvim/testdir/test_suspend.vim
+++ b/src/nvim/testdir/test_suspend.vim
@@ -2,6 +2,20 @@
source shared.vim
+func CheckSuspended(buf, fileExists)
+ call WaitForAssert({-> assert_match('[$#] $', term_getline(a:buf, '.'))})
+
+ if a:fileExists
+ call assert_equal(['foo'], readfile('Xfoo'))
+ else
+ " Without 'autowrite', buffer should not be written.
+ call assert_equal(0, filereadable('Xfoo'))
+ endif
+
+ call term_sendkeys(a:buf, "fg\<CR>\<C-L>")
+ call WaitForAssert({-> assert_equal(' 1 foo', term_getline(a:buf, '.'))})
+endfunc
+
func Test_suspend()
if !has('terminal') || !executable('/bin/sh')
return
@@ -26,13 +40,7 @@ func Test_suspend()
\ "\<C-Z>"]
" Suspend and wait for shell prompt.
call term_sendkeys(buf, suspend_cmd)
- call WaitForAssert({-> assert_match('[$#] $', term_getline(buf, '.'))})
-
- " Without 'autowrite', buffer should not be written.
- call assert_equal(0, filereadable('Xfoo'))
-
- call term_sendkeys(buf, "fg\<CR>")
- call WaitForAssert({-> assert_equal(' 1 foo', term_getline(buf, '.'))})
+ call CheckSuspended(buf, 0)
endfor
" Test that :suspend! with 'autowrite' writes content of buffers if modified.
@@ -40,10 +48,7 @@ func Test_suspend()
call assert_equal(0, filereadable('Xfoo'))
call term_sendkeys(buf, ":suspend\<CR>")
" Wait for shell prompt.
- call WaitForAssert({-> assert_match('[$#] $', term_getline(buf, '.'))})
- call assert_equal(['foo'], readfile('Xfoo'))
- call term_sendkeys(buf, "fg\<CR>")
- call WaitForAssert({-> assert_equal(' 1 foo', term_getline(buf, '.'))})
+ call CheckSuspended(buf, 1)
" Quit gracefully to dump coverage information.
call term_sendkeys(buf, ":qall!\<CR>")
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 7dbb8ec790..fc4a3a403d 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -341,15 +341,15 @@ void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol,
flags, (const schar_T *)grid->chars + off,
(const sattr_T *)grid->attrs + off);
- if (p_wd) { // 'writedelay': flush & delay each time.
- int old_row = cursor_row, old_col = cursor_col;
- handle_T old_grid = cursor_grid_handle;
+ // 'writedelay': flush & delay each time.
+ if (p_wd && !(rdb_flags & RDB_COMPOSITOR)) {
// If 'writedelay' is active, set the cursor to indicate what was drawn.
- ui_grid_cursor_goto(grid->handle, row, MIN(clearcol, (int)Columns-1));
- ui_flush();
+ ui_call_grid_cursor_goto(grid->handle, row,
+ MIN(clearcol, (int)grid->Columns-1));
+ ui_call_flush();
uint64_t wd = (uint64_t)labs(p_wd);
os_microdelay(wd * 1000u, true);
- ui_grid_cursor_goto(old_grid, old_row, old_col);
+ pending_cursor_update = true; // restore the cursor later
}
}
@@ -372,6 +372,14 @@ void ui_grid_cursor_goto(handle_T grid_handle, int new_row, int new_col)
pending_cursor_update = true;
}
+/// moving the cursor grid will implicitly move the cursor
+void ui_check_cursor_grid(handle_T grid_handle)
+{
+ if (cursor_grid_handle == grid_handle) {
+ pending_cursor_update = true;
+ }
+}
+
void ui_mode_info_set(void)
{
pending_mode_info_update = true;
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index d12a411019..858ffbe5bc 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -49,6 +49,8 @@ static bool valid_screen = true;
static bool msg_scroll_mode = false;
static int msg_first_invalid = 0;
+static int dbghl_normal, dbghl_clear, dbghl_composed, dbghl_recompose;
+
void ui_comp_init(void)
{
if (compositor != NULL) {
@@ -81,6 +83,13 @@ void ui_comp_init(void)
ui_attach_impl(compositor);
}
+void ui_comp_syn_init(void)
+{
+ dbghl_normal = syn_check_group((char_u *)S_LEN("RedrawDebugNormal"));
+ dbghl_clear = syn_check_group((char_u *)S_LEN("RedrawDebugClear"));
+ dbghl_composed = syn_check_group((char_u *)S_LEN("RedrawDebugComposed"));
+ dbghl_recompose = syn_check_group((char_u *)S_LEN("RedrawDebugRecompose"));
+}
void ui_comp_attach(UI *ui)
{
@@ -290,10 +299,14 @@ static void compose_line(Integer row, Integer startcol, Integer endcol,
{
// in case we start on the right half of a double-width char, we need to
// check the left half. But skip it in output if it wasn't doublewidth.
- int skip = 0;
+ int skipstart = 0, skipend = 0;
if (startcol > 0 && (flags & kLineFlagInvalid)) {
startcol--;
- skip = 1;
+ skipstart = 1;
+ }
+ if (endcol < default_grid.Columns && (flags & kLineFlagInvalid)) {
+ endcol++;
+ skipend = 1;
}
int col = (int)startcol;
@@ -345,20 +358,27 @@ static void compose_line(Integer row, Integer startcol, Integer endcol,
if (linebuf[col-startcol][0] == NUL) {
linebuf[col-startcol][0] = ' ';
linebuf[col-startcol][1] = NUL;
+ if (col == endcol-1) {
+ skipend = 0;
+ }
} else if (n > 1 && linebuf[col-startcol+1][0] == NUL) {
- skip = 0;
+ skipstart = 0;
}
if (grid->comp_col+grid->Columns > until
&& grid->chars[off+n][0] == NUL) {
linebuf[until-1-startcol][0] = ' ';
linebuf[until-1-startcol][1] = '\0';
if (col == startcol && n == 1) {
- skip = 0;
+ skipstart = 0;
}
}
col = until;
}
+ if (linebuf[endcol-startcol-1][0] == NUL) {
+ skipend = 0;
+ }
+
assert(endcol <= chk_width);
assert(row < chk_height);
@@ -368,14 +388,48 @@ static void compose_line(Integer row, Integer startcol, Integer endcol,
flags = flags & ~kLineFlagWrap;
}
- ui_composed_call_raw_line(1, row, startcol+skip, endcol, endcol, 0, flags,
- (const schar_T *)linebuf+skip,
- (const sattr_T *)attrbuf+skip);
+ ui_composed_call_raw_line(1, row, startcol+skipstart,
+ endcol-skipend, endcol-skipend, 0, flags,
+ (const schar_T *)linebuf+skipstart,
+ (const sattr_T *)attrbuf+skipstart);
}
+static void compose_debug(Integer startrow, Integer endrow, Integer startcol,
+ Integer endcol, int syn_id, bool delay)
+{
+ if (!(rdb_flags & RDB_COMPOSITOR)) {
+ return;
+ }
+
+ endrow = MIN(endrow, default_grid.Rows);
+ endcol = MIN(endcol, default_grid.Columns);
+ int attr = syn_id2attr(syn_id);
+
+ for (int row = (int)startrow; row < endrow; row++) {
+ ui_composed_call_raw_line(1, row, startcol, startcol, endcol, attr, false,
+ (const schar_T *)linebuf,
+ (const sattr_T *)attrbuf);
+ }
+
+
+ if (delay) {
+ debug_delay(endrow-startrow);
+ }
+}
+
+static void debug_delay(Integer lines)
+{
+ ui_call_flush();
+ uint64_t wd = (uint64_t)labs(p_wd);
+ uint64_t factor = (uint64_t)MAX(MIN(lines, 5), 1);
+ os_microdelay(factor * wd * 1000u, true);
+}
+
+
static void compose_area(Integer startrow, Integer endrow,
Integer startcol, Integer endcol)
{
+ compose_debug(startrow, endrow, startcol, endcol, dbghl_recompose, true);
endrow = MIN(endrow, default_grid.Rows);
endcol = MIN(endcol, default_grid.Columns);
if (endcol <= startcol) {
@@ -420,8 +474,11 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row,
if (flags & kLineFlagInvalid
|| kv_size(layers) > curgrid->comp_index+1
|| curgrid->blending) {
+ compose_debug(row, row+1, startcol, clearcol, dbghl_composed, true);
compose_line(row, startcol, clearcol, flags);
} else {
+ compose_debug(row, row+1, startcol, endcol, dbghl_normal, false);
+ compose_debug(row, row+1, endcol, clearcol, dbghl_clear, true);
ui_composed_call_raw_line(1, row, startcol, endcol, clearcol, clearattr,
flags, chunk, attrs);
}
@@ -481,6 +538,9 @@ static void ui_comp_grid_scroll(UI *ui, Integer grid, Integer top,
} else {
msg_first_invalid = MIN(msg_first_invalid, (int)top);
ui_composed_call_grid_scroll(1, top, bot, left, right, rows, cols);
+ if (rdb_flags & RDB_COMPOSITOR) {
+ debug_delay(2);
+ }
}
}
diff --git a/src/nvim/window.c b/src/nvim/window.c
index a3b1efeaaa..6ce095f976 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -375,7 +375,7 @@ newwindow:
/* set current window height */
case Ctrl__:
case '_':
- win_setheight(Prenum ? (int)Prenum : 9999);
+ win_setheight(Prenum ? (int)Prenum : Rows-1);
break;
/* increase current window width */
@@ -390,7 +390,7 @@ newwindow:
/* set current window width */
case '|':
- win_setwidth(Prenum != 0 ? (int)Prenum : 9999);
+ win_setwidth(Prenum != 0 ? (int)Prenum : Columns);
break;
/* jump to tag and split window if tag exists (in preview window) */
@@ -584,15 +584,43 @@ win_T *win_new_float(win_T *wp, FloatConfig fconfig, Error *err)
wp->w_status_height = 0;
wp->w_vsep_width = 0;
- // TODO(bfredl): use set_option_to() after merging #9110 ?
- wp->w_p_nu = false;
- wp->w_allbuf_opt.wo_nu = false;
win_config_float(wp, fconfig);
wp->w_pos_changed = true;
redraw_win_later(wp, VALID);
return wp;
}
+void win_set_minimal_style(win_T *wp)
+{
+ wp->w_p_nu = false;
+ wp->w_p_rnu = false;
+ wp->w_p_cul = false;
+ wp->w_p_cuc = false;
+ wp->w_p_spell = false;
+ wp->w_p_list = false;
+
+ // Hide EOB region: use " " fillchar and cleared highlighting
+ if (wp->w_p_fcs_chars.eob != ' ') {
+ char_u *old = wp->w_p_fcs;
+ wp->w_p_fcs = ((*old == NUL)
+ ? (char_u *)xstrdup("eob: ")
+ : concat_str(old, (char_u *)",eob: "));
+ xfree(old);
+ }
+ if (wp->w_hl_ids[HLF_EOB] != -1) {
+ char_u *old = wp->w_p_winhl;
+ wp->w_p_winhl = ((*old == NUL)
+ ? (char_u *)xstrdup("EndOfBuffer:")
+ : concat_str(old, (char_u *)",EndOfBuffer:"));
+ xfree(old);
+ }
+
+ if (wp->w_p_scl[0] != 'a') {
+ xfree(wp->w_p_scl);
+ wp->w_p_scl = (char_u *)xstrdup("auto");
+ }
+}
+
void win_config_float(win_T *wp, FloatConfig fconfig)
{
wp->w_width = MAX(fconfig.width, 1);
@@ -666,6 +694,7 @@ static void ui_ext_win_position(win_T *wp)
bool on_top = (curwin == wp) || !curwin->w_floating;
ui_comp_put_grid(&wp->w_grid, comp_row, comp_col, wp->w_height,
wp->w_width, valid, on_top);
+ ui_check_cursor_grid(wp->w_grid.handle);
if (!valid) {
wp->w_grid.valid = false;
redraw_win_later(wp, NOT_VALID);
@@ -821,6 +850,20 @@ bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf,
"'focusable' key must be Boolean");
return false;
}
+ } else if (!strcmp(key, "style")) {
+ if (val.type != kObjectTypeString) {
+ api_set_error(err, kErrorTypeValidation,
+ "'style' key must be String");
+ return false;
+ }
+ if (val.data.string.data[0] == NUL) {
+ fconfig->style = kWinStyleUnused;
+ } else if (striequal(val.data.string.data, "minimal")) {
+ fconfig->style = kWinStyleMinimal;
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "Invalid value of 'style' key");
+ }
} else {
api_set_error(err, kErrorTypeValidation,
"Invalid key '%s'", key);
@@ -4823,13 +4866,9 @@ void win_setheight_win(int height, win_T *win)
}
if (win->w_floating) {
- if (win->w_float_config.external) {
- win->w_float_config.height = height;
- win_config_float(win, win->w_float_config);
- } else {
- beep_flush();
- return;
- }
+ win->w_float_config.height = height;
+ win_config_float(win, win->w_float_config);
+ redraw_win_later(win, NOT_VALID);
} else {
frame_setheight(win->w_frame, height + win->w_status_height);
@@ -4844,9 +4883,9 @@ void win_setheight_win(int height, win_T *win)
cmdline_row = row;
msg_row = row;
msg_col = 0;
+ redraw_all_later(NOT_VALID);
}
- redraw_all_later(NOT_VALID);
}
@@ -5029,21 +5068,17 @@ void win_setwidth_win(int width, win_T *wp)
width = 1;
}
if (wp->w_floating) {
- if (wp->w_float_config.external) {
- wp->w_float_config.width = width;
- win_config_float(wp, wp->w_float_config);
- } else {
- beep_flush();
- return;
- }
+ wp->w_float_config.width = width;
+ win_config_float(wp, wp->w_float_config);
+ redraw_win_later(wp, NOT_VALID);
} else {
frame_setwidth(wp->w_frame, width + wp->w_vsep_width);
// recompute the window positions
(void)win_comp_pos();
+ redraw_all_later(NOT_VALID);
}
- redraw_all_later(NOT_VALID);
}
/*