Skip to content

Commit

Permalink
feat(ui): add 'statuscolumn' option
Browse files Browse the repository at this point in the history
Problem:    Unable to customize the column next to a window ('gutter').
Solution:   Add 'statuscolumn' option that follows the 'statusline' syntax,
	    allowing to customize the status column. Also supporting the %@
	    click execute function label. Adds new items @C and @s which
	    will print the fold and sign columns. Line numbers and signs
	    can be clicked, highlighted, aligned, transformed, margined etc.
  • Loading branch information
luukvbaal committed Jan 9, 2023
1 parent 50f0377 commit 364b131
Show file tree
Hide file tree
Showing 26 changed files with 681 additions and 43 deletions.
17 changes: 13 additions & 4 deletions runtime/doc/eval.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2001,10 +2001,10 @@ v:lc_time The current locale setting for time messages of the runtime
command. See |multi-lang|.

*v:lnum* *lnum-variable*
v:lnum Line number for the 'foldexpr' |fold-expr|, 'formatexpr' and
'indentexpr' expressions, tab page number for 'guitablabel'
and 'guitabtooltip'. Only valid while one of these
expressions is being evaluated. Read-only when in the
v:lnum Line number for the 'foldexpr' |fold-expr|, 'formatexpr',
'indentexpr' and 'statuscolumn' expressions, tab page number
for 'guitablabel' and 'guitabtooltip'. Only valid while one of
these expressions is being evaluated. Read-only when in the
|sandbox|.

*v:lua* *lua-variable*
Expand Down Expand Up @@ -2138,6 +2138,10 @@ v:register The name of the register in effect for the current normal mode
'*' or '+'.
Also see |getreg()| and |setreg()|

*v:relnum* *relnum-variable*
v:relnum Relative line number for the 'statuscolumn' expression.
Read-only.

*v:scrollstart* *scrollstart-variable*
v:scrollstart String describing the script or function that caused the
screen to scroll up. It's only set when it is empty, thus the
Expand Down Expand Up @@ -2293,6 +2297,11 @@ v:version Vim version number: major version times 100 plus minor

*v:vim_did_enter* *vim_did_enter-variable*
v:vim_did_enter 0 during startup, 1 just before |VimEnter|.
Read-only.

*v:wrap* *wrap-variable*
v:wrap Boolean indicating whether 'statuscolumn' is being evaluated
for the wrapped part of a line.
Read-only.

*v:warningmsg* *warningmsg-variable*
Expand Down
5 changes: 5 additions & 0 deletions runtime/doc/news.txt
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ The following new APIs or features were added.

|'splitkeep'| option to control the scroll behavior of horizontal splits.

|'statuscolumn'| option to customize the area to the side of a window,
normally containing the fold, sign and number columns. This new option follows
the 'statusline' syntax and can be used to transform the line numbers, create
mouse click callbacks for |signs|, introduce a custom margin or separator etc.

|nvim_select_popupmenu_item()| now supports |cmdline-completion| popup menu.

|'diffopt'| now includes a `linematch` option to enable a second-stage diff
Expand Down
46 changes: 46 additions & 0 deletions runtime/doc/options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6001,6 +6001,52 @@ A jump table for the options with a short description can be found at |Q_op|.
In case of buffer changing commands the cursor is placed at the column
where it was the last time the buffer was edited.

*'statuscolumn'* *'stc'*
'statuscolumn' 'stc' string (default: empty)
local to window
EXPERIMENTAL
When non-empty, this option determines the content of the area to the
side of a window, normally containing the fold, sign and number columns.
The format of this option is like that of 'statusline'.

Some of the items from the 'statusline' format are different for
'statuscolumn':

%l line number of currently drawn line
%r relative line number of currently drawn line
%s sign column for currently drawn line
%C fold column for currently drawn line

To draw the sign and fold columns, they must be included in
'statuscolumn'.

The |v:lnum| variable holds the line number to be drawn.
The |v:relnum| variable holds the relative line number to be drawn.
The |v:wrap| variable holds true for the wrapped part of a line.

Examples: >vim
" Relative number with bar separator and click handlers:
:set statuscolumn=%@SignCb@%s%=%T%@NumCb@%r│%T

" Right aligned relative cursor line number:
:let &stc='%=%{v:relnum?v:relnum:v:lnum} '

" Line numbers in hexadecimal for non wrapped part of lines:
:let &stc='%=%{v:wrap?"":printf("%x",v:lnum)} '

" Human readable line numbers with thousands separator:
:let &stc='%{substitute(v:lnum,"\\d\\zs\\ze\\'
. '%(\\d\\d\\d\\)\\+$",",","g")}'

" Both relative and absolute line numbers with different
" highlighting for odd and even relative numbers:
:let &stc='%#NonText#%{&nu?v:lnum:""}' .
'%=%{&rnu&&(v:lnum%2)?"\ ".v:relnum:""}' .
'%#LineNr#%{&rnu&&!(v:lnum%2)?"\ ".v:relnum:""}'

< WARNING: this expression is evaluated for each screen line so defining
an expensive expression can negatively affect render performance.

*'statusline'* *'stl'* *E540* *E542*
'statusline' 'stl' string (default empty)
global or local to window |global-local|
Expand Down
1 change: 1 addition & 0 deletions runtime/doc/quickref.txt
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,7 @@ Short explanation of each option: *option-list*
'splitkeep' 'spk' determines scroll behavior for split windows
'splitright' 'spr' new window is put right of the current one
'startofline' 'sol' commands move cursor to first non-blank in line
'statuscolumn' 'stc' custom format for the status column
'statusline' 'stl' custom format for the status line
'suffixes' 'su' suffixes that are ignored with multiple match
'suffixesadd' 'sua' suffixes added when searching for a file
Expand Down
3 changes: 3 additions & 0 deletions runtime/optwin.vim
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,9 @@ call <SID>Header(gettext("multiple windows"))
call <SID>AddOption("laststatus", gettext("0, 1, 2 or 3; when to use a status line for the last window"))
call append("$", " \tset ls=" . &ls)
if has("statusline")
call <SID>AddOption("statuscolumn", gettext("custom format for the status column"))
call append("$", "\t" .. s:local_to_window)
call <SID>OptionG("stc", &stc)
call <SID>AddOption("statusline", gettext("alternate format to be used for a status line"))
call <SID>OptionG("stl", &stl)
endif
Expand Down
1 change: 1 addition & 0 deletions src/nvim/api/vim.c
Original file line number Diff line number Diff line change
Expand Up @@ -2238,6 +2238,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
fillchar,
maxwidth,
hltab_ptr,
NULL,
NULL);

PUT(result, "width", INTEGER_OBJ(width));
Expand Down
4 changes: 2 additions & 2 deletions src/nvim/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -3236,7 +3236,7 @@ void maketitle(void)
if (*p_titlestring != NUL) {
if (stl_syntax & STL_IN_TITLE) {
build_stl_str_hl(curwin, buf, sizeof(buf), p_titlestring,
"titlestring", 0, 0, maxlen, NULL, NULL);
"titlestring", 0, 0, maxlen, NULL, NULL, NULL);
title_str = buf;
} else {
title_str = p_titlestring;
Expand Down Expand Up @@ -3342,7 +3342,7 @@ void maketitle(void)
if (*p_iconstring != NUL) {
if (stl_syntax & STL_IN_ICON) {
build_stl_str_hl(curwin, icon_str, sizeof(buf), p_iconstring,
"iconstring", 0, 0, 0, NULL, NULL);
"iconstring", 0, 0, 0, NULL, NULL, NULL);
} else {
icon_str = p_iconstring;
}
Expand Down
28 changes: 28 additions & 0 deletions src/nvim/buffer_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ typedef struct {
#define w_p_cc w_onebuf_opt.wo_cc // 'colorcolumn'
char *wo_sbr;
#define w_p_sbr w_onebuf_opt.wo_sbr // 'showbreak'
char *wo_stc;
#define w_p_stc w_onebuf_opt.wo_stc // 'statuscolumn'
char *wo_stl;
#define w_p_stl w_onebuf_opt.wo_stl // 'statusline'
char *wo_wbr;
Expand Down Expand Up @@ -1300,6 +1302,7 @@ struct window_S {
linenr_T w_redraw_bot; // when != 0: last line needing redraw
bool w_redr_status; // if true statusline/winbar must be redrawn
bool w_redr_border; // if true border must be redrawn
bool w_redr_statuscol; // if true 'statuscolumn' must be redrawn

// remember what is shown in the ruler for this window (if 'ruler' set)
pos_T w_ru_cursor; // cursor position shown in ruler
Expand Down Expand Up @@ -1404,6 +1407,31 @@ struct window_S {
StlClickDefinition *w_winbar_click_defs;
// Size of the w_winbar_click_defs array
size_t w_winbar_click_defs_size;

// Status column click definitions
StlClickDefinition *w_statuscol_click_defs;
// Size of the w_statuscol_click_defs array
size_t w_statuscol_click_defs_size;
};

/// Struct to hold info for 'statuscolumn'
typedef struct statuscol statuscol_T;

struct statuscol {
int width; // width of the status column
int cur_attr; // current attributes in text
int num_attr; // attributes used for line number
int fold_attr; // attributes used for fold column
int sign_attr[SIGN_SHOW_MAX]; // attributes used for signs
int truncate; // truncated width
bool draw; // draw statuscolumn or not
char fold_text[10]; // text in fold column (%C)
char *sign_text[SIGN_SHOW_MAX]; // text in sign column (%s)
char text[MAXPATHL]; // text in status column
char *textp; // current position in text
size_t text_len; // length of text
stl_hlrec_t *hlrec; // highlight groups
stl_hlrec_t *hlrecp; // current highlight group
};

/// Macros defined in Vim, but not in Neovim
Expand Down
Loading

0 comments on commit 364b131

Please sign in to comment.