aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/vim.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/api/vim.c')
-rw-r--r--src/nvim/api/vim.c128
1 files changed, 93 insertions, 35 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 9812313b7b..b62521290d 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -25,6 +25,7 @@
#include "nvim/buffer.h"
#include "nvim/channel.h"
#include "nvim/context.h"
+#include "nvim/cursor.h"
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
@@ -59,6 +60,7 @@
#include "nvim/popupmenu.h"
#include "nvim/pos.h"
#include "nvim/runtime.h"
+#include "nvim/sign.h"
#include "nvim/state.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
@@ -737,7 +739,7 @@ error:
void nvim_out_write(String str)
FUNC_API_SINCE(1)
{
- write_msg(str, false);
+ write_msg(str, false, false);
}
/// Writes a message to the Vim error buffer. Does not append "\n", the
@@ -747,7 +749,7 @@ void nvim_out_write(String str)
void nvim_err_write(String str)
FUNC_API_SINCE(1)
{
- write_msg(str, true);
+ write_msg(str, true, false);
}
/// Writes a message to the Vim error buffer. Appends "\n", so the buffer is
@@ -758,8 +760,7 @@ void nvim_err_write(String str)
void nvim_err_writeln(String str)
FUNC_API_SINCE(1)
{
- nvim_err_write(str);
- nvim_err_write((String) { .data = "\n", .size = 1 });
+ write_msg(str, true, true);
}
/// Gets the current list of buffer handles
@@ -1672,23 +1673,24 @@ theend:
///
/// @param message Message to write
/// @param to_err true: message is an error (uses `emsg` instead of `msg`)
-static void write_msg(String message, bool to_err)
+/// @param writeln Append a trailing newline
+static void write_msg(String message, bool to_err, bool writeln)
{
static StringBuilder out_line_buf = KV_INITIAL_VALUE;
static StringBuilder err_line_buf = KV_INITIAL_VALUE;
-#define PUSH_CHAR(i, line_buf, msg) \
+#define PUSH_CHAR(c, line_buf, msg) \
if (kv_max(line_buf) == 0) { \
kv_resize(line_buf, LINE_BUFFER_MIN_SIZE); \
} \
- if (message.data[i] == NL) { \
+ if (c == NL) { \
kv_push(line_buf, NUL); \
msg(line_buf.items); \
kv_drop(line_buf, kv_size(line_buf)); \
kv_resize(line_buf, LINE_BUFFER_MIN_SIZE); \
- continue; \
- } \
- kv_push(line_buf, message.data[i]);
+ } else { \
+ kv_push(line_buf, c); \
+ }
no_wait_return++;
for (uint32_t i = 0; i < message.size; i++) {
@@ -1696,9 +1698,16 @@ static void write_msg(String message, bool to_err)
break;
}
if (to_err) {
- PUSH_CHAR(i, err_line_buf, emsg);
+ PUSH_CHAR(message.data[i], err_line_buf, emsg);
} else {
- PUSH_CHAR(i, out_line_buf, msg);
+ PUSH_CHAR(message.data[i], out_line_buf, msg);
+ }
+ }
+ if (writeln) {
+ if (to_err) {
+ PUSH_CHAR(NL, err_line_buf, emsg);
+ } else {
+ PUSH_CHAR(NL, out_line_buf, msg);
}
}
no_wait_return--;
@@ -2047,6 +2056,7 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err)
/// - use_winbar: (boolean) Evaluate winbar instead of statusline.
/// - use_tabline: (boolean) Evaluate tabline instead of statusline. When true, {winid}
/// is ignored. Mutually exclusive with {use_winbar}.
+/// - use_statuscol_lnum: (number) Evaluate statuscolumn for this line number instead of statusline.
///
/// @param[out] err Error details, if any.
/// @return Dictionary containing statusline information, with these keys:
@@ -2064,6 +2074,8 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
int maxwidth;
int fillchar = 0;
+ int use_bools = 0;
+ int statuscol_lnum = 0;
Window window = 0;
bool use_winbar = false;
bool use_tabline = false;
@@ -2104,36 +2116,48 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
}
if (HAS_KEY(opts->use_winbar)) {
use_winbar = api_object_to_bool(opts->use_winbar, "use_winbar", false, err);
-
if (ERROR_SET(err)) {
return result;
}
+ use_bools++;
}
if (HAS_KEY(opts->use_tabline)) {
use_tabline = api_object_to_bool(opts->use_tabline, "use_tabline", false, err);
-
if (ERROR_SET(err)) {
return result;
}
+ use_bools++;
}
- VALIDATE(!(use_winbar && use_tabline), "%s", "Cannot use both 'use_winbar' and 'use_tabline'", {
+
+ win_T *wp = use_tabline ? curwin : find_window_by_handle(window, err);
+ if (wp == NULL) {
+ api_set_error(err, kErrorTypeException, "unknown winid %d", window);
+ return result;
+ }
+
+ if (HAS_KEY(opts->use_statuscol_lnum)) {
+ VALIDATE_T("use_statuscol_lnum", kObjectTypeInteger, opts->use_statuscol_lnum.type, {
+ return result;
+ });
+ statuscol_lnum = (int)opts->use_statuscol_lnum.data.integer;
+ VALIDATE_RANGE(statuscol_lnum > 0 && statuscol_lnum <= wp->w_buffer->b_ml.ml_line_count,
+ "use_statuscol_lnum", {
+ return result;
+ });
+ use_bools++;
+ }
+ VALIDATE(use_bools <= 1, "%s",
+ "Can only use one of 'use_winbar', 'use_tabline' and 'use_statuscol_lnum'", {
return result;
});
- win_T *wp, *ewp;
+ int stc_hl_id = 0;
+ statuscol_T statuscol = { 0 };
+ SignTextAttrs sattrs[SIGN_SHOW_MAX] = { 0 };
if (use_tabline) {
- wp = NULL;
- ewp = curwin;
fillchar = ' ';
} else {
- wp = find_window_by_handle(window, err);
- if (wp == NULL) {
- api_set_error(err, kErrorTypeException, "unknown winid %d", window);
- return result;
- }
- ewp = wp;
-
if (fillchar == 0) {
if (use_winbar) {
fillchar = wp->w_p_fcs_chars.wbr;
@@ -2142,6 +2166,40 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
fillchar = fillchar_status(&attr, wp);
}
}
+ if (statuscol_lnum) {
+ HlPriId line = { 0 };
+ HlPriId cul = { 0 };
+ HlPriId num = { 0 };
+ linenr_T lnum = statuscol_lnum;
+ int num_signs = buf_get_signattrs(wp->w_buffer, lnum, sattrs, &num, &line, &cul);
+ decor_redraw_signs(wp->w_buffer, lnum - 1, &num_signs, sattrs, &num, &line, &cul);
+
+ statuscol.sattrs = sattrs;
+ statuscol.foldinfo = fold_info(wp, lnum);
+ wp->w_cursorline = win_cursorline_standout(wp) ? wp->w_cursor.lnum : 0;
+
+ if (wp->w_p_cul) {
+ if (statuscol.foldinfo.fi_level > 0 && statuscol.foldinfo.fi_lines > 0) {
+ wp->w_cursorline = statuscol.foldinfo.fi_lnum;
+ }
+ statuscol.use_cul = lnum == wp->w_cursorline && (wp->w_p_culopt_flags & CULOPT_NBR);
+ }
+
+ statuscol.sign_cul_id = statuscol.use_cul ? cul.hl_id : 0;
+ if (num.hl_id) {
+ stc_hl_id = num.hl_id;
+ } else if (statuscol.use_cul) {
+ stc_hl_id = HLF_CLN + 1;
+ } else if (wp->w_p_rnu) {
+ stc_hl_id = (lnum < wp->w_cursor.lnum ? HLF_LNA : HLF_LNB) + 1;
+ } else {
+ stc_hl_id = HLF_N + 1;
+ }
+
+ set_vim_var_nr(VV_LNUM, lnum);
+ set_vim_var_nr(VV_RELNUM, labs(get_cursor_rel_lnum(wp, lnum)));
+ set_vim_var_nr(VV_VIRTNUM, 0);
+ }
}
if (HAS_KEY(opts->maxwidth)) {
@@ -2151,18 +2209,18 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
maxwidth = (int)opts->maxwidth.data.integer;
} else {
- maxwidth = (use_tabline || (!use_winbar && global_stl_height() > 0)) ? Columns : wp->w_width;
+ maxwidth = statuscol_lnum ? win_col_off(wp)
+ : (use_tabline || (!use_winbar && global_stl_height() > 0)) ? Columns : wp->w_width;
}
char buf[MAXPATHL];
stl_hlrec_t *hltab;
- stl_hlrec_t **hltab_ptr = highlights ? &hltab : NULL;
// Temporarily reset 'cursorbind' to prevent side effects from moving the cursor away and back.
- int p_crb_save = ewp->w_p_crb;
- ewp->w_p_crb = false;
+ int p_crb_save = wp->w_p_crb;
+ wp->w_p_crb = false;
- int width = build_stl_str_hl(ewp,
+ int width = build_stl_str_hl(wp,
buf,
sizeof(buf),
str.data,
@@ -2170,14 +2228,14 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
0,
fillchar,
maxwidth,
- hltab_ptr,
+ highlights ? &hltab : NULL,
NULL,
- NULL);
+ statuscol_lnum ? &statuscol : NULL);
PUT(result, "width", INTEGER_OBJ(width));
// Restore original value of 'cursorbind'
- ewp->w_p_crb = p_crb_save;
+ wp->w_p_crb = p_crb_save;
if (highlights) {
Array hl_values = ARRAY_DICT_INIT;
@@ -2188,7 +2246,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
// add the default highlight at the beginning of the highlight list
if (hltab->start == NULL || (hltab->start - buf) != 0) {
Dictionary hl_info = ARRAY_DICT_INIT;
- grpname = get_default_stl_hl(wp, use_winbar);
+ grpname = get_default_stl_hl(use_tabline ? NULL : wp, use_winbar, stc_hl_id);
PUT(hl_info, "start", INTEGER_OBJ(0));
PUT(hl_info, "group", CSTR_TO_OBJ(grpname));
@@ -2202,7 +2260,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
PUT(hl_info, "start", INTEGER_OBJ(sp->start - buf));
if (sp->userhl == 0) {
- grpname = get_default_stl_hl(wp, use_winbar);
+ grpname = get_default_stl_hl(use_tabline ? NULL : wp, use_winbar, stc_hl_id);
} else if (sp->userhl < 0) {
grpname = syn_id2name(-sp->userhl);
} else {