mirror of
https://github.com/neovim/neovim.git
synced 2025-09-28 22:18:33 +00:00
feat: click support for 'statusline', 'winbar' #18650
The mouseclick item "%@" is now supported by 'statusline' and 'winbar'. Previously it was only supported by 'tabline'.
This commit is contained in:
@@ -6009,7 +6009,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
the label, e.g.: %3Xclose%X. Use %999X for a "close current
|
the label, e.g.: %3Xclose%X. Use %999X for a "close current
|
||||||
tab" label. Clicking this label with left mouse button closes
|
tab" label. Clicking this label with left mouse button closes
|
||||||
specified tab page.
|
specified tab page.
|
||||||
@ N For 'tabline': start of execute function label. Use %X or %T to
|
@ N Start of execute function label. Use %X or %T to
|
||||||
end the label, e.g.: %10@SwitchBuffer@foo.c%X. Clicking this
|
end the label, e.g.: %10@SwitchBuffer@foo.c%X. Clicking this
|
||||||
label runs specified function: in the example when clicking once
|
label runs specified function: in the example when clicking once
|
||||||
using left mouse button on "foo.c" "SwitchBuffer(10, 1, 'l',
|
using left mouse button on "foo.c" "SwitchBuffer(10, 1, 'l',
|
||||||
@@ -6033,8 +6033,6 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
is a bug that denotes that new mouse button recognition was
|
is a bug that denotes that new mouse button recognition was
|
||||||
added without modifying code that reacts on mouse clicks on
|
added without modifying code that reacts on mouse clicks on
|
||||||
this label.
|
this label.
|
||||||
Note: to test whether your version of Neovim contains this
|
|
||||||
feature use `has('tablineat')`.
|
|
||||||
< - Where to truncate line if too long. Default is at the start.
|
< - Where to truncate line if too long. Default is at the start.
|
||||||
No width fields allowed.
|
No width fields allowed.
|
||||||
= - Separation point between alignment sections. Each section will
|
= - Separation point between alignment sections. Each section will
|
||||||
|
@@ -6,6 +6,8 @@
|
|||||||
// for FILE
|
// for FILE
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "grid_defs.h"
|
||||||
|
|
||||||
typedef struct file_buffer buf_T; // Forward declaration
|
typedef struct file_buffer buf_T; // Forward declaration
|
||||||
|
|
||||||
// Reference to a buffer that stores the value of buf_free_count.
|
// Reference to a buffer that stores the value of buf_free_count.
|
||||||
@@ -1492,6 +1494,16 @@ struct window_S {
|
|||||||
// Location list reference used in the location list window.
|
// Location list reference used in the location list window.
|
||||||
// In a non-location list window, w_llist_ref is NULL.
|
// In a non-location list window, w_llist_ref is NULL.
|
||||||
qf_info_T *w_llist_ref;
|
qf_info_T *w_llist_ref;
|
||||||
|
|
||||||
|
// Status line click definitions
|
||||||
|
StlClickDefinition *w_status_click_defs;
|
||||||
|
// Size of the w_status_click_defs array
|
||||||
|
size_t w_status_click_defs_size;
|
||||||
|
|
||||||
|
// Window bar click definitions
|
||||||
|
StlClickDefinition *w_winbar_click_defs;
|
||||||
|
// Size of the w_winbar_click_defs array
|
||||||
|
size_t w_winbar_click_defs_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int win_hl_attr(win_T *wp, int hlf)
|
static inline int win_hl_attr(win_T *wp, int hlf)
|
||||||
|
@@ -111,4 +111,22 @@ struct ScreenGrid {
|
|||||||
false, 0, 0, NULL, false, true, 0, \
|
false, 0, 0, NULL, false, true, 0, \
|
||||||
0, 0, 0, 0, 0, false }
|
0, 0, 0, 0, 0, false }
|
||||||
|
|
||||||
|
/// Status line click definition
|
||||||
|
typedef struct {
|
||||||
|
enum {
|
||||||
|
kStlClickDisabled = 0, ///< Clicks to this area are ignored.
|
||||||
|
kStlClickTabSwitch, ///< Switch to the given tab.
|
||||||
|
kStlClickTabClose, ///< Close given tab.
|
||||||
|
kStlClickFuncRun, ///< Run user function.
|
||||||
|
} type; ///< Type of the click.
|
||||||
|
int tabnr; ///< Tab page number.
|
||||||
|
char *func; ///< Function to run.
|
||||||
|
} StlClickDefinition;
|
||||||
|
|
||||||
|
/// Used for tabline clicks
|
||||||
|
typedef struct {
|
||||||
|
StlClickDefinition def; ///< Click definition.
|
||||||
|
const char *start; ///< Location where region starts.
|
||||||
|
} StlClickRecord;
|
||||||
|
|
||||||
#endif // NVIM_GRID_DEFS_H
|
#endif // NVIM_GRID_DEFS_H
|
||||||
|
@@ -241,8 +241,8 @@ retnomove:
|
|||||||
}
|
}
|
||||||
|
|
||||||
curwin->w_cursor.lnum = curwin->w_topline;
|
curwin->w_cursor.lnum = curwin->w_topline;
|
||||||
} else if (on_status_line && which_button == MOUSE_LEFT) {
|
} else if (on_status_line) {
|
||||||
if (dragwin != NULL) {
|
if (which_button == MOUSE_LEFT && dragwin != NULL) {
|
||||||
// Drag the status line
|
// Drag the status line
|
||||||
count = row - dragwin->w_winrow - dragwin->w_height + 1
|
count = row - dragwin->w_winrow - dragwin->w_height + 1
|
||||||
- on_status_line;
|
- on_status_line;
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include "nvim/fold.h"
|
#include "nvim/fold.h"
|
||||||
#include "nvim/getchar.h"
|
#include "nvim/getchar.h"
|
||||||
#include "nvim/globals.h"
|
#include "nvim/globals.h"
|
||||||
|
#include "nvim/grid_defs.h"
|
||||||
#include "nvim/indent.h"
|
#include "nvim/indent.h"
|
||||||
#include "nvim/keycodes.h"
|
#include "nvim/keycodes.h"
|
||||||
#include "nvim/log.h"
|
#include "nvim/log.h"
|
||||||
@@ -1432,6 +1433,63 @@ static void move_tab_to_mouse(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Call click definition function for column "col" in the "click_defs" array for button
|
||||||
|
/// "which_button".
|
||||||
|
static void call_click_def_func(StlClickDefinition *click_defs, int col, int which_button)
|
||||||
|
{
|
||||||
|
typval_T argv[] = {
|
||||||
|
{
|
||||||
|
.v_lock = VAR_FIXED,
|
||||||
|
.v_type = VAR_NUMBER,
|
||||||
|
.vval = {
|
||||||
|
.v_number = (varnumber_T)click_defs[col].tabnr
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.v_lock = VAR_FIXED,
|
||||||
|
.v_type = VAR_NUMBER,
|
||||||
|
.vval = {
|
||||||
|
.v_number = ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK
|
||||||
|
? 4
|
||||||
|
: ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK
|
||||||
|
? 3
|
||||||
|
: ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK
|
||||||
|
? 2
|
||||||
|
: 1)))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.v_lock = VAR_FIXED,
|
||||||
|
.v_type = VAR_STRING,
|
||||||
|
.vval = {
|
||||||
|
.v_string = (which_button == MOUSE_LEFT
|
||||||
|
? "l"
|
||||||
|
: (which_button == MOUSE_RIGHT
|
||||||
|
? "r"
|
||||||
|
: (which_button == MOUSE_MIDDLE
|
||||||
|
? "m"
|
||||||
|
: "?")))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.v_lock = VAR_FIXED,
|
||||||
|
.v_type = VAR_STRING,
|
||||||
|
.vval = {
|
||||||
|
.v_string = (char[]) {
|
||||||
|
(char)(mod_mask & MOD_MASK_SHIFT ? 's' : ' '),
|
||||||
|
(char)(mod_mask & MOD_MASK_CTRL ? 'c' : ' '),
|
||||||
|
(char)(mod_mask & MOD_MASK_ALT ? 'a' : ' '),
|
||||||
|
(char)(mod_mask & MOD_MASK_META ? 'm' : ' '),
|
||||||
|
NUL
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
typval_T rettv;
|
||||||
|
(void)call_vim_function(click_defs[col].func, ARRAY_SIZE(argv), argv, &rettv);
|
||||||
|
tv_clear(&rettv);
|
||||||
|
}
|
||||||
|
|
||||||
/// Do the appropriate action for the current mouse click in the current mode.
|
/// Do the appropriate action for the current mouse click in the current mode.
|
||||||
/// Not used for Command-line mode.
|
/// Not used for Command-line mode.
|
||||||
///
|
///
|
||||||
@@ -1481,6 +1539,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
|
|||||||
int jump_flags = 0; // flags for jump_to_mouse()
|
int jump_flags = 0; // flags for jump_to_mouse()
|
||||||
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_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
|
||||||
@@ -1711,66 +1770,10 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case kStlClickFuncRun: {
|
case kStlClickFuncRun:
|
||||||
typval_T argv[] = {
|
call_click_def_func(tab_page_click_defs, mouse_col, which_button);
|
||||||
{
|
|
||||||
.v_lock = VAR_FIXED,
|
|
||||||
.v_type = VAR_NUMBER,
|
|
||||||
.vval = {
|
|
||||||
.v_number = (varnumber_T)tab_page_click_defs[mouse_col].tabnr
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.v_lock = VAR_FIXED,
|
|
||||||
.v_type = VAR_NUMBER,
|
|
||||||
.vval = {
|
|
||||||
.v_number = ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK
|
|
||||||
? 4
|
|
||||||
: ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK
|
|
||||||
? 3
|
|
||||||
: ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK
|
|
||||||
? 2
|
|
||||||
: 1)))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.v_lock = VAR_FIXED,
|
|
||||||
.v_type = VAR_STRING,
|
|
||||||
.vval = {
|
|
||||||
.v_string = (which_button == MOUSE_LEFT
|
|
||||||
? "l"
|
|
||||||
: (which_button == MOUSE_RIGHT
|
|
||||||
? "r"
|
|
||||||
: (which_button == MOUSE_MIDDLE
|
|
||||||
? "m"
|
|
||||||
: "?")))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.v_lock = VAR_FIXED,
|
|
||||||
.v_type = VAR_STRING,
|
|
||||||
.vval = {
|
|
||||||
.v_string = (char[]) {
|
|
||||||
(char)(mod_mask & MOD_MASK_SHIFT ? 's' : ' '),
|
|
||||||
(char)(mod_mask & MOD_MASK_CTRL ? 'c' : ' '),
|
|
||||||
(char)(mod_mask & MOD_MASK_ALT ? 'a' : ' '),
|
|
||||||
(char)(mod_mask & MOD_MASK_META ? 'm' : ' '),
|
|
||||||
NUL
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
typval_T rettv;
|
|
||||||
funcexe_T funcexe = FUNCEXE_INIT;
|
|
||||||
funcexe.firstline = curwin->w_cursor.lnum;
|
|
||||||
funcexe.lastline = curwin->w_cursor.lnum;
|
|
||||||
funcexe.evaluate = true;
|
|
||||||
(void)call_func(tab_page_click_defs[mouse_col].func, -1,
|
|
||||||
&rettv, ARRAY_SIZE(argv), argv, &funcexe);
|
|
||||||
tv_clear(&rettv);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (is_drag && in_tab_line) {
|
} else if (is_drag && in_tab_line) {
|
||||||
@@ -1840,15 +1843,39 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
|
|||||||
oap == NULL ? NULL : &(oap->inclusive),
|
oap == NULL ? NULL : &(oap->inclusive),
|
||||||
which_button);
|
which_button);
|
||||||
|
|
||||||
// A click in the window bar has no side effects.
|
|
||||||
if (jump_flags & MOUSE_WINBAR) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
moved = (jump_flags & CURSOR_MOVED);
|
moved = (jump_flags & CURSOR_MOVED);
|
||||||
|
in_winbar = (jump_flags & MOUSE_WINBAR);
|
||||||
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) {
|
||||||
|
// Handle click event on window bar or status lin
|
||||||
|
int click_grid = mouse_grid;
|
||||||
|
int click_row = mouse_row;
|
||||||
|
int click_col = mouse_col;
|
||||||
|
win_T *wp = mouse_find_win(&click_grid, &click_row, &click_col);
|
||||||
|
|
||||||
|
StlClickDefinition *click_defs = in_status_line ? wp->w_status_click_defs
|
||||||
|
: wp->w_winbar_click_defs;
|
||||||
|
|
||||||
|
if (click_defs != NULL) {
|
||||||
|
switch (click_defs[click_col].type) {
|
||||||
|
case kStlClickDisabled:
|
||||||
|
break;
|
||||||
|
case kStlClickFuncRun:
|
||||||
|
call_click_def_func(click_defs, click_col, which_button);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false && "winbar and statusline only support %@ for clicks");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} else if (in_winbar) {
|
||||||
|
// A drag or release event in the window bar has no side effects.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// When jumping to another window, clear a pending operator. That's a bit
|
// When jumping to another window, clear a pending operator. That's a bit
|
||||||
// friendlier than beeping and not jumping to that window.
|
// friendlier than beeping and not jumping to that window.
|
||||||
|
@@ -88,6 +88,7 @@
|
|||||||
#include "nvim/fold.h"
|
#include "nvim/fold.h"
|
||||||
#include "nvim/garray.h"
|
#include "nvim/garray.h"
|
||||||
#include "nvim/getchar.h"
|
#include "nvim/getchar.h"
|
||||||
|
#include "nvim/grid_defs.h"
|
||||||
#include "nvim/highlight.h"
|
#include "nvim/highlight.h"
|
||||||
#include "nvim/highlight_group.h"
|
#include "nvim/highlight_group.h"
|
||||||
#include "nvim/indent.h"
|
#include "nvim/indent.h"
|
||||||
@@ -5337,11 +5338,27 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
|||||||
attr = (wp == curwin) ? HL_ATTR(HLF_WBR) : HL_ATTR(HLF_WBRNC);
|
attr = (wp == curwin) ? HL_ATTR(HLF_WBR) : HL_ATTR(HLF_WBRNC);
|
||||||
maxwidth = wp->w_width_inner;
|
maxwidth = wp->w_width_inner;
|
||||||
use_sandbox = was_set_insecurely(wp, "winbar", 0);
|
use_sandbox = was_set_insecurely(wp, "winbar", 0);
|
||||||
|
|
||||||
|
stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size);
|
||||||
|
// Allocate / resize the click definitions array for winbar if needed.
|
||||||
|
if (wp->w_winbar_height && wp->w_winbar_click_defs_size < (size_t)maxwidth) {
|
||||||
|
xfree(wp->w_winbar_click_defs);
|
||||||
|
wp->w_winbar_click_defs_size = (size_t)maxwidth;
|
||||||
|
wp->w_winbar_click_defs = xcalloc(wp->w_winbar_click_defs_size, sizeof(StlClickRecord));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
row = is_stl_global ? (Rows - p_ch - 1) : W_ENDROW(wp);
|
row = is_stl_global ? (Rows - p_ch - 1) : W_ENDROW(wp);
|
||||||
fillchar = fillchar_status(&attr, wp);
|
fillchar = fillchar_status(&attr, wp);
|
||||||
maxwidth = is_stl_global ? Columns : wp->w_width;
|
maxwidth = is_stl_global ? Columns : wp->w_width;
|
||||||
|
|
||||||
|
stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size);
|
||||||
|
// Allocate / resize the click definitions array for statusline if needed.
|
||||||
|
if (wp->w_status_click_defs_size < (size_t)maxwidth) {
|
||||||
|
xfree(wp->w_status_click_defs);
|
||||||
|
wp->w_status_click_defs_size = maxwidth;
|
||||||
|
wp->w_status_click_defs = xcalloc(wp->w_status_click_defs_size, sizeof(StlClickRecord));
|
||||||
|
}
|
||||||
|
|
||||||
if (draw_ruler) {
|
if (draw_ruler) {
|
||||||
stl = p_ruf;
|
stl = p_ruf;
|
||||||
// advance past any leading group spec - implicit in ru_col
|
// advance past any leading group spec - implicit in ru_col
|
||||||
@@ -5445,26 +5462,38 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
|||||||
|
|
||||||
grid_puts_line_flush(false);
|
grid_puts_line_flush(false);
|
||||||
|
|
||||||
if (wp == NULL) {
|
// Fill the tab_page_click_defs, w_status_click_defs or w_winbar_click_defs array for clicking
|
||||||
// Fill the tab_page_click_defs array for clicking in the tab pages line.
|
// in the tab page line, status line or window bar
|
||||||
col = 0;
|
StlClickDefinition *click_defs = (wp == NULL) ? tab_page_click_defs
|
||||||
len = 0;
|
: draw_winbar ? wp->w_winbar_click_defs
|
||||||
p = buf;
|
: wp->w_status_click_defs;
|
||||||
StlClickDefinition cur_click_def = {
|
|
||||||
.type = kStlClickDisabled,
|
if (click_defs == NULL) {
|
||||||
};
|
goto theend;
|
||||||
for (n = 0; tabtab[n].start != NULL; n++) {
|
}
|
||||||
len += vim_strnsize(p, (int)(tabtab[n].start - (char *)p));
|
|
||||||
while (col < len) {
|
col = 0;
|
||||||
tab_page_click_defs[col++] = cur_click_def;
|
len = 0;
|
||||||
}
|
p = buf;
|
||||||
p = (char_u *)tabtab[n].start;
|
StlClickDefinition cur_click_def = {
|
||||||
cur_click_def = tabtab[n].def;
|
.type = kStlClickDisabled,
|
||||||
|
};
|
||||||
|
for (n = 0; tabtab[n].start != NULL; n++) {
|
||||||
|
len += vim_strnsize(p, (int)(tabtab[n].start - (char *)p));
|
||||||
|
while (col < len) {
|
||||||
|
click_defs[col++] = cur_click_def;
|
||||||
}
|
}
|
||||||
while (col < Columns) {
|
p = (char_u *)tabtab[n].start;
|
||||||
tab_page_click_defs[col++] = cur_click_def;
|
cur_click_def = tabtab[n].def;
|
||||||
|
if ((wp != NULL) && !(cur_click_def.type == kStlClickDisabled
|
||||||
|
|| cur_click_def.type == kStlClickFuncRun)) {
|
||||||
|
// window bar and status line only support click functions
|
||||||
|
cur_click_def.type = kStlClickDisabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
while (col < maxwidth) {
|
||||||
|
click_defs[col++] = cur_click_def;
|
||||||
|
}
|
||||||
|
|
||||||
theend:
|
theend:
|
||||||
entered = false;
|
entered = false;
|
||||||
@@ -5572,7 +5601,6 @@ void check_for_delay(bool check_msg_scroll)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Resize the screen to Rows and Columns.
|
/// Resize the screen to Rows and Columns.
|
||||||
///
|
///
|
||||||
/// Allocate default_grid.chars[] and other grid arrays.
|
/// Allocate default_grid.chars[] and other grid arrays.
|
||||||
@@ -5641,7 +5669,7 @@ retry:
|
|||||||
StlClickDefinition *new_tab_page_click_defs =
|
StlClickDefinition *new_tab_page_click_defs =
|
||||||
xcalloc((size_t)Columns, sizeof(*new_tab_page_click_defs));
|
xcalloc((size_t)Columns, sizeof(*new_tab_page_click_defs));
|
||||||
|
|
||||||
clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size);
|
stl_clear_click_defs(tab_page_click_defs, tab_page_click_defs_size);
|
||||||
xfree(tab_page_click_defs);
|
xfree(tab_page_click_defs);
|
||||||
|
|
||||||
tab_page_click_defs = new_tab_page_click_defs;
|
tab_page_click_defs = new_tab_page_click_defs;
|
||||||
@@ -5672,19 +5700,19 @@ retry:
|
|||||||
resizing = false;
|
resizing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear tab_page_click_defs table
|
/// Clear status line, window bar or tab page line click definition table
|
||||||
///
|
///
|
||||||
/// @param[out] tpcd Table to clear.
|
/// @param[out] tpcd Table to clear.
|
||||||
/// @param[in] tpcd_size Size of the table.
|
/// @param[in] tpcd_size Size of the table.
|
||||||
void clear_tab_page_click_defs(StlClickDefinition *const tpcd, const long tpcd_size)
|
void stl_clear_click_defs(StlClickDefinition *const click_defs, const long click_defs_size)
|
||||||
{
|
{
|
||||||
if (tpcd != NULL) {
|
if (click_defs != NULL) {
|
||||||
for (long i = 0; i < tpcd_size; i++) {
|
for (long i = 0; i < click_defs_size; i++) {
|
||||||
if (i == 0 || tpcd[i].func != tpcd[i - 1].func) {
|
if (i == 0 || click_defs[i].func != click_defs[i - 1].func) {
|
||||||
xfree(tpcd[i].func);
|
xfree(click_defs[i].func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memset(tpcd, 0, (size_t)tpcd_size * sizeof(tpcd[0]));
|
memset(click_defs, 0, (size_t)click_defs_size * sizeof(click_defs[0]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6200,7 +6228,7 @@ void draw_tabline(void)
|
|||||||
|
|
||||||
// Init TabPageIdxs[] to zero: Clicking outside of tabs has no effect.
|
// Init TabPageIdxs[] to zero: Clicking outside of tabs has no effect.
|
||||||
assert(Columns == tab_page_click_defs_size);
|
assert(Columns == tab_page_click_defs_size);
|
||||||
clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size);
|
stl_clear_click_defs(tab_page_click_defs, tab_page_click_defs_size);
|
||||||
|
|
||||||
// Use the 'tabline' option if it's set.
|
// Use the 'tabline' option if it's set.
|
||||||
if (*p_tal != NUL) {
|
if (*p_tal != NUL) {
|
||||||
|
@@ -30,24 +30,6 @@ typedef enum {
|
|||||||
// Maximum columns for terminal highlight attributes
|
// Maximum columns for terminal highlight attributes
|
||||||
#define TERM_ATTRS_MAX 1024
|
#define TERM_ATTRS_MAX 1024
|
||||||
|
|
||||||
/// Status line click definition
|
|
||||||
typedef struct {
|
|
||||||
enum {
|
|
||||||
kStlClickDisabled = 0, ///< Clicks to this area are ignored.
|
|
||||||
kStlClickTabSwitch, ///< Switch to the given tab.
|
|
||||||
kStlClickTabClose, ///< Close given tab.
|
|
||||||
kStlClickFuncRun, ///< Run user function.
|
|
||||||
} type; ///< Type of the click.
|
|
||||||
int tabnr; ///< Tab page number.
|
|
||||||
char *func; ///< Function to run.
|
|
||||||
} StlClickDefinition;
|
|
||||||
|
|
||||||
/// Used for tabline clicks
|
|
||||||
typedef struct {
|
|
||||||
StlClickDefinition def; ///< Click definition.
|
|
||||||
const char *start; ///< Location where region starts.
|
|
||||||
} StlClickRecord;
|
|
||||||
|
|
||||||
/// Array defining what should be done when tabline is clicked
|
/// Array defining what should be done when tabline is clicked
|
||||||
EXTERN StlClickDefinition *tab_page_click_defs INIT(= NULL);
|
EXTERN StlClickDefinition *tab_page_click_defs INIT(= NULL);
|
||||||
|
|
||||||
|
@@ -5119,6 +5119,12 @@ static void win_free(win_T *wp, tabpage_T *tp)
|
|||||||
xfree(wp->w_localdir);
|
xfree(wp->w_localdir);
|
||||||
xfree(wp->w_prevdir);
|
xfree(wp->w_prevdir);
|
||||||
|
|
||||||
|
stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size);
|
||||||
|
xfree(wp->w_status_click_defs);
|
||||||
|
|
||||||
|
stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size);
|
||||||
|
xfree(wp->w_winbar_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) {
|
||||||
@@ -6612,6 +6618,23 @@ void last_status(bool morewin)
|
|||||||
global_stl_height() > 0);
|
global_stl_height() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove status line from window, replacing it with a horizontal separator if needed.
|
||||||
|
static void win_remove_status_line(win_T *wp, bool add_hsep)
|
||||||
|
{
|
||||||
|
wp->w_status_height = 0;
|
||||||
|
if (add_hsep) {
|
||||||
|
wp->w_hsep_height = 1;
|
||||||
|
} else {
|
||||||
|
win_new_height(wp, wp->w_height + STATUS_HEIGHT);
|
||||||
|
}
|
||||||
|
comp_col();
|
||||||
|
|
||||||
|
stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size);
|
||||||
|
xfree(wp->w_status_click_defs);
|
||||||
|
wp->w_status_click_defs_size = 0;
|
||||||
|
wp->w_status_click_defs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Look for resizable frames and take lines from them to make room for the statusline
|
// Look for resizable frames and take lines from them to make room for the statusline
|
||||||
static void resize_frame_for_status(frame_T *fr)
|
static void resize_frame_for_status(frame_T *fr)
|
||||||
{
|
{
|
||||||
@@ -6652,10 +6675,7 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
|
|||||||
|
|
||||||
if (is_last) {
|
if (is_last) {
|
||||||
if (wp->w_status_height != 0 && (!statusline || is_stl_global)) {
|
if (wp->w_status_height != 0 && (!statusline || is_stl_global)) {
|
||||||
// Remove status line
|
win_remove_status_line(wp, false);
|
||||||
wp->w_status_height = 0;
|
|
||||||
win_new_height(wp, wp->w_height + STATUS_HEIGHT);
|
|
||||||
comp_col();
|
|
||||||
} else if (wp->w_status_height == 0 && !is_stl_global && statusline) {
|
} else if (wp->w_status_height == 0 && !is_stl_global && statusline) {
|
||||||
// Add statusline to window if needed
|
// Add statusline to window if needed
|
||||||
wp->w_status_height = STATUS_HEIGHT;
|
wp->w_status_height = STATUS_HEIGHT;
|
||||||
@@ -6665,9 +6685,7 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
|
|||||||
} else if (wp->w_status_height != 0 && is_stl_global) {
|
} else if (wp->w_status_height != 0 && is_stl_global) {
|
||||||
// If statusline is global and the window has a statusline, replace it with a horizontal
|
// If statusline is global and the window has a statusline, replace it with a horizontal
|
||||||
// separator
|
// separator
|
||||||
wp->w_status_height = 0;
|
win_remove_status_line(wp, true);
|
||||||
wp->w_hsep_height = 1;
|
|
||||||
comp_col();
|
|
||||||
} else if (wp->w_status_height == 0 && !is_stl_global) {
|
} else if (wp->w_status_height == 0 && !is_stl_global) {
|
||||||
// If statusline isn't global and the window doesn't have a statusline, re-add it
|
// If statusline isn't global and the window doesn't have a statusline, re-add it
|
||||||
wp->w_status_height = STATUS_HEIGHT;
|
wp->w_status_height = STATUS_HEIGHT;
|
||||||
@@ -6675,13 +6693,8 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
|
|||||||
comp_col();
|
comp_col();
|
||||||
}
|
}
|
||||||
redraw_all_later(SOME_VALID);
|
redraw_all_later(SOME_VALID);
|
||||||
} else if (fr->fr_layout == FR_COL) {
|
|
||||||
// For a column frame, recursively call this function for all child frames
|
|
||||||
FOR_ALL_FRAMES(fp, fr->fr_child) {
|
|
||||||
last_status_rec(fp, statusline, is_stl_global);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// For a row frame, recursively call this function for all child frames
|
// For a column or row frame, recursively call this function for all child frames
|
||||||
FOR_ALL_FRAMES(fp, fr->fr_child) {
|
FOR_ALL_FRAMES(fp, fr->fr_child) {
|
||||||
last_status_rec(fp, statusline, is_stl_global);
|
last_status_rec(fp, statusline, is_stl_global);
|
||||||
}
|
}
|
||||||
@@ -6697,6 +6710,14 @@ void set_winbar(void)
|
|||||||
wp->w_winbar_height = winbar_height;
|
wp->w_winbar_height = winbar_height;
|
||||||
win_set_inner_size(wp);
|
win_set_inner_size(wp);
|
||||||
wp->w_redr_winbar = winbar_height;
|
wp->w_redr_winbar = winbar_height;
|
||||||
|
|
||||||
|
if (winbar_height == 0) {
|
||||||
|
// When removing winbar, deallocate the w_winbar_click_defs array
|
||||||
|
stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size);
|
||||||
|
xfree(wp->w_winbar_click_defs);
|
||||||
|
wp->w_winbar_click_defs_size = 0;
|
||||||
|
wp->w_winbar_click_defs = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,260 +0,0 @@
|
|||||||
local helpers = require('test.functional.helpers')(after_each)
|
|
||||||
local Screen = require('test.functional.ui.screen')
|
|
||||||
local clear, command, feed = helpers.clear, helpers.command, helpers.feed
|
|
||||||
local eq, funcs, meths = helpers.eq, helpers.funcs, helpers.meths
|
|
||||||
|
|
||||||
describe('global statusline', function()
|
|
||||||
local screen
|
|
||||||
|
|
||||||
before_each(function()
|
|
||||||
clear()
|
|
||||||
screen = Screen.new(60, 16)
|
|
||||||
screen:attach()
|
|
||||||
command('set laststatus=3')
|
|
||||||
command('set ruler')
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('works', function()
|
|
||||||
screen:expect{grid=[[
|
|
||||||
^ |
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{2:[No Name] 0,0-1 All}|
|
|
||||||
|
|
|
||||||
]], attr_ids={
|
|
||||||
[1] = {bold = true, foreground = Screen.colors.Blue1};
|
|
||||||
[2] = {bold = true, reverse = true};
|
|
||||||
}}
|
|
||||||
|
|
||||||
feed('i<CR><CR>')
|
|
||||||
screen:expect{grid=[[
|
|
||||||
|
|
|
||||||
|
|
|
||||||
^ |
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{2:[No Name] [+] 3,1 All}|
|
|
||||||
{3:-- INSERT --} |
|
|
||||||
]], attr_ids={
|
|
||||||
[1] = {bold = true, foreground = Screen.colors.Blue};
|
|
||||||
[2] = {bold = true, reverse = true};
|
|
||||||
[3] = {bold = true};
|
|
||||||
}}
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('works with splits', function()
|
|
||||||
command('vsplit | split | vsplit | vsplit | wincmd l | split | 2wincmd l | split')
|
|
||||||
screen:expect{grid=[[
|
|
||||||
│ │ │^ |
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }├────────────────┤{2:~}│{2:~ }|
|
|
||||||
{2:~ }│ │{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}├────────────────────|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│ |
|
|
||||||
────────────────────┴────────────────┴─┤{2:~ }|
|
|
||||||
│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{3:[No Name] 0,0-1 All}|
|
|
||||||
|
|
|
||||||
]], attr_ids={
|
|
||||||
[1] = {reverse = true};
|
|
||||||
[2] = {bold = true, foreground = Screen.colors.Blue1};
|
|
||||||
[3] = {bold = true, reverse = true};
|
|
||||||
}}
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('works when switching between values of laststatus', function()
|
|
||||||
command('set laststatus=1')
|
|
||||||
screen:expect{grid=[[
|
|
||||||
^ |
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
0,0-1 All |
|
|
||||||
]], attr_ids={
|
|
||||||
[1] = {foreground = Screen.colors.Blue, bold = true};
|
|
||||||
}}
|
|
||||||
|
|
||||||
command('set laststatus=3')
|
|
||||||
screen:expect{grid=[[
|
|
||||||
^ |
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{2:[No Name] 0,0-1 All}|
|
|
||||||
|
|
|
||||||
]], attr_ids={
|
|
||||||
[1] = {foreground = Screen.colors.Blue, bold = true};
|
|
||||||
[2] = {reverse = true, bold = true};
|
|
||||||
}}
|
|
||||||
|
|
||||||
command('vsplit | split | vsplit | vsplit | wincmd l | split | 2wincmd l | split')
|
|
||||||
command('set laststatus=2')
|
|
||||||
screen:expect{grid=[[
|
|
||||||
│ │ │^ |
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{1:< Name] 0,0-1 }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│ │{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{3:<No Name] 0,0-1 All}|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│ |
|
|
||||||
{1:<No Name] 0,0-1 All < Name] 0,0-1 <}│{2:~ }|
|
|
||||||
│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{1:[No Name] 0,0-1 All <No Name] 0,0-1 All}|
|
|
||||||
|
|
|
||||||
]], attr_ids={
|
|
||||||
[1] = {reverse = true};
|
|
||||||
[2] = {foreground = Screen.colors.Blue, bold = true};
|
|
||||||
[3] = {reverse = true, bold = true};
|
|
||||||
}}
|
|
||||||
|
|
||||||
command('set laststatus=3')
|
|
||||||
screen:expect{grid=[[
|
|
||||||
│ │ │^ |
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }├────────────────┤{2:~}│{2:~ }|
|
|
||||||
{2:~ }│ │{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}├────────────────────|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│ |
|
|
||||||
────────────────────┴────────────────┴─┤{2:~ }|
|
|
||||||
│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{3:[No Name] 0,0-1 All}|
|
|
||||||
|
|
|
||||||
]], attr_ids={
|
|
||||||
[1] = {reverse = true};
|
|
||||||
[2] = {foreground = Screen.colors.Blue, bold = true};
|
|
||||||
[3] = {reverse = true, bold = true};
|
|
||||||
}}
|
|
||||||
|
|
||||||
command('set laststatus=0')
|
|
||||||
screen:expect{grid=[[
|
|
||||||
│ │ │^ |
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{1:< Name] 0,0-1 }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│ │{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{3:<No Name] 0,0-1 All}|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│ |
|
|
||||||
{1:<No Name] 0,0-1 All < Name] 0,0-1 <}│{2:~ }|
|
|
||||||
│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
0,0-1 All |
|
|
||||||
]], attr_ids={
|
|
||||||
[1] = {reverse = true};
|
|
||||||
[2] = {foreground = Screen.colors.Blue, bold = true};
|
|
||||||
[3] = {reverse = true, bold = true};
|
|
||||||
}}
|
|
||||||
|
|
||||||
command('set laststatus=3')
|
|
||||||
screen:expect{grid=[[
|
|
||||||
│ │ │^ |
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }├────────────────┤{2:~}│{2:~ }|
|
|
||||||
{2:~ }│ │{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }│{2:~}├────────────────────|
|
|
||||||
{2:~ }│{2:~ }│{2:~}│ |
|
|
||||||
────────────────────┴────────────────┴─┤{2:~ }|
|
|
||||||
│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{2:~ }│{2:~ }|
|
|
||||||
{3:[No Name] 0,0-1 All}|
|
|
||||||
|
|
|
||||||
]], attr_ids={
|
|
||||||
[1] = {reverse = true};
|
|
||||||
[2] = {foreground = Screen.colors.Blue, bold = true};
|
|
||||||
[3] = {reverse = true, bold = true};
|
|
||||||
}}
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('win_move_statusline() can reduce cmdheight to 1', function()
|
|
||||||
eq(1, meths.get_option('cmdheight'))
|
|
||||||
funcs.win_move_statusline(0, -1)
|
|
||||||
eq(2, meths.get_option('cmdheight'))
|
|
||||||
funcs.win_move_statusline(0, -1)
|
|
||||||
eq(3, meths.get_option('cmdheight'))
|
|
||||||
funcs.win_move_statusline(0, 1)
|
|
||||||
eq(2, meths.get_option('cmdheight'))
|
|
||||||
funcs.win_move_statusline(0, 1)
|
|
||||||
eq(1, meths.get_option('cmdheight'))
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('mouse dragging can reduce cmdheight to 1', function()
|
|
||||||
command('set mouse=a')
|
|
||||||
meths.input_mouse('left', 'press', '', 0, 14, 10)
|
|
||||||
eq(1, meths.get_option('cmdheight'))
|
|
||||||
meths.input_mouse('left', 'drag', '', 0, 13, 10)
|
|
||||||
eq(2, meths.get_option('cmdheight'))
|
|
||||||
meths.input_mouse('left', 'drag', '', 0, 12, 10)
|
|
||||||
eq(3, meths.get_option('cmdheight'))
|
|
||||||
meths.input_mouse('left', 'drag', '', 0, 13, 10)
|
|
||||||
eq(2, meths.get_option('cmdheight'))
|
|
||||||
meths.input_mouse('left', 'drag', '', 0, 14, 10)
|
|
||||||
eq(1, meths.get_option('cmdheight'))
|
|
||||||
end)
|
|
||||||
end)
|
|
317
test/functional/ui/statusline_spec.lua
Normal file
317
test/functional/ui/statusline_spec.lua
Normal file
@@ -0,0 +1,317 @@
|
|||||||
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
|
local Screen = require('test.functional.ui.screen')
|
||||||
|
local clear = helpers.clear
|
||||||
|
local command = helpers.command
|
||||||
|
local feed = helpers.feed
|
||||||
|
local eq = helpers.eq
|
||||||
|
local funcs = helpers.funcs
|
||||||
|
local meths = helpers.meths
|
||||||
|
local exec = helpers.exec
|
||||||
|
local exec_lua = helpers.exec_lua
|
||||||
|
local eval = helpers.eval
|
||||||
|
|
||||||
|
describe('statusline clicks', function()
|
||||||
|
local screen
|
||||||
|
|
||||||
|
before_each(function()
|
||||||
|
clear()
|
||||||
|
screen = Screen.new(40, 8)
|
||||||
|
screen:attach()
|
||||||
|
command('set laststatus=2')
|
||||||
|
exec([=[
|
||||||
|
function! MyClickFunc(minwid, clicks, button, mods)
|
||||||
|
let g:testvar = printf("%d %d %s", a:minwid, a:clicks, a:button)
|
||||||
|
endfunction
|
||||||
|
]=])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works', function()
|
||||||
|
meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
|
||||||
|
meths.input_mouse('left', 'press', '', 0, 6, 17)
|
||||||
|
eq('0 1 l', eval("g:testvar"))
|
||||||
|
meths.input_mouse('right', 'press', '', 0, 6, 17)
|
||||||
|
eq('0 1 r', eval("g:testvar"))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works for winbar', function()
|
||||||
|
meths.set_option('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
|
||||||
|
meths.input_mouse('left', 'press', '', 0, 0, 17)
|
||||||
|
eq('0 1 l', eval("g:testvar"))
|
||||||
|
meths.input_mouse('right', 'press', '', 0, 6, 17)
|
||||||
|
eq('0 1 r', eval("g:testvar"))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works for winbar in floating window', function()
|
||||||
|
meths.open_win(0, true, { width=30, height=4, relative='editor', row=1, col=5,
|
||||||
|
border = "single" })
|
||||||
|
meths.set_option_value('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T',
|
||||||
|
{ scope = 'local' })
|
||||||
|
meths.input_mouse('left', 'press', '', 0, 2, 23)
|
||||||
|
eq('0 1 l', eval("g:testvar"))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works when there are multiple windows', function()
|
||||||
|
command('split')
|
||||||
|
meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
|
||||||
|
meths.set_option('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
|
||||||
|
meths.input_mouse('left', 'press', '', 0, 0, 17)
|
||||||
|
eq('0 1 l', eval("g:testvar"))
|
||||||
|
meths.input_mouse('right', 'press', '', 0, 4, 17)
|
||||||
|
eq('0 1 r', eval("g:testvar"))
|
||||||
|
meths.input_mouse('middle', 'press', '', 0, 3, 17)
|
||||||
|
eq('0 1 m', eval("g:testvar"))
|
||||||
|
meths.input_mouse('left', 'press', '', 0, 6, 17)
|
||||||
|
eq('0 1 l', eval("g:testvar"))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works with Lua function', function()
|
||||||
|
exec_lua([[
|
||||||
|
function clicky_func(minwid, clicks, button, mods)
|
||||||
|
vim.g.testvar = string.format("%d %d %s", minwid, clicks, button)
|
||||||
|
end
|
||||||
|
]])
|
||||||
|
meths.set_option('statusline', 'Not clicky stuff %0@v:lua.clicky_func@Clicky stuff%T')
|
||||||
|
meths.input_mouse('left', 'press', '', 0, 6, 17)
|
||||||
|
eq('0 1 l', eval("g:testvar"))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('ignores unsupported click items', function()
|
||||||
|
command('tabnew | tabprevious')
|
||||||
|
meths.set_option('statusline', '%2TNot clicky stuff%T')
|
||||||
|
meths.input_mouse('left', 'press', '', 0, 6, 0)
|
||||||
|
eq(1, meths.get_current_tabpage().id)
|
||||||
|
meths.set_option('statusline', '%2XNot clicky stuff%X')
|
||||||
|
meths.input_mouse('left', 'press', '', 0, 6, 0)
|
||||||
|
eq(2, #meths.list_tabpages())
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe('global statusline', function()
|
||||||
|
local screen
|
||||||
|
|
||||||
|
before_each(function()
|
||||||
|
clear()
|
||||||
|
screen = Screen.new(60, 16)
|
||||||
|
screen:attach()
|
||||||
|
screen:set_default_attr_ids({
|
||||||
|
[1] = {bold = true, foreground = Screen.colors.Blue};
|
||||||
|
[2] = {bold = true, reverse = true};
|
||||||
|
[3] = {bold = true};
|
||||||
|
[4] = {reverse = true};
|
||||||
|
})
|
||||||
|
command('set laststatus=3')
|
||||||
|
command('set ruler')
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works', function()
|
||||||
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{2:[No Name] 0,0-1 All}|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
feed('i<CR><CR>')
|
||||||
|
screen:expect([[
|
||||||
|
|
|
||||||
|
|
|
||||||
|
^ |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{2:[No Name] [+] 3,1 All}|
|
||||||
|
{3:-- INSERT --} |
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works with splits', function()
|
||||||
|
command('vsplit | split | vsplit | vsplit | wincmd l | split | 2wincmd l | split')
|
||||||
|
screen:expect([[
|
||||||
|
│ │ │^ |
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }├────────────────┤{1:~}│{1:~ }|
|
||||||
|
{1:~ }│ │{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}├────────────────────|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│ |
|
||||||
|
────────────────────┴────────────────┴─┤{1:~ }|
|
||||||
|
│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{2:[No Name] 0,0-1 All}|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works when switching between values of laststatus', function()
|
||||||
|
command('set laststatus=1')
|
||||||
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
0,0-1 All |
|
||||||
|
]])
|
||||||
|
|
||||||
|
command('set laststatus=3')
|
||||||
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{2:[No Name] 0,0-1 All}|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
command('vsplit | split | vsplit | vsplit | wincmd l | split | 2wincmd l | split')
|
||||||
|
command('set laststatus=2')
|
||||||
|
screen:expect([[
|
||||||
|
│ │ │^ |
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{4:< Name] 0,0-1 }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│ │{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{2:<No Name] 0,0-1 All}|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│ |
|
||||||
|
{4:<No Name] 0,0-1 All < Name] 0,0-1 <}│{1:~ }|
|
||||||
|
│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{4:[No Name] 0,0-1 All <No Name] 0,0-1 All}|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
command('set laststatus=3')
|
||||||
|
screen:expect([[
|
||||||
|
│ │ │^ |
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }├────────────────┤{1:~}│{1:~ }|
|
||||||
|
{1:~ }│ │{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}├────────────────────|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│ |
|
||||||
|
────────────────────┴────────────────┴─┤{1:~ }|
|
||||||
|
│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{2:[No Name] 0,0-1 All}|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
command('set laststatus=0')
|
||||||
|
screen:expect([[
|
||||||
|
│ │ │^ |
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{4:< Name] 0,0-1 }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│ │{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{2:<No Name] 0,0-1 All}|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│ |
|
||||||
|
{4:<No Name] 0,0-1 All < Name] 0,0-1 <}│{1:~ }|
|
||||||
|
│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
0,0-1 All |
|
||||||
|
]])
|
||||||
|
|
||||||
|
command('set laststatus=3')
|
||||||
|
screen:expect([[
|
||||||
|
│ │ │^ |
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }├────────────────┤{1:~}│{1:~ }|
|
||||||
|
{1:~ }│ │{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }│{1:~}├────────────────────|
|
||||||
|
{1:~ }│{1:~ }│{1:~}│ |
|
||||||
|
────────────────────┴────────────────┴─┤{1:~ }|
|
||||||
|
│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{1:~ }│{1:~ }|
|
||||||
|
{2:[No Name] 0,0-1 All}|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('win_move_statusline() can reduce cmdheight to 1', function()
|
||||||
|
eq(1, meths.get_option('cmdheight'))
|
||||||
|
funcs.win_move_statusline(0, -1)
|
||||||
|
eq(2, meths.get_option('cmdheight'))
|
||||||
|
funcs.win_move_statusline(0, -1)
|
||||||
|
eq(3, meths.get_option('cmdheight'))
|
||||||
|
funcs.win_move_statusline(0, 1)
|
||||||
|
eq(2, meths.get_option('cmdheight'))
|
||||||
|
funcs.win_move_statusline(0, 1)
|
||||||
|
eq(1, meths.get_option('cmdheight'))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('mouse dragging can reduce cmdheight to 1', function()
|
||||||
|
command('set mouse=a')
|
||||||
|
meths.input_mouse('left', 'press', '', 0, 14, 10)
|
||||||
|
eq(1, meths.get_option('cmdheight'))
|
||||||
|
meths.input_mouse('left', 'drag', '', 0, 13, 10)
|
||||||
|
eq(2, meths.get_option('cmdheight'))
|
||||||
|
meths.input_mouse('left', 'drag', '', 0, 12, 10)
|
||||||
|
eq(3, meths.get_option('cmdheight'))
|
||||||
|
meths.input_mouse('left', 'drag', '', 0, 13, 10)
|
||||||
|
eq(2, meths.get_option('cmdheight'))
|
||||||
|
meths.input_mouse('left', 'drag', '', 0, 14, 10)
|
||||||
|
eq(1, meths.get_option('cmdheight'))
|
||||||
|
end)
|
||||||
|
end)
|
Reference in New Issue
Block a user