diff options
author | Luuk van Baal <luukvbaal@gmail.com> | 2023-04-06 03:33:57 +0200 |
---|---|---|
committer | Luuk van Baal <luukvbaal@gmail.com> | 2023-04-07 03:27:44 +0200 |
commit | 25dfed6e0148771cdb659df8c616df3860583c47 (patch) | |
tree | e7e7e71e9c8cdc797d792e30f93a6ab3d2099da4 | |
parent | fd32a987520cb132455d61301467182cb58cddf2 (diff) | |
download | rneovim-25dfed6e0148771cdb659df8c616df3860583c47.tar.gz rneovim-25dfed6e0148771cdb659df8c616df3860583c47.tar.bz2 rneovim-25dfed6e0148771cdb659df8c616df3860583c47.zip |
feat(api): set statuscolumn line number in nvim_eval_statusline()
Having the user set `v:lnum` before calling `nvim_eval_statusline()` is
unnecesarily fragile. Redraws inbetween setting `v:lnum` and the
`nvim_eval_statusline()` call will overwrite `v:lnum`.
-rw-r--r-- | runtime/doc/api.txt | 4 | ||||
-rw-r--r-- | runtime/doc/news.txt | 2 | ||||
-rw-r--r-- | src/nvim/api/keysets.lua | 2 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 74 | ||||
-rw-r--r-- | test/functional/api/vim_spec.lua | 10 |
5 files changed, 50 insertions, 42 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 52c3f7fa97..09d260e0cd 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -773,8 +773,8 @@ nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()* • use_tabline: (boolean) Evaluate tabline instead of statusline. When true, {winid} is ignored. Mutually exclusive with {use_winbar}. - • use_statuscol: (boolean) Evaluate statuscolumn instead of - statusline. + • use_statuscol_lnum: (number) Evaluate statuscolumn for this + line number instead of statusline. Return: ~ Dictionary containing statusline information, with these keys: diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 98f3f3f398..12dc4674af 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -74,7 +74,7 @@ NEW FEATURES *news-features* The following new APIs or features were added. • |nvim_eval_statusline()| supports evaluating the |'statuscolumn'| through a - new `opts` field: `use_statuscol`. + new `opts` field: `use_statuscol_lnum`. • |nvim_buf_get_extmarks()| now accepts a -1 `ns_id` to request extmarks from all namespaces and adds the namespace id to the details array. diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua index 26e87bccec..01f5a8b860 100644 --- a/src/nvim/api/keysets.lua +++ b/src/nvim/api/keysets.lua @@ -97,7 +97,7 @@ return { "highlights"; "use_winbar"; "use_tabline"; - "use_statuscol"; + "use_statuscol_lnum"; }}; { 'option', { "scope"; diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 383953a676..b62521290d 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -2056,7 +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: (boolean) Evaluate statuscolumn instead of statusline. +/// - 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: @@ -2075,10 +2075,10 @@ 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; - bool use_statuscol = false; bool highlights = false; if (str.size < 2 || memcmp(str.data, "%!", 2) != 0) { @@ -2116,47 +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); - use_bools++; 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); - use_bools++; if (ERROR_SET(err)) { return result; } - } - if (HAS_KEY(opts->use_statuscol)) { - use_statuscol = api_object_to_bool(opts->use_statuscol, "use_statuscol", false, err); use_bools++; - if (ERROR_SET(err)) { + } + + 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'", { + "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; @@ -2165,18 +2166,25 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * fillchar = fillchar_status(&attr, wp); } } - if (use_statuscol) { + if (statuscol_lnum) { HlPriId line = { 0 }; HlPriId cul = { 0 }; HlPriId num = { 0 }; - linenr_T lnum = (linenr_T)get_vim_var_nr(VV_LNUM); + 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); - statuscol.use_cul = wp->w_p_cul && lnum == wp->w_cursorline - && (wp->w_p_culopt_flags & CULOPT_NBR); + 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; @@ -2187,6 +2195,8 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * } 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); } @@ -2199,7 +2209,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * maxwidth = (int)opts->maxwidth.data.integer; } else { - maxwidth = use_statuscol ? win_col_off(wp) + maxwidth = statuscol_lnum ? win_col_off(wp) : (use_tabline || (!use_winbar && global_stl_height() > 0)) ? Columns : wp->w_width; } @@ -2207,10 +2217,10 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * stl_hlrec_t *hltab; // 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, @@ -2220,12 +2230,12 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * maxwidth, highlights ? &hltab : NULL, NULL, - use_statuscol ? &statuscol : 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; @@ -2236,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, stc_hl_id); + 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)); @@ -2250,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, stc_hl_id); + 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 { diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index cddea48a76..af6fbf092a 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -3422,7 +3422,7 @@ describe('API', function() { use_winbar = true, highlights = true })) end) it('works with statuscolumn', function() - command([[ + exec([[ let &stc='%C%s%=%l ' set cul nu nuw=3 scl=yes:2 fdc=2 call setline(1, repeat(['aaaaa'], 5)) @@ -3431,9 +3431,8 @@ describe('API', function() call sign_place(2, 1, 'a', bufnr(), {'lnum':4}) call nvim_buf_set_extmark(0, g:ns, 3, 1, { 'sign_text':'bb', 'sign_hl_group':'ErrorMsg' }) 1,5fold | 1,5 fold | foldopen! + norm 4G ]]) - command('norm 4G') - command('let v:lnum=4') eq({ str = '││aabb 4 ', width = 9, @@ -3444,8 +3443,7 @@ describe('API', function() { group = 'ErrorMsg', start = 8 }, { group = 'Normal', start = 10 } } - }, meths.eval_statusline('%C%s%=%l ', { use_statuscol = true, highlights = true })) - command('let v:lnum=3') + }, meths.eval_statusline('%C%s%=%l ', { use_statuscol_lnum = 4, highlights = true })) eq({ str = '3 ' , width = 2, @@ -3453,7 +3451,7 @@ describe('API', function() { group = 'LineNr', start = 0 }, { group = 'ErrorMsg', start = 1 } } - }, meths.eval_statusline('%l%#ErrorMsg# ', { use_statuscol = true, highlights = true })) + }, meths.eval_statusline('%l%#ErrorMsg# ', { use_statuscol_lnum = 3, highlights = true })) end) it('no memory leak with click functions', function() meths.eval_statusline('%@ClickFunc@StatusLineStringWithClickFunc%T', {}) |