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/buffer.c4
-rw-r--r--src/nvim/buffer_defs.h6
-rw-r--r--src/nvim/event/process.c22
-rw-r--r--src/nvim/event/process.h3
-rw-r--r--src/nvim/globals.h3
-rw-r--r--src/nvim/msgpack_rpc/server.h2
-rw-r--r--src/nvim/option.c54
-rw-r--r--src/nvim/option_defs.h1
-rw-r--r--src/nvim/options.lua8
-rw-r--r--src/nvim/os/shell.h2
-rw-r--r--src/nvim/screen.c91
-rw-r--r--src/nvim/terminal.c10
-rw-r--r--src/nvim/window.c8
14 files changed, 177 insertions, 41 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 23ec74fe5b..8deeff4654 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -508,10 +508,6 @@ function(get_test_target prefix sfile relative_path_var target_var)
endfunction()
set(NO_SINGLE_CHECK_HEADERS
- misc2.h
- msgpack_rpc/server.h
- os/shell.h
- os_unix.h
os/win_defs.h
regexp_defs.h
syntax_defs.h
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 7def8c1684..4ed75d8a2d 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -449,7 +449,7 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last)
if (buf->terminal) {
terminal_close(buf->terminal, NULL);
- }
+ }
/* Always remove the buffer when there is no file name. */
if (buf->b_ffname == NULL)
@@ -2316,7 +2316,7 @@ void get_winopts(buf_T *buf)
/* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */
if (p_fdls >= 0)
curwin->w_p_fdl = p_fdls;
- check_colorcolumn(curwin);
+ didset_window_options(curwin);
}
/*
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 20a2b931bd..88fa9726a4 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -233,6 +233,8 @@ typedef struct {
# define w_p_crb_save w_onebuf_opt.wo_crb_save
char_u *wo_scl;
# define w_p_scl w_onebuf_opt.wo_scl // 'signcolumn'
+ char_u *wo_winhl;
+# define w_p_winhl w_onebuf_opt.wo_winhl // 'winhighlight'
int wo_scriptID[WV_COUNT]; /* SIDs for window-local options */
# define w_p_scriptID w_onebuf_opt.wo_scriptID
@@ -930,6 +932,10 @@ struct window_S {
synblock_T *w_s; /* for :ownsyntax */
+ int w_hl_id; ///< 'winhighlight' id
+ int w_hl_id_inactive; ///< 'winhighlight' id for inactive window
+ int w_hl_attr; ///< 'winhighlight' final attrs
+
win_T *w_prev; /* link to previous window */
win_T *w_next; /* link to next window */
bool w_closing; /* window is being closed, don't let
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index 6aab7d903c..ffda10a494 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -20,9 +20,9 @@
# include "event/process.c.generated.h"
#endif
-// Time for a process to exit cleanly before we send KILL.
-#define KILL_TIMEOUT_MS 2000
-#define KILL_TIMEOUT_NS (KILL_TIMEOUT_MS * 1000000)
+// Time (ns) for a process to exit cleanly before we send TERM/KILL.
+#define TERM_TIMEOUT 1000000000
+#define KILL_TIMEOUT (TERM_TIMEOUT * 2)
#define CLOSE_PROC_STREAM(proc, stream) \
do { \
@@ -121,6 +121,8 @@ void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL
// Close handles to process without killing it.
CREATE_EVENT(loop->events, process_close_handles, 1, proc);
} else {
+ uv_kill(proc->pid, SIGTERM);
+ proc->term_sent = true;
process_stop(proc);
}
}
@@ -242,16 +244,12 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL
abort();
}
- ILOG("Sending SIGTERM to pid %d", proc->pid);
- uv_kill(proc->pid, SIGTERM);
-
Loop *loop = proc->loop;
if (!loop->children_stop_requests++) {
// When there's at least one stop request pending, start a timer that
- // will periodically check if a signal should be send to the job.
+ // will periodically check if a signal should be send to a to the job
DLOG("Starting job kill timer");
- uv_timer_start(&loop->children_kill_timer, children_kill_cb,
- KILL_TIMEOUT_MS, 100);
+ uv_timer_start(&loop->children_kill_timer, children_kill_cb, 100, 100);
}
}
@@ -269,7 +267,11 @@ static void children_kill_cb(uv_timer_t *handle)
}
uint64_t elapsed = now - proc->stopped_time;
- if (elapsed >= KILL_TIMEOUT_NS) {
+ if (!proc->term_sent && elapsed >= TERM_TIMEOUT) {
+ ILOG("Sending SIGTERM to pid %d", proc->pid);
+ uv_kill(proc->pid, SIGTERM);
+ proc->term_sent = true;
+ } else if (elapsed >= KILL_TIMEOUT) {
ILOG("Sending SIGKILL to pid %d", proc->pid);
uv_kill(proc->pid, SIGKILL);
}
diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h
index 5c00e8e7ec..26d70a5e6d 100644
--- a/src/nvim/event/process.h
+++ b/src/nvim/event/process.h
@@ -26,7 +26,7 @@ struct process {
Stream *in, *out, *err;
process_exit_cb cb;
internal_process_cb internal_exit_cb, internal_close_cb;
- bool closed, detach;
+ bool closed, term_sent, detach;
MultiQueue *events;
};
@@ -48,6 +48,7 @@ static inline Process process_init(Loop *loop, ProcessType type, void *data)
.err = NULL,
.cb = NULL,
.closed = false,
+ .term_sent = false,
.internal_close_cb = NULL,
.internal_exit_cb = NULL,
.detach = false
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index df9f418951..b820965680 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -465,6 +465,7 @@ typedef enum {
, HLF_MC // 'colorcolumn'
, HLF_QFL // selected quickfix line
, HLF_0 // Whitespace
+ , HLF_INACTIVE // NormalNC: Normal text in non-current windows
, HLF_COUNT // MUST be the last one
} hlf_T;
@@ -473,7 +474,7 @@ typedef enum {
#define HL_FLAGS { '8', '~', 'z', 'Z', '@', 'd', 'e', 'i', 'l', 'm', 'M', 'n', \
'N', 'r', 's', 'S', 'c', 't', 'v', 'V', 'w', 'W', 'f', 'F', \
'A', 'C', 'D', 'T', '-', '>', 'B', 'P', 'R', 'L', '+', '=', \
- 'x', 'X', '*', '#', '_', '!', '.', 'o', 'q', '0' }
+ 'x', 'X', '*', '#', '_', '!', '.', 'o', 'q', '0', 'I' }
EXTERN int highlight_attr[HLF_COUNT]; /* Highl. attr for each context. */
EXTERN int highlight_user[9]; /* User[1-9] attributes */
diff --git a/src/nvim/msgpack_rpc/server.h b/src/nvim/msgpack_rpc/server.h
index f1a6703938..5446e40e0b 100644
--- a/src/nvim/msgpack_rpc/server.h
+++ b/src/nvim/msgpack_rpc/server.h
@@ -1,6 +1,8 @@
#ifndef NVIM_MSGPACK_RPC_SERVER_H
#define NVIM_MSGPACK_RPC_SERVER_H
+#include <stdio.h>
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "msgpack_rpc/server.h.generated.h"
#endif
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 3658f17883..ad09b936e0 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -8,6 +8,9 @@
// - Add a BV_XX or WV_XX entry to option_defs.h
// - Add a variable to the window or buffer struct in buffer_defs.h.
// - For a window option, add some code to copy_winopt().
+// - For a window string option, add code to check_winopt()
+// and clear_winopt(). If setting the option needs parsing,
+// add some code to didset_window_options().
// - For a buffer option, add some code to buf_copy_options().
// - For a buffer string option, add code to check_buf_options().
// - If it's a numeric option, add any necessary bounds checks to do_set().
@@ -249,7 +252,7 @@ typedef struct vimoption {
"B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel," \
"x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill," \
"!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine," \
- "0:Whitespace"
+ "0:Whitespace,I:NormalNC"
/*
* options[] is initialized here.
@@ -3171,6 +3174,10 @@ did_set_string_option (
if (!valid_filetype(*varp)) {
errmsg = e_invarg;
}
+ } else if (varp == &curwin->w_p_winhl) {
+ if (!parse_winhl_opt(curwin)) {
+ errmsg = e_invarg;
+ }
} else {
// Options that are a list of flags.
p = NULL;
@@ -3579,6 +3586,38 @@ static char_u *compile_cap_prog(synblock_T *synblock)
return NULL;
}
+/// Handle setting `winhighlight' in window "wp"
+static bool parse_winhl_opt(win_T *wp)
+{
+ int w_hl_id = 0, w_hl_id_inactive = 0;
+
+ const char *p = (const char *)wp->w_p_winhl;
+ while (*p) {
+ char *colon = strchr(p, ':');
+ if (!colon) {
+ return false;
+ }
+ 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));
+
+ if (strncmp("Normal", p, nlen) == 0) {
+ w_hl_id = hl_id;
+ } else if (strncmp("NormalNC", p, nlen) == 0) {
+ w_hl_id_inactive = hl_id;
+ } else {
+ return false;
+ }
+
+ p = *commap ? commap+1 : "";
+ }
+
+ wp->w_hl_id = w_hl_id;
+ wp->w_hl_id_inactive = w_hl_id_inactive;
+ return true;
+}
+
/*
* Set the scriptID for an option, taking care of setting the buffer- or
* window-local value.
@@ -5488,6 +5527,7 @@ static char_u *get_varp(vimoption_T *p)
case PV_WM: return (char_u *)&(curbuf->b_p_wm);
case PV_KMAP: return (char_u *)&(curbuf->b_p_keymap);
case PV_SCL: return (char_u *)&(curwin->w_p_scl);
+ case PV_WINHL: return (char_u *)&(curwin->w_p_winhl);
default: EMSG(_("E356: get_varp ERROR"));
}
/* always return a valid pointer to avoid a crash! */
@@ -5514,7 +5554,6 @@ void win_copy_options(win_T *wp_from, win_T *wp_to)
copy_winopt(&wp_from->w_allbuf_opt, &wp_to->w_allbuf_opt);
/* Is this right? */
wp_to->w_farsi = wp_from->w_farsi;
- briopt_check(wp_to);
}
/*
@@ -5566,6 +5605,7 @@ void copy_winopt(winopt_T *from, winopt_T *to)
to->wo_fdt = vim_strsave(from->wo_fdt);
to->wo_fmr = vim_strsave(from->wo_fmr);
to->wo_scl = vim_strsave(from->wo_scl);
+ to->wo_winhl = vim_strsave(from->wo_winhl);
check_winopt(to); // don't want NULL pointers
}
@@ -5595,6 +5635,7 @@ static void check_winopt(winopt_T *wop)
check_string_option(&wop->wo_cc);
check_string_option(&wop->wo_cocu);
check_string_option(&wop->wo_briopt);
+ check_string_option(&wop->wo_winhl);
}
/*
@@ -5614,8 +5655,17 @@ void clear_winopt(winopt_T *wop)
clear_string_option(&wop->wo_cc);
clear_string_option(&wop->wo_cocu);
clear_string_option(&wop->wo_briopt);
+ clear_string_option(&wop->wo_winhl);
}
+void didset_window_options(win_T *wp)
+{
+ check_colorcolumn(wp);
+ briopt_check(wp);
+ parse_winhl_opt(wp);
+}
+
+
/*
* Copy global option values to local options for one buffer.
* Used when creating a new buffer and sometimes when entering a buffer.
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 4ee0f4f225..e68dba734e 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -807,6 +807,7 @@ enum {
, WV_WFW
, WV_WRAP
, WV_SCL
+ , WV_WINHL
, WV_COUNT // must be the last one
};
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index ba7bf5bafb..6ad0501f0a 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2702,6 +2702,14 @@ return {
defaults={if_true={vi="menu"}}
},
{
+ full_name='winhighlight', abbreviation='winhl',
+ type='string', scope={'window'},
+ vi_def=true,
+ alloced=true,
+ redraw={'current_window'},
+ defaults={if_true={vi=""}}
+ },
+ {
full_name='window', abbreviation='wi',
type='number', scope={'global'},
vi_def=true,
diff --git a/src/nvim/os/shell.h b/src/nvim/os/shell.h
index 58960db157..48503f2601 100644
--- a/src/nvim/os/shell.h
+++ b/src/nvim/os/shell.h
@@ -1,6 +1,8 @@
#ifndef NVIM_OS_SHELL_H
#define NVIM_OS_SHELL_H
+#include <stdio.h>
+
#include "nvim/types.h"
// Flags for os_call_shell() second argument
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index f2709c48fd..238b3f07c8 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -1584,6 +1584,11 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
# define FDC_OFF n
int fdc = compute_foldcolumn(wp, 0);
+ int attr = hl_attr(hl);
+ if (wp->w_hl_attr != 0) {
+ attr = hl_combine_attr(wp->w_hl_attr, attr);
+ }
+
if (wp->w_p_rl) {
// No check for cmdline window: should never be right-left.
n = fdc;
@@ -1612,10 +1617,10 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
wp->w_wincol, W_ENDCOL(wp) - 1 - FDC_OFF,
- c2, c2, hl_attr(hl));
+ c2, c2, attr);
screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
W_ENDCOL(wp) - 1 - FDC_OFF, W_ENDCOL(wp) - FDC_OFF,
- c1, c2, hl_attr(hl));
+ c1, c2, attr);
} else {
if (cmdwin_type != 0 && wp == curwin) {
/* draw the cmdline character in the leftmost column */
@@ -1653,7 +1658,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
wp->w_wincol + FDC_OFF, W_ENDCOL(wp),
- c1, c2, hl_attr(hl));
+ c1, c2, attr);
}
set_empty_rows(wp, row);
}
@@ -2418,6 +2423,10 @@ win_line (
line_attr = hl_attr(HLF_QFL);
}
+ if (wp->w_hl_attr != 0) {
+ line_attr = hl_combine_attr(wp->w_hl_attr, line_attr);
+ }
+
if (line_attr != 0) {
area_highlighting = true;
}
@@ -2849,6 +2858,10 @@ win_line (
} else
char_attr = 0;
}
+
+ if (wp->w_hl_attr != 0) {
+ char_attr = hl_combine_attr(wp->w_hl_attr, char_attr);
+ }
}
/* When still displaying '$' of change command, stop at cursor */
@@ -3083,10 +3096,14 @@ win_line (
mb_l = 1;
mb_utf8 = FALSE;
multi_attr = hl_attr(HLF_AT);
- /* put the pointer back to output the double-width
- * character at the start of the next line. */
- ++n_extra;
- --p_extra;
+ if (wp->w_hl_attr != 0) {
+ multi_attr = hl_combine_attr(wp->w_hl_attr, multi_attr);
+ }
+
+ // put the pointer back to output the double-width
+ // character at the start of the next line.
+ n_extra++;
+ p_extra--;
} else {
n_extra -= mb_l - 1;
p_extra += mb_l - 1;
@@ -3221,11 +3238,15 @@ win_line (
mb_utf8 = FALSE;
mb_l = 1;
multi_attr = hl_attr(HLF_AT);
- /* Put pointer back so that the character will be
- * displayed at the start of the next line. */
- --ptr;
- } else if (*ptr != NUL)
+ if (wp->w_hl_attr != 0) {
+ multi_attr = hl_combine_attr(wp->w_hl_attr, multi_attr);
+ }
+ // Put pointer back so that the character will be
+ // displayed at the start of the next line.
+ ptr--;
+ } else if (*ptr != NUL) {
ptr += mb_l - 1;
+ }
/* If a double-width char doesn't fit at the left side display
* a '<' in the first column. Don't do this for unprintable
@@ -3752,7 +3773,10 @@ win_line (
mb_utf8 = false; // don't draw as UTF-8
}
saved_attr3 = char_attr; // save current attr
- char_attr = hl_attr(HLF_AT); // later copied to char_attr
+ char_attr = hl_attr(HLF_AT); // overwriting char_attr
+ if (wp->w_hl_attr != 0) {
+ char_attr = hl_combine_attr(wp->w_hl_attr, char_attr);
+ }
n_attr3 = 1;
}
@@ -3836,6 +3860,10 @@ win_line (
}
}
}
+
+ if (wp->w_hl_attr != 0) {
+ char_attr = hl_combine_attr(wp->w_hl_attr, char_attr);
+ }
ScreenAttrs[off] = char_attr;
if (wp->w_p_rl) {
--col;
@@ -3897,6 +3925,14 @@ win_line (
if (rightmost_vcol < color_cols[i])
rightmost_vcol = color_cols[i];
+ int cuc_attr = hl_attr(HLF_CUC);
+ int mc_attr = hl_attr(HLF_MC);
+ if (wp->w_hl_attr != 0) {
+ cuc_attr = hl_combine_attr(wp->w_hl_attr, cuc_attr);
+ mc_attr = hl_combine_attr(wp->w_hl_attr, mc_attr);
+ }
+
+
while (col < wp->w_width) {
ScreenLines[off] = ' ';
if (enc_utf8)
@@ -3906,12 +3942,13 @@ win_line (
draw_color_col = advance_color_col(VCOL_HLC,
&color_cols);
- if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol)
- ScreenAttrs[off++] = hl_attr(HLF_CUC);
- else if (draw_color_col && VCOL_HLC == *color_cols)
- ScreenAttrs[off++] = hl_attr(HLF_MC);
- else
- ScreenAttrs[off++] = 0;
+ if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) {
+ ScreenAttrs[off++] = cuc_attr;
+ } else if (draw_color_col && VCOL_HLC == *color_cols) {
+ ScreenAttrs[off++] = mc_attr;
+ } else {
+ ScreenAttrs[off++] = wp->w_hl_attr;
+ }
if (VCOL_HLC >= rightmost_vcol)
break;
@@ -3920,6 +3957,7 @@ win_line (
}
}
+ // TODO(bfredl): integrate with the common beyond-the-end-loop
if (wp->w_buffer->terminal) {
// terminal buffers may need to highlight beyond the end of the
// logical line
@@ -3961,6 +3999,9 @@ win_line (
|| (n_extra && (c_extra != NUL || *p_extra != NUL)))) {
c = lcs_ext;
char_attr = hl_attr(HLF_AT);
+ if (wp->w_hl_attr != 0) {
+ char_attr = hl_combine_attr(wp->w_hl_attr, char_attr);
+ }
mb_c = c;
if (enc_utf8 && (*mb_char2len)(c) > 1) {
mb_utf8 = TRUE;
@@ -5510,7 +5551,19 @@ static void init_search_hl(win_T *wp)
search_hl.buf = wp->w_buffer;
search_hl.lnum = 0;
search_hl.first_lnum = 0;
- /* time limit is set at the toplevel, for all windows */
+ // time limit is set at the toplevel, for all windows
+
+ // determine window specific background set in 'winhighlight'
+ if (wp != curwin && wp->w_hl_id_inactive > 0) {
+ wp->w_hl_attr = syn_id2attr(wp->w_hl_id_inactive);
+ } else if (wp->w_hl_id > 0) {
+ wp->w_hl_attr = syn_id2attr(wp->w_hl_id);
+ } else {
+ wp->w_hl_attr = 0;
+ }
+ if (wp != curwin) {
+ wp->w_hl_attr = hl_combine_attr(hl_attr(HLF_INACTIVE), wp->w_hl_attr);
+ }
}
/*
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index c44fe15be5..cc1de583d3 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -302,8 +302,16 @@ void terminal_close(Terminal *term, char *msg)
}
term->forward_mouse = false;
- term->closed = true;
+
+ // flush any pending changes to the buffer
+ if (!exiting) {
+ block_autocmds();
+ refresh_terminal(term);
+ unblock_autocmds();
+ }
+
buf_T *buf = handle_get_buffer(term->buf_handle);
+ term->closed = true;
if (!msg || exiting) {
// If no msg was given, this was called by close_buffer(buffer.c). Or if
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 69c0a838ea..b71b48a6b7 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -1043,7 +1043,7 @@ static void win_init(win_T *newp, win_T *oldp, int flags)
win_init_some(newp, oldp);
- check_colorcolumn(newp);
+ didset_window_options(newp);
}
/*
@@ -3722,6 +3722,12 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid,
if (restart_edit)
redraw_later(VALID); /* causes status line redraw */
+ if (hl_attr(HLF_INACTIVE)
+ || (prevwin && prevwin->w_hl_id_inactive)
+ || curwin->w_hl_id_inactive) {
+ redraw_all_later(NOT_VALID);
+ }
+
/* set window height to desired minimal value */
if (curwin->w_height < p_wh && !curwin->w_p_wfh)
win_setheight((int)p_wh);