mirror of
https://github.com/neovim/neovim.git
synced 2025-09-15 15:58:17 +00:00
feat(ui): add 'statuscolumn' option
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.
This commit is contained in:
@@ -2001,10 +2001,10 @@ v:lc_time The current locale setting for time messages of the runtime
|
|||||||
command. See |multi-lang|.
|
command. See |multi-lang|.
|
||||||
|
|
||||||
*v:lnum* *lnum-variable*
|
*v:lnum* *lnum-variable*
|
||||||
v:lnum Line number for the 'foldexpr' |fold-expr|, 'formatexpr' and
|
v:lnum Line number for the 'foldexpr' |fold-expr|, 'formatexpr',
|
||||||
'indentexpr' expressions, tab page number for 'guitablabel'
|
'indentexpr' and 'statuscolumn' expressions, tab page number
|
||||||
and 'guitabtooltip'. Only valid while one of these
|
for 'guitablabel' and 'guitabtooltip'. Only valid while one of
|
||||||
expressions is being evaluated. Read-only when in the
|
these expressions is being evaluated. Read-only when in the
|
||||||
|sandbox|.
|
|sandbox|.
|
||||||
|
|
||||||
*v:lua* *lua-variable*
|
*v:lua* *lua-variable*
|
||||||
@@ -2138,6 +2138,10 @@ v:register The name of the register in effect for the current normal mode
|
|||||||
'*' or '+'.
|
'*' or '+'.
|
||||||
Also see |getreg()| and |setreg()|
|
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* *scrollstart-variable*
|
||||||
v:scrollstart String describing the script or function that caused the
|
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
|
screen to scroll up. It's only set when it is empty, thus the
|
||||||
@@ -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* *vim_did_enter-variable*
|
||||||
v:vim_did_enter 0 during startup, 1 just before |VimEnter|.
|
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.
|
Read-only.
|
||||||
|
|
||||||
*v:warningmsg* *warningmsg-variable*
|
*v:warningmsg* *warningmsg-variable*
|
||||||
|
@@ -118,6 +118,11 @@ The following new APIs or features were added.
|
|||||||
|
|
||||||
• |'splitkeep'| option to control the scroll behavior of horizontal splits.
|
• |'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.
|
• |nvim_select_popupmenu_item()| now supports |cmdline-completion| popup menu.
|
||||||
|
|
||||||
• |'diffopt'| now includes a `linematch` option to enable a second-stage diff
|
• |'diffopt'| now includes a `linematch` option to enable a second-stage diff
|
||||||
|
@@ -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
|
In case of buffer changing commands the cursor is placed at the column
|
||||||
where it was the last time the buffer was edited.
|
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'* *E540* *E542*
|
||||||
'statusline' 'stl' string (default empty)
|
'statusline' 'stl' string (default empty)
|
||||||
global or local to window |global-local|
|
global or local to window |global-local|
|
||||||
|
@@ -883,6 +883,7 @@ Short explanation of each option: *option-list*
|
|||||||
'splitkeep' 'spk' determines scroll behavior for split windows
|
'splitkeep' 'spk' determines scroll behavior for split windows
|
||||||
'splitright' 'spr' new window is put right of the current one
|
'splitright' 'spr' new window is put right of the current one
|
||||||
'startofline' 'sol' commands move cursor to first non-blank in line
|
'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
|
'statusline' 'stl' custom format for the status line
|
||||||
'suffixes' 'su' suffixes that are ignored with multiple match
|
'suffixes' 'su' suffixes that are ignored with multiple match
|
||||||
'suffixesadd' 'sua' suffixes added when searching for a file
|
'suffixesadd' 'sua' suffixes added when searching for a file
|
||||||
|
@@ -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 <SID>AddOption("laststatus", gettext("0, 1, 2 or 3; when to use a status line for the last window"))
|
||||||
call append("$", " \tset ls=" . &ls)
|
call append("$", " \tset ls=" . &ls)
|
||||||
if has("statusline")
|
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>AddOption("statusline", gettext("alternate format to be used for a status line"))
|
||||||
call <SID>OptionG("stl", &stl)
|
call <SID>OptionG("stl", &stl)
|
||||||
endif
|
endif
|
||||||
|
@@ -2238,6 +2238,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
|||||||
fillchar,
|
fillchar,
|
||||||
maxwidth,
|
maxwidth,
|
||||||
hltab_ptr,
|
hltab_ptr,
|
||||||
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
PUT(result, "width", INTEGER_OBJ(width));
|
PUT(result, "width", INTEGER_OBJ(width));
|
||||||
|
@@ -3236,7 +3236,7 @@ void maketitle(void)
|
|||||||
if (*p_titlestring != NUL) {
|
if (*p_titlestring != NUL) {
|
||||||
if (stl_syntax & STL_IN_TITLE) {
|
if (stl_syntax & STL_IN_TITLE) {
|
||||||
build_stl_str_hl(curwin, buf, sizeof(buf), p_titlestring,
|
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;
|
title_str = buf;
|
||||||
} else {
|
} else {
|
||||||
title_str = p_titlestring;
|
title_str = p_titlestring;
|
||||||
@@ -3342,7 +3342,7 @@ void maketitle(void)
|
|||||||
if (*p_iconstring != NUL) {
|
if (*p_iconstring != NUL) {
|
||||||
if (stl_syntax & STL_IN_ICON) {
|
if (stl_syntax & STL_IN_ICON) {
|
||||||
build_stl_str_hl(curwin, icon_str, sizeof(buf), p_iconstring,
|
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 {
|
} else {
|
||||||
icon_str = p_iconstring;
|
icon_str = p_iconstring;
|
||||||
}
|
}
|
||||||
|
@@ -204,6 +204,8 @@ typedef struct {
|
|||||||
#define w_p_cc w_onebuf_opt.wo_cc // 'colorcolumn'
|
#define w_p_cc w_onebuf_opt.wo_cc // 'colorcolumn'
|
||||||
char *wo_sbr;
|
char *wo_sbr;
|
||||||
#define w_p_sbr w_onebuf_opt.wo_sbr // 'showbreak'
|
#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;
|
char *wo_stl;
|
||||||
#define w_p_stl w_onebuf_opt.wo_stl // 'statusline'
|
#define w_p_stl w_onebuf_opt.wo_stl // 'statusline'
|
||||||
char *wo_wbr;
|
char *wo_wbr;
|
||||||
@@ -1300,6 +1302,7 @@ struct window_S {
|
|||||||
linenr_T w_redraw_bot; // when != 0: last line needing redraw
|
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_status; // if true statusline/winbar must be redrawn
|
||||||
bool w_redr_border; // if true border 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)
|
// remember what is shown in the ruler for this window (if 'ruler' set)
|
||||||
pos_T w_ru_cursor; // cursor position shown in ruler
|
pos_T w_ru_cursor; // cursor position shown in ruler
|
||||||
@@ -1404,6 +1407,31 @@ struct window_S {
|
|||||||
StlClickDefinition *w_winbar_click_defs;
|
StlClickDefinition *w_winbar_click_defs;
|
||||||
// Size of the w_winbar_click_defs array
|
// Size of the w_winbar_click_defs array
|
||||||
size_t w_winbar_click_defs_size;
|
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
|
/// Macros defined in Vim, but not in Neovim
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
#include "nvim/decoration_provider.h"
|
#include "nvim/decoration_provider.h"
|
||||||
#include "nvim/diff.h"
|
#include "nvim/diff.h"
|
||||||
#include "nvim/drawline.h"
|
#include "nvim/drawline.h"
|
||||||
|
#include "nvim/eval.h"
|
||||||
#include "nvim/extmark_defs.h"
|
#include "nvim/extmark_defs.h"
|
||||||
#include "nvim/fold.h"
|
#include "nvim/fold.h"
|
||||||
#include "nvim/garray.h"
|
#include "nvim/garray.h"
|
||||||
@@ -43,6 +44,7 @@
|
|||||||
#include "nvim/sign.h"
|
#include "nvim/sign.h"
|
||||||
#include "nvim/spell.h"
|
#include "nvim/spell.h"
|
||||||
#include "nvim/state.h"
|
#include "nvim/state.h"
|
||||||
|
#include "nvim/statusline.h"
|
||||||
#include "nvim/strings.h"
|
#include "nvim/strings.h"
|
||||||
#include "nvim/syntax.h"
|
#include "nvim/syntax.h"
|
||||||
#include "nvim/terminal.h"
|
#include "nvim/terminal.h"
|
||||||
@@ -60,6 +62,7 @@ typedef enum {
|
|||||||
WL_FOLD, // 'foldcolumn'
|
WL_FOLD, // 'foldcolumn'
|
||||||
WL_SIGN, // column for signs
|
WL_SIGN, // column for signs
|
||||||
WL_NR, // line number
|
WL_NR, // line number
|
||||||
|
WL_STC, // 'statuscolumn'
|
||||||
WL_BRI, // 'breakindent'
|
WL_BRI, // 'breakindent'
|
||||||
WL_SBR, // 'showbreak' or 'diff'
|
WL_SBR, // 'showbreak' or 'diff'
|
||||||
WL_LINE, // text in the line
|
WL_LINE, // text in the line
|
||||||
@@ -395,6 +398,90 @@ static int get_sign_attrs(buf_T *buf, linenr_T lnum, SignTextAttrs *sattrs, int
|
|||||||
return num_signs;
|
return num_signs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines,
|
||||||
|
int cul_attr, int sign_num_attr, SignTextAttrs *sattrs,
|
||||||
|
foldinfo_T foldinfo, char_u *extra, statuscol_T *stcp)
|
||||||
|
{
|
||||||
|
long relnum;
|
||||||
|
bool wrapped = row != startrow + filler_lines;
|
||||||
|
bool use_cul = use_cursor_line_sign(wp, lnum);
|
||||||
|
|
||||||
|
// Set num, fold and sign text and attrs, empty when wrapped
|
||||||
|
if (row == startrow) {
|
||||||
|
relnum = labs(get_cursor_rel_lnum(wp, lnum));
|
||||||
|
stcp->num_attr = sign_num_attr ? sign_num_attr
|
||||||
|
: get_line_number_attr(wp, lnum, row, startrow, filler_lines);
|
||||||
|
|
||||||
|
if (compute_foldcolumn(wp, 0)) {
|
||||||
|
size_t n = fill_foldcolumn((char_u *)stcp->fold_text, wp, foldinfo, lnum);
|
||||||
|
stcp->fold_text[n] = NUL;
|
||||||
|
stcp->fold_attr = win_hl_attr(wp, use_cul ? HLF_CLF : HLF_FC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (; i < wp->w_scwidth; i++) {
|
||||||
|
SignTextAttrs *sattr = wrapped ? NULL : sign_get_attr(i, sattrs, wp->w_scwidth);
|
||||||
|
stcp->sign_text[i] = sattr && sattr->text ? sattr->text : " ";
|
||||||
|
stcp->sign_attr[i] = use_cul && cul_attr ? cul_attr : sattr ? sattr->hl_attr_id : 0;
|
||||||
|
}
|
||||||
|
stcp->sign_text[i] = NULL;
|
||||||
|
|
||||||
|
int width = build_statuscol_str(wp, row == startrow, wrapped, lnum, relnum,
|
||||||
|
stcp->width, ' ', stcp->text, &stcp->hlrec, stcp);
|
||||||
|
// Force a redraw in case of error or when truncated
|
||||||
|
if (*wp->w_p_stc == NUL || (stcp->truncate > 0 && wp->w_nrwidth < MAX_NUMBERWIDTH)) {
|
||||||
|
if (stcp->truncate) { // Avoid truncating 'statuscolumn'
|
||||||
|
wp->w_nrwidth = MIN(MAX_NUMBERWIDTH, wp->w_nrwidth + stcp->truncate);
|
||||||
|
wp->w_nrwidth_width = wp->w_nrwidth;
|
||||||
|
} else { // 'statuscolumn' reset due to error
|
||||||
|
wp->w_nrwidth_line_count = 0;
|
||||||
|
wp->w_nrwidth = (wp->w_p_nu || wp->w_p_rnu) * number_width(wp);
|
||||||
|
}
|
||||||
|
wp->w_redr_statuscol = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset text/highlight pointer and current attr for new line
|
||||||
|
stcp->textp = stcp->text;
|
||||||
|
stcp->hlrecp = stcp->hlrec;
|
||||||
|
stcp->cur_attr = stcp->num_attr;
|
||||||
|
stcp->text_len = strlen(stcp->text);
|
||||||
|
|
||||||
|
int fill = stcp->width - width;
|
||||||
|
if (fill > 0) {
|
||||||
|
// Fill up with ' '
|
||||||
|
memset(&stcp->text[stcp->text_len], ' ', (size_t)fill);
|
||||||
|
stcp->text_len += (size_t)fill;
|
||||||
|
stcp->text[stcp->text_len] = NUL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_statuscol_display_info(LineDrawState *draw_state, int *char_attr, int *n_extrap,
|
||||||
|
int *c_extrap, int *c_finalp, char_u *extra, char **pp_extra,
|
||||||
|
statuscol_T *stcp)
|
||||||
|
{
|
||||||
|
*c_extrap = NUL;
|
||||||
|
*c_finalp = NUL;
|
||||||
|
do {
|
||||||
|
*draw_state = WL_STC;
|
||||||
|
*char_attr = stcp->cur_attr;
|
||||||
|
*pp_extra = stcp->textp;
|
||||||
|
*n_extrap = stcp->hlrecp->start ? (int)(stcp->hlrecp->start - stcp->textp)
|
||||||
|
: (int)strlen(*pp_extra);
|
||||||
|
// Prepare for next highlight section if not yet at the end
|
||||||
|
if (stcp->textp + *n_extrap < stcp->text + stcp->text_len) {
|
||||||
|
int hl = stcp->hlrecp->userhl;
|
||||||
|
stcp->textp = stcp->hlrecp->start;
|
||||||
|
stcp->cur_attr = hl < 0 ? syn_id2attr(-stcp->hlrecp->userhl)
|
||||||
|
: hl > 0 ? hl : stcp->num_attr;
|
||||||
|
stcp->hlrecp++;
|
||||||
|
*draw_state = WL_STC - 1;
|
||||||
|
}
|
||||||
|
// Skip over empty highlight sections
|
||||||
|
} while (*n_extrap == 0 && stcp->textp < stcp->text + stcp->text_len);
|
||||||
|
}
|
||||||
|
|
||||||
/// Return true if CursorLineNr highlight is to be used for the number column.
|
/// Return true if CursorLineNr highlight is to be used for the number column.
|
||||||
///
|
///
|
||||||
/// - 'cursorline' must be set
|
/// - 'cursorline' must be set
|
||||||
@@ -1098,6 +1185,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
|||||||
extra_check = true;
|
extra_check = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
statuscol_T statuscol = { 0 };
|
||||||
|
if (*wp->w_p_stc != NUL) {
|
||||||
|
// Draw the 'statuscolumn' if option is set.
|
||||||
|
statuscol.draw = true;
|
||||||
|
statuscol.width = win_col_off(wp);
|
||||||
|
}
|
||||||
|
|
||||||
int sign_idx = 0;
|
int sign_idx = 0;
|
||||||
// Repeat for the whole displayed line.
|
// Repeat for the whole displayed line.
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -1125,9 +1219,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip fold, sign and number states if 'statuscolumn' is set.
|
||||||
|
if (draw_state == WL_FOLD - 1 && n_extra == 0 && statuscol.draw) {
|
||||||
|
draw_state = WL_STC - 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (draw_state == WL_FOLD - 1 && n_extra == 0) {
|
if (draw_state == WL_FOLD - 1 && n_extra == 0) {
|
||||||
int fdc = compute_foldcolumn(wp, 0);
|
int fdc = compute_foldcolumn(wp, 0);
|
||||||
|
|
||||||
draw_state = WL_FOLD;
|
draw_state = WL_FOLD;
|
||||||
if (fdc > 0) {
|
if (fdc > 0) {
|
||||||
// Draw the 'foldcolumn'. Allocate a buffer, "extra" may
|
// Draw the 'foldcolumn'. Allocate a buffer, "extra" may
|
||||||
@@ -1217,7 +1315,23 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (draw_state == WL_NR && n_extra == 0) {
|
if (draw_state == WL_STC - 1 && n_extra == 0) {
|
||||||
|
draw_state = WL_STC;
|
||||||
|
// Draw the 'statuscolumn' if option is set.
|
||||||
|
if (statuscol.draw) {
|
||||||
|
if (statuscol.text_len == 0) {
|
||||||
|
get_statuscol_str(wp, lnum, row, startrow, filler_lines, cul_attr,
|
||||||
|
sign_num_attr, sattrs, foldinfo, extra, &statuscol);
|
||||||
|
if (wp->w_redr_statuscol) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get_statuscol_display_info(&draw_state, &char_attr, &n_extra, &c_extra,
|
||||||
|
&c_final, extra, &p_extra, &statuscol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (draw_state == WL_STC && n_extra == 0) {
|
||||||
win_col_offset = off;
|
win_col_offset = off;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1349,7 +1463,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
|||||||
&& wp == curwin
|
&& wp == curwin
|
||||||
&& lnum == wp->w_cursor.lnum
|
&& lnum == wp->w_cursor.lnum
|
||||||
&& vcol >= (long)wp->w_virtcol)
|
&& vcol >= (long)wp->w_virtcol)
|
||||||
|| (number_only && draw_state > WL_NR))
|
|| (number_only && draw_state > WL_STC))
|
||||||
&& filler_todo <= 0) {
|
&& filler_todo <= 0) {
|
||||||
draw_virt_text(wp, buf, win_col_offset, &col, grid->cols, row);
|
draw_virt_text(wp, buf, win_col_offset, &col, grid->cols, row);
|
||||||
grid_put_linebuf(grid, row, 0, col, -grid->cols, wp->w_p_rl, wp, bg_attr, false);
|
grid_put_linebuf(grid, row, 0, col, -grid->cols, wp->w_p_rl, wp, bg_attr, false);
|
||||||
@@ -2214,7 +2328,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
|||||||
&& wp->w_p_list
|
&& wp->w_p_list
|
||||||
&& (wp->w_p_wrap ? (wp->w_skipcol > 0 && row == 0) : wp->w_leftcol > 0)
|
&& (wp->w_p_wrap ? (wp->w_skipcol > 0 && row == 0) : wp->w_leftcol > 0)
|
||||||
&& filler_todo <= 0
|
&& filler_todo <= 0
|
||||||
&& draw_state > WL_NR
|
&& draw_state > WL_STC
|
||||||
&& c != NUL) {
|
&& c != NUL) {
|
||||||
c = wp->w_p_lcs_chars.prec;
|
c = wp->w_p_lcs_chars.prec;
|
||||||
lcs_prec_todo = NUL;
|
lcs_prec_todo = NUL;
|
||||||
@@ -2508,7 +2622,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
|||||||
col++;
|
col++;
|
||||||
// UTF-8: Put a 0 in the second screen char.
|
// UTF-8: Put a 0 in the second screen char.
|
||||||
linebuf_char[off][0] = 0;
|
linebuf_char[off][0] = 0;
|
||||||
if (draw_state > WL_NR && filler_todo <= 0) {
|
if (draw_state > WL_STC && filler_todo <= 0) {
|
||||||
vcol++;
|
vcol++;
|
||||||
}
|
}
|
||||||
// When "tocol" is halfway through a character, set it to the end of
|
// When "tocol" is halfway through a character, set it to the end of
|
||||||
@@ -2591,7 +2705,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
|||||||
|
|
||||||
// Only advance the "vcol" when after the 'number' or 'relativenumber'
|
// Only advance the "vcol" when after the 'number' or 'relativenumber'
|
||||||
// column.
|
// column.
|
||||||
if (draw_state > WL_NR
|
if (draw_state > WL_STC
|
||||||
&& filler_todo <= 0) {
|
&& filler_todo <= 0) {
|
||||||
vcol++;
|
vcol++;
|
||||||
}
|
}
|
||||||
@@ -2601,7 +2715,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// restore attributes after "predeces" in 'listchars'
|
// restore attributes after "predeces" in 'listchars'
|
||||||
if (draw_state > WL_NR && n_attr3 > 0 && --n_attr3 == 0) {
|
if (draw_state > WL_STC && n_attr3 > 0 && --n_attr3 == 0) {
|
||||||
char_attr = saved_attr3;
|
char_attr = saved_attr3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2697,6 +2811,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
|||||||
if (filler_todo <= 0) {
|
if (filler_todo <= 0) {
|
||||||
need_showbreak = true;
|
need_showbreak = true;
|
||||||
}
|
}
|
||||||
|
if (statuscol.draw) {
|
||||||
|
if (row == startrow + 1 || row == startrow + filler_lines) {
|
||||||
|
// Re-evaluate 'statuscolumn' for the first wrapped row and non filler line
|
||||||
|
statuscol.text_len = 0;
|
||||||
|
} else { // Otherwise just reset the text/hlrec pointers
|
||||||
|
statuscol.textp = statuscol.text;
|
||||||
|
statuscol.hlrecp = statuscol.hlrec;
|
||||||
|
} // Fall back to default columns if the 'n' flag isn't in 'cpo'
|
||||||
|
statuscol.draw = vim_strchr(p_cpo, CPO_NUMCOL) == NULL;
|
||||||
|
}
|
||||||
filler_todo--;
|
filler_todo--;
|
||||||
// When the filler lines are actually below the last line of the
|
// When the filler lines are actually below the last line of the
|
||||||
// file, don't draw the line itself, break here.
|
// file, don't draw the line itself, break here.
|
||||||
|
@@ -522,7 +522,7 @@ int update_screen(void)
|
|||||||
// TODO(bfredl): special casing curwin here is SÅ JÄVLA BULL.
|
// TODO(bfredl): special casing curwin here is SÅ JÄVLA BULL.
|
||||||
// Either this should be done for all windows or not at all.
|
// Either this should be done for all windows or not at all.
|
||||||
if (curwin->w_redr_type < UPD_NOT_VALID
|
if (curwin->w_redr_type < UPD_NOT_VALID
|
||||||
&& curwin->w_nrwidth != ((curwin->w_p_nu || curwin->w_p_rnu)
|
&& curwin->w_nrwidth != ((curwin->w_p_nu || curwin->w_p_rnu || *curwin->w_p_stc)
|
||||||
? number_width(curwin) : 0)) {
|
? number_width(curwin) : 0)) {
|
||||||
curwin->w_redr_type = UPD_NOT_VALID;
|
curwin->w_redr_type = UPD_NOT_VALID;
|
||||||
}
|
}
|
||||||
@@ -1032,7 +1032,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
|
|||||||
|
|
||||||
// Force redraw when width of 'number' or 'relativenumber' column
|
// Force redraw when width of 'number' or 'relativenumber' column
|
||||||
// changes.
|
// changes.
|
||||||
int nrwidth = (wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) : 0;
|
int nrwidth = (wp->w_p_nu || wp->w_p_rnu || *wp->w_p_stc) ? number_width(wp) : 0;
|
||||||
if (wp->w_nrwidth != nrwidth) {
|
if (wp->w_nrwidth != nrwidth) {
|
||||||
type = UPD_NOT_VALID;
|
type = UPD_NOT_VALID;
|
||||||
wp->w_nrwidth = nrwidth;
|
wp->w_nrwidth = nrwidth;
|
||||||
@@ -1823,6 +1823,18 @@ static void win_update(win_T *wp, DecorProviders *providers)
|
|||||||
did_update = DID_NONE;
|
did_update = DID_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 'statuscolumn' width has changed or errored, start from the top.
|
||||||
|
if (wp->w_redr_statuscol) {
|
||||||
|
wp->w_redr_statuscol = false;
|
||||||
|
idx = 0;
|
||||||
|
row = 0;
|
||||||
|
lnum = wp->w_topline;
|
||||||
|
wp->w_lines_valid = 0;
|
||||||
|
wp->w_valid &= ~VALID_WCOL;
|
||||||
|
decor_providers_invoke_win(wp, providers, &line_providers, &provider_err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (lnum > buf->b_ml.ml_line_count) {
|
if (lnum > buf->b_ml.ml_line_count) {
|
||||||
eof = true;
|
eof = true;
|
||||||
break;
|
break;
|
||||||
|
@@ -267,6 +267,8 @@ static struct vimvar {
|
|||||||
VV(VV__NULL_DICT, "_null_dict", VAR_DICT, VV_RO),
|
VV(VV__NULL_DICT, "_null_dict", VAR_DICT, VV_RO),
|
||||||
VV(VV__NULL_BLOB, "_null_blob", VAR_BLOB, VV_RO),
|
VV(VV__NULL_BLOB, "_null_blob", VAR_BLOB, VV_RO),
|
||||||
VV(VV_LUA, "lua", VAR_PARTIAL, VV_RO),
|
VV(VV_LUA, "lua", VAR_PARTIAL, VV_RO),
|
||||||
|
VV(VV_RELNUM, "relnum", VAR_NUMBER, VV_RO),
|
||||||
|
VV(VV_WRAP, "wrap", VAR_BOOL, VV_RO),
|
||||||
};
|
};
|
||||||
#undef VV
|
#undef VV
|
||||||
|
|
||||||
|
@@ -165,6 +165,8 @@ typedef enum {
|
|||||||
VV__NULL_DICT, // Dictionary with NULL value. For test purposes only.
|
VV__NULL_DICT, // Dictionary with NULL value. For test purposes only.
|
||||||
VV__NULL_BLOB, // Blob with NULL value. For test purposes only.
|
VV__NULL_BLOB, // Blob with NULL value. For test purposes only.
|
||||||
VV_LUA,
|
VV_LUA,
|
||||||
|
VV_RELNUM,
|
||||||
|
VV_WRAP,
|
||||||
} VimVarIndex;
|
} VimVarIndex;
|
||||||
|
|
||||||
/// All recognized msgpack types
|
/// All recognized msgpack types
|
||||||
|
@@ -291,6 +291,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
|
|||||||
pos_T start_visual;
|
pos_T start_visual;
|
||||||
bool moved; // Has cursor moved?
|
bool moved; // Has cursor moved?
|
||||||
bool in_winbar; // mouse in window bar
|
bool in_winbar; // mouse in window bar
|
||||||
|
bool in_statuscol; // mouse in status column
|
||||||
bool in_status_line; // mouse in status line
|
bool in_status_line; // mouse in status line
|
||||||
static bool in_tab_line = false; // mouse clicked in tab line
|
static bool in_tab_line = false; // mouse clicked in tab line
|
||||||
bool in_sep_line; // mouse in vertical separator line
|
bool in_sep_line; // mouse in vertical separator line
|
||||||
@@ -645,10 +646,11 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
|
|||||||
|
|
||||||
moved = (jump_flags & CURSOR_MOVED);
|
moved = (jump_flags & CURSOR_MOVED);
|
||||||
in_winbar = (jump_flags & MOUSE_WINBAR);
|
in_winbar = (jump_flags & MOUSE_WINBAR);
|
||||||
|
in_statuscol = (jump_flags & MOUSE_STATUSCOL);
|
||||||
in_status_line = (jump_flags & IN_STATUS_LINE);
|
in_status_line = (jump_flags & IN_STATUS_LINE);
|
||||||
in_sep_line = (jump_flags & IN_SEP_LINE);
|
in_sep_line = (jump_flags & IN_SEP_LINE);
|
||||||
|
|
||||||
if ((in_winbar || in_status_line) && is_click) {
|
if ((in_winbar || in_status_line || in_statuscol) && is_click) {
|
||||||
// Handle click event on window bar or status lin
|
// Handle click event on window bar or status lin
|
||||||
int click_grid = mouse_grid;
|
int click_grid = mouse_grid;
|
||||||
int click_row = mouse_row;
|
int click_row = mouse_row;
|
||||||
@@ -659,7 +661,8 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
StlClickDefinition *click_defs = in_status_line ? wp->w_status_click_defs
|
StlClickDefinition *click_defs = in_status_line ? wp->w_status_click_defs
|
||||||
: wp->w_winbar_click_defs;
|
: in_winbar ? wp->w_winbar_click_defs
|
||||||
|
: wp->w_statuscol_click_defs;
|
||||||
|
|
||||||
if (in_status_line && global_stl_height() > 0) {
|
if (in_status_line && global_stl_height() > 0) {
|
||||||
// global statusline is displayed for the current window,
|
// global statusline is displayed for the current window,
|
||||||
@@ -682,8 +685,8 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} else if (in_winbar) {
|
} else if (in_winbar || in_statuscol) {
|
||||||
// A drag or release event in the window bar has no side effects.
|
// A drag or release event in the window bar and status column has no side effects.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1027,6 +1030,7 @@ int jump_to_mouse(int flags, bool *inclusive, int which_button)
|
|||||||
static bool on_status_line = false;
|
static bool on_status_line = false;
|
||||||
static bool on_sep_line = false;
|
static bool on_sep_line = false;
|
||||||
static bool on_winbar = false;
|
static bool on_winbar = false;
|
||||||
|
static bool on_statuscol = false;
|
||||||
static int prev_row = -1;
|
static int prev_row = -1;
|
||||||
static int prev_col = -1;
|
static int prev_col = -1;
|
||||||
static int did_drag = false; // drag was noticed
|
static int did_drag = false; // drag was noticed
|
||||||
@@ -1069,6 +1073,9 @@ retnomove:
|
|||||||
if (on_winbar) {
|
if (on_winbar) {
|
||||||
return IN_OTHER_WIN | MOUSE_WINBAR;
|
return IN_OTHER_WIN | MOUSE_WINBAR;
|
||||||
}
|
}
|
||||||
|
if (on_statuscol) {
|
||||||
|
return IN_OTHER_WIN | MOUSE_STATUSCOL;
|
||||||
|
}
|
||||||
if (flags & MOUSE_MAY_STOP_VIS) {
|
if (flags & MOUSE_MAY_STOP_VIS) {
|
||||||
end_visual_mode();
|
end_visual_mode();
|
||||||
redraw_curbuf_later(UPD_INVERTED); // delete the inversion
|
redraw_curbuf_later(UPD_INVERTED); // delete the inversion
|
||||||
@@ -1103,6 +1110,10 @@ retnomove:
|
|||||||
? wp->w_winbar_height != 0
|
? wp->w_winbar_height != 0
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
|
on_statuscol = grid == (col < win_col_off(wp))
|
||||||
|
? *wp->w_p_stc != NUL
|
||||||
|
: false;
|
||||||
|
|
||||||
on_sep_line = grid == DEFAULT_GRID_HANDLE && col >= wp->w_width
|
on_sep_line = grid == DEFAULT_GRID_HANDLE && col >= wp->w_width
|
||||||
? col - wp->w_width + 1 == 1
|
? col - wp->w_width + 1 == 1
|
||||||
: false;
|
: false;
|
||||||
@@ -1130,6 +1141,10 @@ retnomove:
|
|||||||
return IN_OTHER_WIN | MOUSE_WINBAR;
|
return IN_OTHER_WIN | MOUSE_WINBAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (on_statuscol) {
|
||||||
|
return IN_OTHER_WIN | MOUSE_STATUSCOL;
|
||||||
|
}
|
||||||
|
|
||||||
fdc = win_fdccol_count(wp);
|
fdc = win_fdccol_count(wp);
|
||||||
dragwin = NULL;
|
dragwin = NULL;
|
||||||
|
|
||||||
@@ -1230,6 +1245,9 @@ retnomove:
|
|||||||
} else if (on_winbar && which_button == MOUSE_RIGHT) {
|
} else if (on_winbar && which_button == MOUSE_RIGHT) {
|
||||||
// After a click on the window bar don't start Visual mode.
|
// After a click on the window bar don't start Visual mode.
|
||||||
return IN_OTHER_WIN | MOUSE_WINBAR;
|
return IN_OTHER_WIN | MOUSE_WINBAR;
|
||||||
|
} else if (on_statuscol && which_button == MOUSE_RIGHT) {
|
||||||
|
// After a click on the status column don't start Visual mode.
|
||||||
|
return IN_OTHER_WIN | MOUSE_STATUSCOL;
|
||||||
} else {
|
} else {
|
||||||
// keep_window_focus must be true
|
// keep_window_focus must be true
|
||||||
// before moving the cursor for a left click, stop Visual mode
|
// before moving the cursor for a left click, stop Visual mode
|
||||||
|
@@ -9,17 +9,18 @@
|
|||||||
#include "nvim/window.h"
|
#include "nvim/window.h"
|
||||||
|
|
||||||
/// jump_to_mouse() returns one of first five these values, possibly with
|
/// jump_to_mouse() returns one of first five these values, possibly with
|
||||||
/// some of the other four added.
|
/// some of the other five added.
|
||||||
enum {
|
enum {
|
||||||
IN_UNKNOWN = 0,
|
IN_UNKNOWN = 0,
|
||||||
IN_BUFFER = 1,
|
IN_BUFFER = 1,
|
||||||
IN_STATUS_LINE = 2, ///< on status or command line
|
IN_STATUS_LINE = 2, ///< on status or command line
|
||||||
IN_SEP_LINE = 4, ///< on vertical separator line
|
IN_SEP_LINE = 4, ///< on vertical separator line
|
||||||
IN_OTHER_WIN = 8, ///< in other window but can't go there
|
IN_OTHER_WIN = 8, ///< in other window but can't go there
|
||||||
CURSOR_MOVED = 0x100,
|
CURSOR_MOVED = 0x100,
|
||||||
MOUSE_FOLD_CLOSE = 0x200, ///< clicked on '-' in fold column
|
MOUSE_FOLD_CLOSE = 0x200, ///< clicked on '-' in fold column
|
||||||
MOUSE_FOLD_OPEN = 0x400, ///< clicked on '+' in fold column
|
MOUSE_FOLD_OPEN = 0x400, ///< clicked on '+' in fold column
|
||||||
MOUSE_WINBAR = 0x800, ///< in window toolbar
|
MOUSE_WINBAR = 0x800, ///< in window toolbar
|
||||||
|
MOUSE_STATUSCOL = 0x1000, ///< in 'statuscolumn'
|
||||||
};
|
};
|
||||||
|
|
||||||
/// flags for jump_to_mouse()
|
/// flags for jump_to_mouse()
|
||||||
|
@@ -649,7 +649,8 @@ void validate_cursor_col(void)
|
|||||||
// fold column and sign column (these don't move when scrolling horizontally).
|
// fold column and sign column (these don't move when scrolling horizontally).
|
||||||
int win_col_off(win_T *wp)
|
int win_col_off(win_T *wp)
|
||||||
{
|
{
|
||||||
return ((wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) + 1 : 0)
|
return ((wp->w_p_nu || wp->w_p_rnu || (*wp->w_p_stc != NUL)) ?
|
||||||
|
(number_width(wp) + (*wp->w_p_stc == NUL)) : 0)
|
||||||
+ (cmdwin_type == 0 || wp != curwin ? 0 : 1)
|
+ (cmdwin_type == 0 || wp != curwin ? 0 : 1)
|
||||||
+ win_fdccol_count(wp)
|
+ win_fdccol_count(wp)
|
||||||
+ (win_signcol_count(wp) * win_signcol_width(wp));
|
+ (win_signcol_count(wp) * win_signcol_width(wp));
|
||||||
|
@@ -2094,6 +2094,9 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
|
|||||||
if (curwin->w_p_spell) {
|
if (curwin->w_p_spell) {
|
||||||
errmsg = did_set_spelllang(curwin);
|
errmsg = did_set_spelllang(curwin);
|
||||||
}
|
}
|
||||||
|
} else if (((int *)varp == &curwin->w_p_nu || (int *)varp == &curwin->w_p_rnu)
|
||||||
|
&& *curwin->w_p_stc != NUL) { // '(relative)number' + 'statuscolumn'
|
||||||
|
curwin->w_nrwidth_line_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((int *)varp == &curwin->w_p_arab) {
|
if ((int *)varp == &curwin->w_p_arab) {
|
||||||
@@ -2316,7 +2319,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
|
|||||||
} else if (pp == &curwin->w_p_nuw || pp == &curwin->w_allbuf_opt.wo_nuw) {
|
} else if (pp == &curwin->w_p_nuw || pp == &curwin->w_allbuf_opt.wo_nuw) {
|
||||||
if (value < 1) {
|
if (value < 1) {
|
||||||
errmsg = e_positive;
|
errmsg = e_positive;
|
||||||
} else if (value > 20) {
|
} else if (value > MAX_NUMBERWIDTH) {
|
||||||
errmsg = e_invarg;
|
errmsg = e_invarg;
|
||||||
}
|
}
|
||||||
} else if (pp == &curbuf->b_p_iminsert || pp == &p_iminsert) {
|
} else if (pp == &curbuf->b_p_iminsert || pp == &p_iminsert) {
|
||||||
@@ -3630,6 +3633,9 @@ void unset_global_local_option(char *name, void *from)
|
|||||||
clear_string_option(&((win_T *)from)->w_p_ve);
|
clear_string_option(&((win_T *)from)->w_p_ve);
|
||||||
((win_T *)from)->w_ve_flags = 0;
|
((win_T *)from)->w_ve_flags = 0;
|
||||||
break;
|
break;
|
||||||
|
case PV_STC:
|
||||||
|
clear_string_option(&((win_T *)from)->w_p_stc);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4014,6 +4020,8 @@ static char_u *get_varp(vimoption_T *p)
|
|||||||
return (char_u *)&(curwin->w_p_winhl);
|
return (char_u *)&(curwin->w_p_winhl);
|
||||||
case PV_WINBL:
|
case PV_WINBL:
|
||||||
return (char_u *)&(curwin->w_p_winbl);
|
return (char_u *)&(curwin->w_p_winbl);
|
||||||
|
case PV_STC:
|
||||||
|
return (char_u *)&(curwin->w_p_stc);
|
||||||
default:
|
default:
|
||||||
iemsg(_("E356: get_varp ERROR"));
|
iemsg(_("E356: get_varp ERROR"));
|
||||||
}
|
}
|
||||||
@@ -4102,6 +4110,7 @@ void copy_winopt(winopt_T *from, winopt_T *to)
|
|||||||
to->wo_scl = copy_option_val(from->wo_scl);
|
to->wo_scl = copy_option_val(from->wo_scl);
|
||||||
to->wo_winhl = copy_option_val(from->wo_winhl);
|
to->wo_winhl = copy_option_val(from->wo_winhl);
|
||||||
to->wo_winbl = from->wo_winbl;
|
to->wo_winbl = from->wo_winbl;
|
||||||
|
to->wo_stc = copy_option_val(from->wo_stc);
|
||||||
|
|
||||||
// Copy the script context so that we know were the value was last set.
|
// Copy the script context so that we know were the value was last set.
|
||||||
memmove(to->wo_script_ctx, from->wo_script_ctx, sizeof(to->wo_script_ctx));
|
memmove(to->wo_script_ctx, from->wo_script_ctx, sizeof(to->wo_script_ctx));
|
||||||
@@ -4139,6 +4148,7 @@ static void check_winopt(winopt_T *wop)
|
|||||||
check_string_option(&wop->wo_fcs);
|
check_string_option(&wop->wo_fcs);
|
||||||
check_string_option(&wop->wo_ve);
|
check_string_option(&wop->wo_ve);
|
||||||
check_string_option(&wop->wo_wbr);
|
check_string_option(&wop->wo_wbr);
|
||||||
|
check_string_option(&wop->wo_stc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Free the allocated memory inside a winopt_T.
|
/// Free the allocated memory inside a winopt_T.
|
||||||
@@ -4165,6 +4175,7 @@ void clear_winopt(winopt_T *wop)
|
|||||||
clear_string_option(&wop->wo_fcs);
|
clear_string_option(&wop->wo_fcs);
|
||||||
clear_string_option(&wop->wo_ve);
|
clear_string_option(&wop->wo_ve);
|
||||||
clear_string_option(&wop->wo_wbr);
|
clear_string_option(&wop->wo_wbr);
|
||||||
|
clear_string_option(&wop->wo_stc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void didset_window_options(win_T *wp, bool valid_cursor)
|
void didset_window_options(win_T *wp, bool valid_cursor)
|
||||||
|
@@ -19,6 +19,8 @@ typedef enum {
|
|||||||
#define BCO_ALWAYS 2 // always copy the options
|
#define BCO_ALWAYS 2 // always copy the options
|
||||||
#define BCO_NOHELP 4 // don't touch the help related options
|
#define BCO_NOHELP 4 // don't touch the help related options
|
||||||
|
|
||||||
|
#define MAX_NUMBERWIDTH 20 // used for 'numberwidth' and 'statuscolumn'
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "option.h.generated.h"
|
# include "option.h.generated.h"
|
||||||
#endif
|
#endif
|
||||||
|
@@ -337,6 +337,8 @@ enum {
|
|||||||
STL_ARGLISTSTAT = 'a', ///< Argument list status as (x of y).
|
STL_ARGLISTSTAT = 'a', ///< Argument list status as (x of y).
|
||||||
STL_PAGENUM = 'N', ///< Page number (when printing).
|
STL_PAGENUM = 'N', ///< Page number (when printing).
|
||||||
STL_SHOWCMD = 'S', ///< 'showcmd' buffer
|
STL_SHOWCMD = 'S', ///< 'showcmd' buffer
|
||||||
|
STL_FOLDCOL = 'C', ///< Fold column for 'statuscolumn'
|
||||||
|
STL_SIGNCOL = 's', ///< Sign column for 'statuscolumn'
|
||||||
STL_VIM_EXPR = '{', ///< Start of expression to substitute.
|
STL_VIM_EXPR = '{', ///< Start of expression to substitute.
|
||||||
STL_SEPARATE = '=', ///< Separation between alignment sections.
|
STL_SEPARATE = '=', ///< Separation between alignment sections.
|
||||||
STL_TRUNCMARK = '<', ///< Truncation mark if line is too long.
|
STL_TRUNCMARK = '<', ///< Truncation mark if line is too long.
|
||||||
@@ -354,8 +356,9 @@ enum {
|
|||||||
STL_HELPFLAG, STL_HELPFLAG_ALT, STL_FILETYPE, STL_FILETYPE_ALT, \
|
STL_HELPFLAG, STL_HELPFLAG_ALT, STL_FILETYPE, STL_FILETYPE_ALT, \
|
||||||
STL_PREVIEWFLAG, STL_PREVIEWFLAG_ALT, STL_MODIFIED, STL_MODIFIED_ALT, \
|
STL_PREVIEWFLAG, STL_PREVIEWFLAG_ALT, STL_MODIFIED, STL_MODIFIED_ALT, \
|
||||||
STL_QUICKFIX, STL_PERCENTAGE, STL_ALTPERCENT, STL_ARGLISTSTAT, STL_PAGENUM, \
|
STL_QUICKFIX, STL_PERCENTAGE, STL_ALTPERCENT, STL_ARGLISTSTAT, STL_PAGENUM, \
|
||||||
STL_SHOWCMD, STL_VIM_EXPR, STL_SEPARATE, STL_TRUNCMARK, STL_USER_HL, \
|
STL_SHOWCMD, STL_FOLDCOL, STL_SIGNCOL, STL_VIM_EXPR, STL_SEPARATE, \
|
||||||
STL_HIGHLIGHT, STL_TABPAGENR, STL_TABCLOSENR, STL_CLICK_FUNC, \
|
STL_TRUNCMARK, STL_USER_HL, STL_HIGHLIGHT, STL_TABPAGENR, STL_TABCLOSENR, \
|
||||||
|
STL_CLICK_FUNC, STL_TABPAGENR, STL_TABCLOSENR, STL_CLICK_FUNC, \
|
||||||
0, \
|
0, \
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -955,6 +958,7 @@ enum {
|
|||||||
WV_CULOPT,
|
WV_CULOPT,
|
||||||
WV_CC,
|
WV_CC,
|
||||||
WV_SBR,
|
WV_SBR,
|
||||||
|
WV_STC,
|
||||||
WV_STL,
|
WV_STL,
|
||||||
WV_WFH,
|
WV_WFH,
|
||||||
WV_WFW,
|
WV_WFW,
|
||||||
|
@@ -2297,6 +2297,15 @@ return {
|
|||||||
varname='p_sol',
|
varname='p_sol',
|
||||||
defaults={if_true=false}
|
defaults={if_true=false}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
full_name='statuscolumn', abbreviation='stc',
|
||||||
|
short_desc=N_("custom format for the status column"),
|
||||||
|
type='string', scope={'window'},
|
||||||
|
redraw={'current_window'},
|
||||||
|
secure=true,
|
||||||
|
alloced=true,
|
||||||
|
defaults={if_true=""}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
full_name='statusline', abbreviation='stl',
|
full_name='statusline', abbreviation='stl',
|
||||||
short_desc=N_("custom format for the status line"),
|
short_desc=N_("custom format for the status line"),
|
||||||
|
@@ -1177,12 +1177,14 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
|
|||||||
redraw_titles();
|
redraw_titles();
|
||||||
}
|
}
|
||||||
} else if (gvarp == &p_stl || gvarp == &p_wbr || varp == &p_tal
|
} else if (gvarp == &p_stl || gvarp == &p_wbr || varp == &p_tal
|
||||||
|| varp == &p_ruf) {
|
|| varp == &p_ruf || varp == &curwin->w_p_stc) {
|
||||||
// 'statusline', 'winbar', 'tabline' or 'rulerformat'
|
// 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn'
|
||||||
int wid;
|
int wid;
|
||||||
|
|
||||||
if (varp == &p_ruf) { // reset ru_wid first
|
if (varp == &p_ruf) { // reset ru_wid first
|
||||||
ru_wid = 0;
|
ru_wid = 0;
|
||||||
|
} else if (varp == &curwin->w_p_stc) {
|
||||||
|
curwin->w_nrwidth_line_count = 0;
|
||||||
}
|
}
|
||||||
s = *varp;
|
s = *varp;
|
||||||
if (varp == &p_ruf && *s == '%') {
|
if (varp == &p_ruf && *s == '%') {
|
||||||
@@ -1197,7 +1199,8 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
|
|||||||
errmsg = check_stl_option(p_ruf);
|
errmsg = check_stl_option(p_ruf);
|
||||||
}
|
}
|
||||||
} else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') {
|
} else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') {
|
||||||
// check 'statusline', 'winbar' or 'tabline' only if it doesn't start with "%!"
|
// check 'statusline', 'winbar', 'tabline' or 'statuscolumn'
|
||||||
|
// only if it doesn't start with "%!"
|
||||||
errmsg = check_stl_option(s);
|
errmsg = check_stl_option(s);
|
||||||
}
|
}
|
||||||
if (varp == &p_ruf && errmsg == NULL) {
|
if (varp == &p_ruf && errmsg == NULL) {
|
||||||
|
@@ -780,6 +780,16 @@ int number_width(win_T *wp)
|
|||||||
}
|
}
|
||||||
wp->w_nrwidth_line_count = lnum;
|
wp->w_nrwidth_line_count = lnum;
|
||||||
|
|
||||||
|
// make best estimate for 'statuscolumn'
|
||||||
|
if (*wp->w_p_stc != NUL) {
|
||||||
|
char buf[MAXPATHL];
|
||||||
|
wp->w_nrwidth_width = 0;
|
||||||
|
n = build_statuscol_str(wp, true, false, lnum, 0, 0, NUL, buf, NULL, NULL);
|
||||||
|
n = MAX(n, (wp->w_p_nu || wp->w_p_rnu) * (int)wp->w_p_nuw);
|
||||||
|
wp->w_nrwidth_width = MIN(n, MAX_NUMBERWIDTH);
|
||||||
|
return wp->w_nrwidth_width;
|
||||||
|
}
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
do {
|
do {
|
||||||
lnum /= 10;
|
lnum /= 10;
|
||||||
|
@@ -367,8 +367,9 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
|||||||
// Make a copy, because the statusline may include a function call that
|
// Make a copy, because the statusline may include a function call that
|
||||||
// might change the option value and free the memory.
|
// might change the option value and free the memory.
|
||||||
stl = xstrdup(stl);
|
stl = xstrdup(stl);
|
||||||
width = build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_name,
|
width = build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_name, opt_scope,
|
||||||
opt_scope, fillchar, maxwidth, &hltab, &tabtab);
|
fillchar, maxwidth, &hltab, &tabtab, NULL);
|
||||||
|
|
||||||
xfree(stl);
|
xfree(stl);
|
||||||
ewp->w_p_crb = p_crb_save;
|
ewp->w_p_crb = p_crb_save;
|
||||||
|
|
||||||
@@ -867,6 +868,32 @@ void draw_tabline(void)
|
|||||||
redraw_tabline = false;
|
redraw_tabline = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int build_statuscol_str(win_T *wp, bool setnum, bool wrap, linenr_T lnum, long relnum, int maxwidth,
|
||||||
|
int fillchar, char *buf, stl_hlrec_t **hlrec, statuscol_T *stcp)
|
||||||
|
{
|
||||||
|
if (setnum) {
|
||||||
|
set_vim_var_nr(VV_LNUM, lnum);
|
||||||
|
set_vim_var_nr(VV_RELNUM, relnum);
|
||||||
|
}
|
||||||
|
set_vim_var_bool(VV_WRAP, wrap);
|
||||||
|
|
||||||
|
StlClickRecord *clickrec;
|
||||||
|
char *stc = xstrdup(wp->w_p_stc);
|
||||||
|
int width = build_stl_str_hl(wp, buf, MAXPATHL, stc, "statuscolumn", OPT_LOCAL,
|
||||||
|
fillchar, maxwidth, hlrec, &clickrec, stcp);
|
||||||
|
xfree(stc);
|
||||||
|
|
||||||
|
// Allocate and fill click def array if width has changed
|
||||||
|
if (wp->w_status_click_defs_size != (size_t)width) {
|
||||||
|
stl_clear_click_defs(wp->w_statuscol_click_defs, wp->w_statuscol_click_defs_size);
|
||||||
|
wp->w_statuscol_click_defs = stl_alloc_click_defs(wp->w_statuscol_click_defs, width,
|
||||||
|
&wp->w_statuscol_click_defs_size);
|
||||||
|
stl_fill_click_defs(wp->w_statuscol_click_defs, clickrec, buf, width, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a string from the status line items in "fmt".
|
/// Build a string from the status line items in "fmt".
|
||||||
/// Return length of string in screen cells.
|
/// Return length of string in screen cells.
|
||||||
///
|
///
|
||||||
@@ -890,11 +917,13 @@ void draw_tabline(void)
|
|||||||
/// @param fillchar Character to use when filling empty space in the statusline
|
/// @param fillchar Character to use when filling empty space in the statusline
|
||||||
/// @param maxwidth The maximum width to make the statusline
|
/// @param maxwidth The maximum width to make the statusline
|
||||||
/// @param hltab HL attributes (can be NULL)
|
/// @param hltab HL attributes (can be NULL)
|
||||||
/// @param tabtab Tab clicks definition (can be NULL).
|
/// @param tabtab Tab clicks definition (can be NULL)
|
||||||
|
/// @param stcp Status column attributes (can be NULL)
|
||||||
///
|
///
|
||||||
/// @return The final width of the statusline
|
/// @return The final width of the statusline
|
||||||
int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_name, int opt_scope,
|
int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_name, int opt_scope,
|
||||||
int fillchar, int maxwidth, stl_hlrec_t **hltab, StlClickRecord **tabtab)
|
int fillchar, int maxwidth, stl_hlrec_t **hltab, StlClickRecord **tabtab,
|
||||||
|
statuscol_T *stcp)
|
||||||
{
|
{
|
||||||
static size_t stl_items_len = 20; // Initial value, grows as needed.
|
static size_t stl_items_len = 20; // Initial value, grows as needed.
|
||||||
static stl_item_t *stl_items = NULL;
|
static stl_item_t *stl_items = NULL;
|
||||||
@@ -1466,8 +1495,9 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
|
|||||||
}
|
}
|
||||||
|
|
||||||
case STL_LINE:
|
case STL_LINE:
|
||||||
num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY)
|
// Overload %l with v:lnum for 'statuscolumn'
|
||||||
? 0L : (long)(wp->w_cursor.lnum);
|
num = strcmp(opt_name, "statuscolumn") == 0 ? get_vim_var_nr(VV_LNUM)
|
||||||
|
: (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ? 0L : (long)(wp->w_cursor.lnum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STL_NUMLINES:
|
case STL_NUMLINES:
|
||||||
@@ -1565,9 +1595,14 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
|
|||||||
|
|
||||||
case STL_ROFLAG:
|
case STL_ROFLAG:
|
||||||
case STL_ROFLAG_ALT:
|
case STL_ROFLAG_ALT:
|
||||||
itemisflag = true;
|
// Overload %r with v:relnum for 'statuscolumn'
|
||||||
if (wp->w_buffer->b_p_ro) {
|
if (strcmp(opt_name, "statuscolumn") == 0) {
|
||||||
str = (opt == STL_ROFLAG_ALT) ? ",RO" : _("[RO]");
|
num = get_vim_var_nr(VV_RELNUM);
|
||||||
|
} else {
|
||||||
|
itemisflag = true;
|
||||||
|
if (wp->w_buffer->b_p_ro) {
|
||||||
|
str = (opt == STL_ROFLAG_ALT) ? ",RO" : _("[RO]");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1579,6 +1614,33 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case STL_FOLDCOL: // 'C' for 'statuscolumn'
|
||||||
|
case STL_SIGNCOL: { // 's' for 'statuscolumn'
|
||||||
|
if (stcp == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fold = opt == STL_FOLDCOL;
|
||||||
|
*buf_tmp = NUL;
|
||||||
|
for (int i = 0; i <= 9; i++) {
|
||||||
|
char *p = fold ? stcp->fold_text : stcp->sign_text[i];
|
||||||
|
if ((!p || !*p) && *buf_tmp == NUL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stl_items[curitem].type = Highlight;
|
||||||
|
stl_items[curitem].start = out_p + strlen(buf_tmp);
|
||||||
|
stl_items[curitem].minwid = !p || (fold && i) ? 0 : fold ? stcp->fold_attr
|
||||||
|
: stcp->sign_attr[i];
|
||||||
|
curitem++;
|
||||||
|
if (!p || (fold && i)) {
|
||||||
|
str = buf_tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
STRCAT(buf_tmp, p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case STL_FILETYPE:
|
case STL_FILETYPE:
|
||||||
// Copy the filetype if it is not null and the formatted string will fit
|
// Copy the filetype if it is not null and the formatted string will fit
|
||||||
// in the temporary buffer
|
// in the temporary buffer
|
||||||
@@ -1850,6 +1912,10 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
|
|||||||
// What follows is post-processing to handle alignment and highlighting.
|
// What follows is post-processing to handle alignment and highlighting.
|
||||||
|
|
||||||
int width = vim_strsize(out);
|
int width = vim_strsize(out);
|
||||||
|
// Return truncated width for 'statuscolumn'
|
||||||
|
if (stcp != NULL && width > maxwidth) {
|
||||||
|
stcp->truncate = width - maxwidth;
|
||||||
|
}
|
||||||
if (maxwidth > 0 && width > maxwidth) {
|
if (maxwidth > 0 && width > maxwidth) {
|
||||||
// Result is too long, must truncate somewhere.
|
// Result is too long, must truncate somewhere.
|
||||||
int item_idx = 0;
|
int item_idx = 0;
|
||||||
|
@@ -5094,6 +5094,9 @@ static void win_free(win_T *wp, tabpage_T *tp)
|
|||||||
stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size);
|
stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size);
|
||||||
xfree(wp->w_winbar_click_defs);
|
xfree(wp->w_winbar_click_defs);
|
||||||
|
|
||||||
|
stl_clear_click_defs(wp->w_statuscol_click_defs, wp->w_statuscol_click_defs_size);
|
||||||
|
xfree(wp->w_statuscol_click_defs);
|
||||||
|
|
||||||
// Remove the window from the b_wininfo lists, it may happen that the
|
// Remove the window from the b_wininfo lists, it may happen that the
|
||||||
// freed memory is re-used for another window.
|
// freed memory is re-used for another window.
|
||||||
FOR_ALL_BUFFERS(buf) {
|
FOR_ALL_BUFFERS(buf) {
|
||||||
|
@@ -29,6 +29,7 @@ describe('ffi.cdef', function()
|
|||||||
typedef struct window_S win_T;
|
typedef struct window_S win_T;
|
||||||
typedef struct {} stl_hlrec_t;
|
typedef struct {} stl_hlrec_t;
|
||||||
typedef struct {} StlClickRecord;
|
typedef struct {} StlClickRecord;
|
||||||
|
typedef struct {} statuscol_T;
|
||||||
typedef struct {} Error;
|
typedef struct {} Error;
|
||||||
|
|
||||||
win_T *find_window_by_handle(int Window, Error *err);
|
win_T *find_window_by_handle(int Window, Error *err);
|
||||||
@@ -43,7 +44,8 @@ describe('ffi.cdef', function()
|
|||||||
int fillchar,
|
int fillchar,
|
||||||
int maxwidth,
|
int maxwidth,
|
||||||
stl_hlrec_t **hltab,
|
stl_hlrec_t **hltab,
|
||||||
StlClickRecord **tabtab
|
StlClickRecord **tabtab,
|
||||||
|
statuscol_T *scp
|
||||||
);
|
);
|
||||||
]]
|
]]
|
||||||
|
|
||||||
@@ -57,6 +59,7 @@ describe('ffi.cdef', function()
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
nil,
|
nil,
|
||||||
|
nil,
|
||||||
nil
|
nil
|
||||||
)
|
)
|
||||||
]=])
|
]=])
|
||||||
|
273
test/functional/ui/statuscolumn_spec.lua
Normal file
273
test/functional/ui/statuscolumn_spec.lua
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
|
local Screen = require('test.functional.ui.screen')
|
||||||
|
local clear = helpers.clear
|
||||||
|
local command = helpers.command
|
||||||
|
local eq = helpers.eq
|
||||||
|
local eval = helpers.eval
|
||||||
|
local meths = helpers.meths
|
||||||
|
local pcall_err = helpers.pcall_err
|
||||||
|
|
||||||
|
describe('statuscolumn', function()
|
||||||
|
local screen
|
||||||
|
before_each(function()
|
||||||
|
clear('--cmd', 'set number nuw=1 | call setline(1, repeat(["aaaaa"], 16)) | norm GM')
|
||||||
|
screen = Screen.new()
|
||||||
|
screen:attach()
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('fails with invalid \'statuscolumn\'', function()
|
||||||
|
command('set stc=%{v:relnum?v:relnum:(v:lnum==5?invalid:v:lnum)}\\ ')
|
||||||
|
screen:expect([[
|
||||||
|
4 aaaaa |
|
||||||
|
3 aaaaa |
|
||||||
|
2 aaaaa |
|
||||||
|
1 aaaaa |
|
||||||
|
8 ^aaaaa |
|
||||||
|
1 aaaaa |
|
||||||
|
2 aaaaa |
|
||||||
|
3 aaaaa |
|
||||||
|
4 aaaaa |
|
||||||
|
5 aaaaa |
|
||||||
|
6 aaaaa |
|
||||||
|
7 aaaaa |
|
||||||
|
8 aaaaa |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
command('norm 5G')
|
||||||
|
eq('Vim(redraw):E121: Undefined variable: invalid', pcall_err(command, 'redraw!'))
|
||||||
|
eq('', eval('&statuscolumn'))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('widens with irregular \'statuscolumn\' width', function()
|
||||||
|
command('set stc=%{v:relnum?v:relnum:(v:lnum==5?\'bbbbb\':v:lnum)}')
|
||||||
|
command('norm 5G | redraw!')
|
||||||
|
screen:expect([[
|
||||||
|
1 aaaaa |
|
||||||
|
bbbbba^eaaa |
|
||||||
|
1 aaaaa |
|
||||||
|
2 aaaaa |
|
||||||
|
3 aaaaa |
|
||||||
|
4 aaaaa |
|
||||||
|
5 aaaaa |
|
||||||
|
6 aaaaa |
|
||||||
|
7 aaaaa |
|
||||||
|
8 aaaaa |
|
||||||
|
9 aaaaa |
|
||||||
|
10 aaaaa |
|
||||||
|
11 aaaaa |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works with \'statuscolumn\'', function()
|
||||||
|
command([[set stc=%{&nu?v:lnum:''}%=%{&rnu?'\ '.v:relnum:''}│]])
|
||||||
|
screen:expect([[
|
||||||
|
4 │aaaaa |
|
||||||
|
5 │aaaaa |
|
||||||
|
6 │aaaaa |
|
||||||
|
7 │aaaaa |
|
||||||
|
8 │^aaaaa |
|
||||||
|
9 │aaaaa |
|
||||||
|
10│aaaaa |
|
||||||
|
11│aaaaa |
|
||||||
|
12│aaaaa |
|
||||||
|
13│aaaaa |
|
||||||
|
14│aaaaa |
|
||||||
|
15│aaaaa |
|
||||||
|
16│aaaaa |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
command('set relativenumber')
|
||||||
|
screen:expect([[
|
||||||
|
4 4│aaaaa |
|
||||||
|
5 3│aaaaa |
|
||||||
|
6 2│aaaaa |
|
||||||
|
7 1│aaaaa |
|
||||||
|
8 0│^aaaaa |
|
||||||
|
9 1│aaaaa |
|
||||||
|
10 2│aaaaa |
|
||||||
|
11 3│aaaaa |
|
||||||
|
12 4│aaaaa |
|
||||||
|
13 5│aaaaa |
|
||||||
|
14 6│aaaaa |
|
||||||
|
15 7│aaaaa |
|
||||||
|
16 8│aaaaa |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
command('norm 12GH')
|
||||||
|
screen:expect([[
|
||||||
|
4 0│^aaaaa |
|
||||||
|
5 1│aaaaa |
|
||||||
|
6 2│aaaaa |
|
||||||
|
7 3│aaaaa |
|
||||||
|
8 4│aaaaa |
|
||||||
|
9 5│aaaaa |
|
||||||
|
10 6│aaaaa |
|
||||||
|
11 7│aaaaa |
|
||||||
|
12 8│aaaaa |
|
||||||
|
13 9│aaaaa |
|
||||||
|
14 10│aaaaa |
|
||||||
|
15 11│aaaaa |
|
||||||
|
16 12│aaaaa |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works with highlighted \'statuscolumn\'', function()
|
||||||
|
command([[set stc=%#NonText#%{&nu?v:lnum:''}]] ..
|
||||||
|
[[%=%{&rnu&&(v:lnum%2)?'\ '.v:relnum:''}]] ..
|
||||||
|
[[%#LineNr#%{&rnu&&!(v:lnum%2)?'\ '.v:relnum:''}│]])
|
||||||
|
screen:set_default_attr_ids({
|
||||||
|
[0] = {bold = true, foreground = Screen.colors.Blue},
|
||||||
|
[1] = {foreground = Screen.colors.Brown},
|
||||||
|
})
|
||||||
|
screen:expect([[
|
||||||
|
{0:4 }{1:│}aaaaa |
|
||||||
|
{0:5 }{1:│}aaaaa |
|
||||||
|
{0:6 }{1:│}aaaaa |
|
||||||
|
{0:7 }{1:│}aaaaa |
|
||||||
|
{0:8 }{1:│}^aaaaa |
|
||||||
|
{0:9 }{1:│}aaaaa |
|
||||||
|
{0:10}{1:│}aaaaa |
|
||||||
|
{0:11}{1:│}aaaaa |
|
||||||
|
{0:12}{1:│}aaaaa |
|
||||||
|
{0:13}{1:│}aaaaa |
|
||||||
|
{0:14}{1:│}aaaaa |
|
||||||
|
{0:15}{1:│}aaaaa |
|
||||||
|
{0:16}{1:│}aaaaa |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
command('set relativenumber')
|
||||||
|
screen:expect([[
|
||||||
|
{0:4 }{1: 4│}aaaaa |
|
||||||
|
{0:5 3}{1:│}aaaaa |
|
||||||
|
{0:6 }{1: 2│}aaaaa |
|
||||||
|
{0:7 1}{1:│}aaaaa |
|
||||||
|
{0:8 }{1: 0│}^aaaaa |
|
||||||
|
{0:9 1}{1:│}aaaaa |
|
||||||
|
{0:10}{1: 2│}aaaaa |
|
||||||
|
{0:11 3}{1:│}aaaaa |
|
||||||
|
{0:12}{1: 4│}aaaaa |
|
||||||
|
{0:13 5}{1:│}aaaaa |
|
||||||
|
{0:14}{1: 6│}aaaaa |
|
||||||
|
{0:15 7}{1:│}aaaaa |
|
||||||
|
{0:16}{1: 8│}aaaaa |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
command('set nonumber')
|
||||||
|
screen:expect([[
|
||||||
|
{1:4│}aaaaa |
|
||||||
|
{0:3}{1:│}aaaaa |
|
||||||
|
{1:2│}aaaaa |
|
||||||
|
{0:1}{1:│}aaaaa |
|
||||||
|
{1:0│}^aaaaa |
|
||||||
|
{0:1}{1:│}aaaaa |
|
||||||
|
{1:2│}aaaaa |
|
||||||
|
{0:3}{1:│}aaaaa |
|
||||||
|
{1:4│}aaaaa |
|
||||||
|
{0:5}{1:│}aaaaa |
|
||||||
|
{1:6│}aaaaa |
|
||||||
|
{0:7}{1:│}aaaaa |
|
||||||
|
{1:8│}aaaaa |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works with wrapped lines, signs and folds', function()
|
||||||
|
command("set stc=%C%s%=%{v:wrap?'':v:lnum}│\\ ")
|
||||||
|
command("call setline(1,repeat([repeat('aaaaa',10)],16))")
|
||||||
|
screen:set_default_attr_ids({
|
||||||
|
[0] = {bold = true, foreground = Screen.colors.Blue},
|
||||||
|
[1] = {foreground = Screen.colors.Brown},
|
||||||
|
[2] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGrey},
|
||||||
|
[3] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey},
|
||||||
|
})
|
||||||
|
screen:expect([[
|
||||||
|
{1: 4│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{1: │ }a |
|
||||||
|
{1: 5│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{1: │ }a |
|
||||||
|
{1: 6│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{1: │ }a |
|
||||||
|
{1: 7│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{1: │ }a |
|
||||||
|
{1: 8│ }^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{1: │ }a |
|
||||||
|
{1: 9│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{1: │ }a |
|
||||||
|
{1:10│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{0:@@@}|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
command('set signcolumn=auto:2 foldcolumn=auto')
|
||||||
|
command('sign define piet1 text=>> texthl=LineNr')
|
||||||
|
command('sign define piet2 text=>! texthl=NonText')
|
||||||
|
command('sign place 1 line=4 name=piet1 buffer=1')
|
||||||
|
command('sign place 2 line=5 name=piet2 buffer=1')
|
||||||
|
command('sign place 3 line=6 name=piet1 buffer=1')
|
||||||
|
command('sign place 4 line=6 name=piet2 buffer=1')
|
||||||
|
screen:expect([[
|
||||||
|
{1:>> 4│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{1: │ }aaaaa |
|
||||||
|
{0:>!}{1: 5│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{1: │ }aaaaa |
|
||||||
|
{1:>>}{0:>!}{1: 6│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{1: │ }aaaaa |
|
||||||
|
{1: 7│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{1: │ }aaaaa |
|
||||||
|
{1: 8│ }^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{1: │ }aaaaa |
|
||||||
|
{1: 9│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{1: │ }aaaaa |
|
||||||
|
{1: 10│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{0:@@@}|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
command('norm zf$')
|
||||||
|
-- Check that alignment works properly with signs after %=
|
||||||
|
command("set stc=%C%=%{v:wrap?'':v:lnum}│%s\\ ")
|
||||||
|
screen:expect([[
|
||||||
|
{2: }{1: 4│>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{2: }{1: │ }aaaaaa |
|
||||||
|
{2: }{1: 5│}{0:>!}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{2: }{1: │ }aaaaaa |
|
||||||
|
{2: }{1: 6│>>}{0:>!}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{2: }{1: │ }aaaaaa |
|
||||||
|
{2: }{1: 7│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{2: }{1: │ }aaaaaa |
|
||||||
|
{2:+}{1: 8│ }{3:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
|
||||||
|
{2: }{1: 9│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{2: }{1: │ }aaaaaa |
|
||||||
|
{2: }{1:10│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{2: }{1: │ }aaaaaa |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works with \'statuscolumn\' clicks', function()
|
||||||
|
command('set mousemodel=extend')
|
||||||
|
command([[
|
||||||
|
function! MyClickFunc(minwid, clicks, button, mods)
|
||||||
|
let g:testvar = printf("%d %d %s %d", a:minwid, a:clicks, a:button, getmousepos().line)
|
||||||
|
if a:mods !=# ' '
|
||||||
|
let g:testvar ..= '(' .. a:mods .. ')'
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
set stc=%0@MyClickFunc@%=%l%T
|
||||||
|
]])
|
||||||
|
meths.input_mouse('left', 'press', '', 0, 0, 0)
|
||||||
|
eq('0 1 l 4', eval("g:testvar"))
|
||||||
|
meths.input_mouse('left', 'press', '', 0, 0, 0)
|
||||||
|
eq('0 2 l 4', eval("g:testvar"))
|
||||||
|
meths.input_mouse('left', 'press', '', 0, 0, 0)
|
||||||
|
eq('0 3 l 4', eval("g:testvar"))
|
||||||
|
meths.input_mouse('left', 'press', '', 0, 0, 0)
|
||||||
|
eq('0 4 l 4', eval("g:testvar"))
|
||||||
|
meths.input_mouse('right', 'press', '', 0, 3, 0)
|
||||||
|
eq('0 1 r 7', eval("g:testvar"))
|
||||||
|
meths.input_mouse('right', 'press', '', 0, 3, 0)
|
||||||
|
eq('0 2 r 7', eval("g:testvar"))
|
||||||
|
meths.input_mouse('right', 'press', '', 0, 3, 0)
|
||||||
|
eq('0 3 r 7', eval("g:testvar"))
|
||||||
|
meths.input_mouse('right', 'press', '', 0, 3, 0)
|
||||||
|
eq('0 4 r 7', eval("g:testvar"))
|
||||||
|
end)
|
||||||
|
end)
|
@@ -238,6 +238,7 @@ describe('buffer functions', function()
|
|||||||
fillchar,
|
fillchar,
|
||||||
maximum_cell_count,
|
maximum_cell_count,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL)
|
NULL)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user