diff options
author | Luuk van Baal <luukvbaal@gmail.com> | 2025-01-21 11:15:31 +0100 |
---|---|---|
committer | luukvbaal <luukvbaal@gmail.com> | 2025-01-23 17:26:10 +0100 |
commit | 2cd72258f6be0ea20f0341be9bc0d306c4533535 (patch) | |
tree | 839c86f5c9d51c3e390de8e7173c9b2f5bce4ab3 | |
parent | a450fda4ededdd93e3dc571d82a6737f6b9d50d9 (diff) | |
download | rneovim-2cd72258f6be0ea20f0341be9bc0d306c4533535.tar.gz rneovim-2cd72258f6be0ea20f0341be9bc0d306c4533535.tar.bz2 rneovim-2cd72258f6be0ea20f0341be9bc0d306c4533535.zip |
fix(mouse): 'statuscolumn' fold and popopmenu handling
Problem: A right-click on the 'statuscolumn' does not open the
popupmenu, even if a cell without a clickdef is clicked.
Clicking the %C fold item does not open/close the fold.
Solution: Open the popupmenu when there is no clickdef like right-clicking
the sign/numbercolumn does. Fill "linebuf_vcol" when drawing the
'statuscolumn' to handle foldcolumn item clicks.
-rw-r--r-- | src/nvim/drawline.c | 25 | ||||
-rw-r--r-- | src/nvim/mouse.c | 190 | ||||
-rw-r--r-- | src/nvim/statusline.c | 10 | ||||
-rw-r--r-- | src/nvim/statusline_defs.h | 1 | ||||
-rw-r--r-- | test/functional/ui/statuscolumn_spec.lua | 89 |
5 files changed, 189 insertions, 126 deletions
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 74a766bd0c..5196d5c9f4 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -368,14 +368,14 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, // TODO(bfredl): integrate with grid.c linebuf code? madness? static void draw_col_buf(win_T *wp, winlinevars_T *wlv, const char *text, size_t len, int attr, - bool vcol) + const colnr_T *fold_vcol, bool inc_vcol) { const char *ptr = text; while (ptr < text + len && wlv->off < wp->w_grid.cols) { int cells = line_putchar(wp->w_buffer, &ptr, &linebuf_char[wlv->off], wp->w_grid.cols - wlv->off, wlv->off); int myattr = attr; - if (vcol) { + if (inc_vcol) { advance_color_col(wlv, wlv->vcol); if (wlv->color_cols && wlv->vcol == *wlv->color_cols) { myattr = hl_combine_attr(win_hl_attr(wp, HLF_MC), myattr); @@ -383,7 +383,7 @@ static void draw_col_buf(win_T *wp, winlinevars_T *wlv, const char *text, size_t } for (int c = 0; c < cells; c++) { linebuf_attr[wlv->off] = myattr; - linebuf_vcol[wlv->off] = vcol ? wlv->vcol++ : -1; + linebuf_vcol[wlv->off] = inc_vcol ? wlv->vcol++ : fold_vcol ? *(fold_vcol++) : -1; wlv->off++; } } @@ -412,7 +412,7 @@ static void draw_foldcolumn(win_T *wp, winlinevars_T *wlv) int fdc = compute_foldcolumn(wp, 0); if (fdc > 0) { int attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLF : HLF_FC); - fill_foldcolumn(wp, wlv->foldinfo, wlv->lnum, attr, fdc, &wlv->off, NULL); + fill_foldcolumn(wp, wlv->foldinfo, wlv->lnum, attr, fdc, &wlv->off, NULL, NULL); } } @@ -421,8 +421,9 @@ static void draw_foldcolumn(win_T *wp, winlinevars_T *wlv) /// @param fdc Current width of the foldcolumn /// @param[out] wlv_off Pointer to linebuf offset, incremented for default column /// @param[out] out_buffer Char array to fill, only used for 'statuscolumn' +/// @param[out] out_vcol vcol array to fill, only used for 'statuscolumn' void fill_foldcolumn(win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int attr, int fdc, int *wlv_off, - schar_T *out_buffer) + colnr_T *out_vcol, schar_T *out_buffer) { bool closed = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0; int level = foldinfo.fi_level; @@ -448,10 +449,12 @@ void fill_foldcolumn(win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int attr, in symbol = schar_from_ascii('>'); } + int vcol = i >= level ? -1 : (i == closedcol - 1 && closed) ? -2 : -3; if (out_buffer) { + out_vcol[i] = vcol; out_buffer[i] = symbol; } else { - linebuf_vcol[*wlv_off] = i >= level ? -1 : (i == closedcol - 1 && closed) ? -2 : -3; + linebuf_vcol[*wlv_off] = vcol; linebuf_attr[*wlv_off] = attr; linebuf_char[(*wlv_off)++] = symbol; } @@ -577,7 +580,7 @@ static void draw_lnum_col(win_T *wp, winlinevars_T *wlv) char *num = skipwhite(buf); rl_mirror_ascii(num, skiptowhite(num)); } - draw_col_buf(wp, wlv, buf, (size_t)width, attr, false); + draw_col_buf(wp, wlv, buf, (size_t)width, attr, NULL, false); } else { draw_col_fill(wlv, schar_from_ascii(' '), width, attr); } @@ -632,6 +635,7 @@ static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int vir char *p = buf; char transbuf[MAXPATHL]; + colnr_T *fold_vcol = NULL; size_t len = strlen(buf); int scl_attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC); int num_attr = hl_combine_attr(get_line_number_attr(wp, wlv), @@ -643,13 +647,14 @@ static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int vir ptrdiff_t textlen = sp->start - p; // Make all characters printable. size_t translen = transstr_buf(p, textlen, transbuf, MAXPATHL, true); - draw_col_buf(wp, wlv, transbuf, translen, cur_attr, false); + draw_col_buf(wp, wlv, transbuf, translen, cur_attr, fold_vcol, false); int attr = sp->item == STL_SIGNCOL ? scl_attr : sp->item == STL_FOLDCOL ? 0 : num_attr; cur_attr = hl_combine_attr(attr, sp->userhl < 0 ? syn_id2attr(-sp->userhl) : 0); + fold_vcol = sp->item == STL_FOLDCOL ? stcp->fold_vcol : NULL; p = sp->start; } size_t translen = transstr_buf(p, buf + len - p, transbuf, MAXPATHL, true); - draw_col_buf(wp, wlv, transbuf, translen, num_attr, false); + draw_col_buf(wp, wlv, transbuf, translen, num_attr, fold_vcol, false); draw_col_fill(wlv, schar_from_ascii(' '), stcp->width - width, num_attr); } @@ -722,7 +727,7 @@ static void handle_showbreak_and_filler(win_T *wp, winlinevars_T *wlv) // Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'. int attr = hl_combine_attr(wlv->cul_attr, win_hl_attr(wp, HLF_AT)); colnr_T vcol_before = wlv->vcol; - draw_col_buf(wp, wlv, sbr, strlen(sbr), attr, true); + draw_col_buf(wp, wlv, sbr, strlen(sbr), attr, NULL, true); wlv->vcol_sbr = wlv->vcol; // Correct start of highlighted area for 'showbreak'. diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 1289adfabb..b0ab235f6b 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -280,6 +280,54 @@ static int get_fpos_of_mouse(pos_T *mpos) return IN_BUFFER; } +static int do_popup(int which_button, int m_pos_flag, pos_T m_pos) +{ + int jump_flags = 0; + if (strcmp(p_mousem, "popup_setpos") == 0) { + // First set the cursor position before showing the popup menu. + if (VIsual_active) { + // set MOUSE_MAY_STOP_VIS if we are outside the selection + // or the current window (might have false negative here) + if (m_pos_flag != IN_BUFFER) { + jump_flags = MOUSE_MAY_STOP_VIS; + } else { + if (VIsual_mode == 'V') { + if ((curwin->w_cursor.lnum <= VIsual.lnum + && (m_pos.lnum < curwin->w_cursor.lnum || VIsual.lnum < m_pos.lnum)) + || (VIsual.lnum < curwin->w_cursor.lnum + && (m_pos.lnum < VIsual.lnum || curwin->w_cursor.lnum < m_pos.lnum))) { + jump_flags = MOUSE_MAY_STOP_VIS; + } + } else if ((ltoreq(curwin->w_cursor, VIsual) + && (lt(m_pos, curwin->w_cursor) || lt(VIsual, m_pos))) + || (lt(VIsual, curwin->w_cursor) + && (lt(m_pos, VIsual) || lt(curwin->w_cursor, m_pos)))) { + jump_flags = MOUSE_MAY_STOP_VIS; + } else if (VIsual_mode == Ctrl_V) { + colnr_T leftcol, rightcol; + getvcols(curwin, &curwin->w_cursor, &VIsual, &leftcol, &rightcol); + getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL); + if (m_pos.col < leftcol || m_pos.col > rightcol) { + jump_flags = MOUSE_MAY_STOP_VIS; + } + } + } + } else { + jump_flags = MOUSE_MAY_STOP_VIS; + } + } + if (jump_flags) { + jump_flags = jump_to_mouse(jump_flags, NULL, which_button); + redraw_curbuf_later(VIsual_active ? UPD_INVERTED : UPD_VALID); + update_screen(); + setcursor(); + ui_flush(); // Update before showing popup menu + } + show_popupmenu(); + got_click = false; // ignore release events + return jump_flags; +} + /// Do the appropriate action for the current mouse click in the current mode. /// Not used for Command-line mode. /// @@ -324,24 +372,8 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent) int which_button; // MOUSE_LEFT, _MIDDLE or _RIGHT bool is_click; // If false it's a drag or release event bool is_drag; // If true it's a drag event - int jump_flags = 0; // flags for jump_to_mouse() - pos_T start_visual; - bool moved; // Has cursor moved? - bool in_winbar; // mouse in window bar - bool in_statuscol; // mouse in status column - bool in_status_line; // mouse in status line static bool in_tab_line = false; // mouse clicked in tab line - bool in_sep_line; // mouse in vertical separator line - int c1; - win_T *old_curwin = curwin; static pos_T orig_cursor; - colnr_T leftcol, rightcol; - pos_T end_visual; - int old_active = VIsual_active; - int old_mode = VIsual_mode; - int regname; - - pos_T save_cursor = curwin->w_cursor; while (true) { which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag); @@ -434,12 +466,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent) return false; } - if (oap != NULL) { - regname = oap->regname; - } else { - regname = 0; - } - + int regname = oap != NULL ? oap->regname : 0; // Middle mouse button does a 'put' of the selected text if (which_button == MOUSE_MIDDLE) { if (State == MODE_NORMAL) { @@ -496,12 +523,10 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent) } } + // flags for jump_to_mouse() // When dragging or button-up stay in the same window. - if (!is_click) { - jump_flags |= MOUSE_FOCUS | MOUSE_DID_MOVE; - } - - start_visual.lnum = 0; + int jump_flags = is_click ? 0 : (MOUSE_FOCUS|MOUSE_DID_MOVE); + win_T *old_curwin = curwin; if (tab_page_click_defs != NULL) { // only when initialized // Check for clicking in the tab page line. @@ -515,8 +540,8 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent) // click in a tab selects that tab page if (is_click && cmdwin_type == 0 && mouse_col < Columns) { + int tabnr = tab_page_click_defs[mouse_col].tabnr; in_tab_line = true; - c1 = tab_page_click_defs[mouse_col].tabnr; switch (tab_page_click_defs[mouse_col].type) { case kStlClickDisabled: @@ -527,11 +552,11 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent) // double click opens new page end_visual_mode(); tabpage_new(); - tabpage_move(c1 == 0 ? 9999 : c1 - 1); + tabpage_move(tabnr == 0 ? 9999 : tabnr - 1); } else { // Go to specified tab page, or next one if not clicking // on a label. - goto_tabpage(c1); + goto_tabpage(tabnr); // It's like clicking on the status line of a window. if (curwin != old_curwin) { @@ -542,7 +567,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent) } FALLTHROUGH; case kStlClickTabClose: - mouse_tab_close(c1); + mouse_tab_close(tabnr); break; case kStlClickFuncRun: call_click_def_func(tab_page_click_defs, mouse_col, which_button); @@ -556,75 +581,33 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent) } } + int m_pos_flag = 0; + pos_T m_pos = { 0 }; // When 'mousemodel' is "popup" or "popup_setpos", translate mouse events: // right button up -> pop-up menu // shift-left button -> right button // alt-left button -> alt-right button if (mouse_model_popup()) { - pos_T m_pos; - int m_pos_flag = get_fpos_of_mouse(&m_pos); - if (m_pos_flag & (IN_STATUS_LINE|MOUSE_WINBAR|MOUSE_STATUSCOL)) { - goto popupexit; - } - if (which_button == MOUSE_RIGHT - && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) { + m_pos_flag = get_fpos_of_mouse(&m_pos); + if (!(m_pos_flag & (IN_STATUS_LINE|MOUSE_WINBAR|MOUSE_STATUSCOL)) + && which_button == MOUSE_RIGHT && !(mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))) { if (!is_click) { // Ignore right button release events, only shows the popup // menu on the button down event. return false; } - jump_flags = 0; - if (strcmp(p_mousem, "popup_setpos") == 0) { - // First set the cursor position before showing the popup menu. - if (VIsual_active) { - // set MOUSE_MAY_STOP_VIS if we are outside the selection - // or the current window (might have false negative here) - if (m_pos_flag != IN_BUFFER) { - jump_flags = MOUSE_MAY_STOP_VIS; - } else { - if (VIsual_mode == 'V') { - if ((curwin->w_cursor.lnum <= VIsual.lnum - && (m_pos.lnum < curwin->w_cursor.lnum || VIsual.lnum < m_pos.lnum)) - || (VIsual.lnum < curwin->w_cursor.lnum - && (m_pos.lnum < VIsual.lnum || curwin->w_cursor.lnum < m_pos.lnum))) { - jump_flags = MOUSE_MAY_STOP_VIS; - } - } else if ((ltoreq(curwin->w_cursor, VIsual) - && (lt(m_pos, curwin->w_cursor) || lt(VIsual, m_pos))) - || (lt(VIsual, curwin->w_cursor) - && (lt(m_pos, VIsual) || lt(curwin->w_cursor, m_pos)))) { - jump_flags = MOUSE_MAY_STOP_VIS; - } else if (VIsual_mode == Ctrl_V) { - getvcols(curwin, &curwin->w_cursor, &VIsual, &leftcol, &rightcol); - getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL); - if (m_pos.col < leftcol || m_pos.col > rightcol) { - jump_flags = MOUSE_MAY_STOP_VIS; - } - } - } - } else { - jump_flags = MOUSE_MAY_STOP_VIS; - } - } - if (jump_flags) { - jump_flags = jump_to_mouse(jump_flags, NULL, which_button); - redraw_curbuf_later(VIsual_active ? UPD_INVERTED : UPD_VALID); - update_screen(); - setcursor(); - ui_flush(); // Update before showing popup menu - } - show_popupmenu(); - got_click = false; // ignore release events - return (jump_flags & CURSOR_MOVED) != 0; + return (do_popup(which_button, m_pos_flag, m_pos) & CURSOR_MOVED); } - if (which_button == MOUSE_LEFT - && (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_ALT))) { + // Only do this translation when mouse is over the buffer text + if (!(m_pos_flag & (IN_STATUS_LINE|MOUSE_WINBAR|MOUSE_STATUSCOL)) + && (which_button == MOUSE_LEFT && (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_ALT)))) { which_button = MOUSE_RIGHT; mod_mask &= ~MOD_MASK_SHIFT; } } -popupexit: + pos_T end_visual = { 0 }; + pos_T start_visual = { 0 }; if ((State & (MODE_NORMAL | MODE_INSERT)) && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) { if (which_button == MOUSE_LEFT) { @@ -664,15 +647,15 @@ popupexit: } // JUMP! - jump_flags = jump_to_mouse(jump_flags, - oap == NULL ? NULL : &(oap->inclusive), - which_button); + int old_active = VIsual_active; + pos_T save_cursor = curwin->w_cursor; + jump_flags = jump_to_mouse(jump_flags, oap == NULL ? NULL : &(oap->inclusive), which_button); - moved = (jump_flags & CURSOR_MOVED); - in_winbar = (jump_flags & MOUSE_WINBAR); - in_statuscol = (jump_flags & MOUSE_STATUSCOL); - in_status_line = (jump_flags & IN_STATUS_LINE); - in_sep_line = (jump_flags & IN_SEP_LINE); + bool moved = (jump_flags & CURSOR_MOVED); + bool in_winbar = (jump_flags & MOUSE_WINBAR); + bool in_statuscol = (jump_flags & MOUSE_STATUSCOL); + bool in_status_line = (jump_flags & IN_STATUS_LINE); + bool in_sep_line = (jump_flags & IN_SEP_LINE); if ((in_winbar || in_status_line || in_statuscol) && is_click) { // Handle click event on window bar, status line or status column @@ -705,6 +688,12 @@ popupexit: if (click_defs != NULL) { switch (click_defs[click_col].type) { case kStlClickDisabled: + // If there is no click definition, still open the popupmenu for a + // statuscolumn click like a click in the sign/number column does. + if (in_statuscol && mouse_model_popup() + && which_button == MOUSE_RIGHT && !(mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))) { + do_popup(which_button, m_pos_flag, m_pos); + } break; case kStlClickFuncRun: call_click_def_func(click_defs, click_col, which_button); @@ -715,7 +704,9 @@ popupexit: } } - return false; + if (!(in_statuscol && (jump_flags & (MOUSE_FOLD_CLOSE|MOUSE_FOLD_OPEN)))) { + return false; + } } else if (in_winbar || in_statuscol) { // A drag or release event in the window bar and status column has no side effects. return false; @@ -760,6 +751,7 @@ popupexit: mouse_row = 0; } + int old_mode = VIsual_mode; if (start_visual.lnum) { // right click in visual mode linenr_T diff; // When ALT is pressed make Visual mode blockwise. @@ -770,6 +762,7 @@ popupexit: // In Visual-block mode, divide the area in four, pick up the corner // that is in the quarter that the cursor is in. if (VIsual_mode == Ctrl_V) { + colnr_T leftcol, rightcol; getvcols(curwin, &start_visual, &end_visual, &leftcol, &rightcol); if (curwin->w_curswant > (leftcol + rightcol) / 2) { end_visual.col = leftcol; @@ -831,7 +824,6 @@ popupexit: // Middle mouse click: Put text before cursor. if (which_button == MOUSE_MIDDLE) { - int c2; if (regname == 0 && eval_has_provider("clipboard", false)) { regname = '*'; } @@ -843,6 +835,7 @@ popupexit: dir = FORWARD; } + int c1, c2; if (fixindent) { c1 = (dir == BACKWARD) ? '[' : ']'; c2 = 'p'; @@ -1258,8 +1251,6 @@ retnomove: if (flags & MOUSE_SETPOS) { goto retnomove; // ugly goto... } - win_T *old_curwin = curwin; - pos_T old_cursor = curwin->w_cursor; if (row < 0 || col < 0) { // check if it makes sense return IN_UNKNOWN; @@ -1299,13 +1290,15 @@ retnomove: grid = mouse_grid; } + win_T *old_curwin = curwin; + pos_T old_cursor = curwin->w_cursor; if (!keep_focus) { if (on_winbar) { return IN_OTHER_WIN | MOUSE_WINBAR; } if (on_statuscol) { - return IN_OTHER_WIN | MOUSE_STATUSCOL; + goto foldclick; } fdc = win_fdccol_count(wp); @@ -1497,6 +1490,7 @@ retnomove: } } +foldclick:; colnr_T col_from_screen = -1; int mouse_fold_flags = 0; mouse_check_grid(&col_from_screen, &mouse_fold_flags); @@ -1535,7 +1529,7 @@ retnomove: *inclusive = false; } - count = IN_BUFFER; + count = on_statuscol ? (IN_OTHER_WIN|MOUSE_STATUSCOL) : IN_BUFFER; if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum || curwin->w_cursor.col != old_cursor.col) { count |= CURSOR_MOVED; // Cursor has moved diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index f0437db1bb..6947a14a2c 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -1157,9 +1157,11 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op } } - // If the group is longer than it is allowed to be - // truncate by removing bytes from the start of the group text. - if (group_len > stl_items[stl_groupitems[groupdepth]].maxwid) { + // If the group is longer than it is allowed to be truncate by removing + // bytes from the start of the group text. Don't truncate when item is a + // 'statuscolumn' fold item to ensure correctness of the mouse clicks. + if (group_len > stl_items[stl_groupitems[groupdepth]].maxwid + && stl_items[stl_groupitems[groupdepth]].type != HighlightFold) { // { Determine the number of bytes to remove // Find the first character that should be included. @@ -1637,7 +1639,7 @@ stcsign: if (fdc > 0) { schar_T fold_buf[9]; - fill_foldcolumn(wp, stcp->foldinfo, lnum, 0, fdc, NULL, fold_buf); + fill_foldcolumn(wp, stcp->foldinfo, lnum, 0, fdc, NULL, stcp->fold_vcol, fold_buf); stl_items[curitem].minwid = -(use_cursor_line_highlight(wp, lnum) ? HLF_CLF : HLF_FC); size_t buflen = 0; // TODO(bfredl): this is very backwards. we must support schar_T diff --git a/src/nvim/statusline_defs.h b/src/nvim/statusline_defs.h index f640d63150..83dda1e035 100644 --- a/src/nvim/statusline_defs.h +++ b/src/nvim/statusline_defs.h @@ -103,5 +103,6 @@ typedef struct { bool draw; ///< whether to draw the statuscolumn stl_hlrec_t *hlrec; ///< highlight groups foldinfo_T foldinfo; ///< fold information + colnr_T fold_vcol[9]; ///< vcol array filled for fold item SignTextAttrs *sattrs; ///< sign attributes } statuscol_T; diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua index 220c573b13..255eeb4754 100644 --- a/test/functional/ui/statuscolumn_spec.lua +++ b/test/functional/ui/statuscolumn_spec.lua @@ -13,8 +13,6 @@ local api = n.api local pcall_err = t.pcall_err local assert_alive = n.assert_alive -local mousemodels = { 'extend', 'popup', 'popup_setpos' } - describe('statuscolumn', function() local screen before_each(function() @@ -592,7 +590,7 @@ describe('statuscolumn', function() ]]) end) - for _, model in ipairs(mousemodels) do + for _, model in ipairs({ 'extend', 'popup', 'popup_setpos' }) do describe('with mousemodel=' .. model, function() before_each(function() command('set mousemodel=' .. model) @@ -651,23 +649,56 @@ describe('statuscolumn', function() -- Check that statusline click doesn't register as statuscolumn click api.nvim_input_mouse('right', 'press', '', 0, 12, 0) eq('', eval('g:testvar')) + -- Check that rightclick still opens popupmenu if there is no clickdef + if model == 'popup' then + api.nvim_set_option_value('statuscolumn', '%0@MyClickFunc@%=%l%TNoClick', {}) + api.nvim_input_mouse('right', 'press', '', 0, 1, 0) + screen:expect([[ + {5:[No Name] }| + {8: 4NoClick}^aaaaa | + {8: 5NoClick}aaaaa | + {8: 6NoClick}aaaaa | + {8: 7NoClick}aaaaa | + {8: 8NoClick}aaaaa | + {8: 9NoClick}aaaaa | + {8:10NoClick}aaaaa | + {8:11NoClick}aaaaa | + {8:12NoClick}aaaaa | + {8:13NoClick}aaaaa | + {8:14NoClick}aaaaa | + {3:[No Name] [+] }| + | + ]]) + api.nvim_input_mouse('right', 'press', '', 0, 1, 3) + screen:expect([[ + {5:[No Name] }| + {8: 4NoClick}^aaaaa | + {8: 5}{4: Inspect } | + {8: 6}{4: } | + {8: 7}{4: Paste } | + {8: 8}{4: Select All } | + {8: 9}{4: } | + {8:10}{4: How-to disable mouse } | + {8:11NoClick}aaaaa | + {8:12NoClick}aaaaa | + {8:13NoClick}aaaaa | + {8:14NoClick}aaaaa | + {3:[No Name] [+] }| + | + ]]) + end end) it('clicks and highlights work with control characters', function() api.nvim_set_option_value('statuscolumn', '\t%#NonText#\1%0@MyClickFunc@\t\1%T\t%##\1', {}) - screen:expect { - grid = [[ - {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |*4 - {1:^I}{0:^A^I^A^I}{1:^A}^aaaaa | - {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |*8 + screen:expect([[ + {8:^I}{1:^A^I^A^I}{8:^A}aaaaa |*4 + {8:^I}{1:^A^I^A^I}{8:^A}^aaaaa | + {8:^I}{1:^A^I^A^I}{8:^A}aaaaa |*8 | - ]], - attr_ids = { - [0] = { foreground = Screen.colors.Blue, bold = true }, -- NonText - [1] = { foreground = Screen.colors.Brown }, -- LineNr - }, - } + ]]) api.nvim_input_mouse('right', 'press', '', 0, 4, 3) + feed('<Esc>') -- Close popupmenu eq('', eval('g:testvar')) api.nvim_input_mouse('left', 'press', '', 0, 5, 8) eq('', eval('g:testvar')) @@ -713,6 +744,36 @@ describe('statuscolumn', function() | ]]) end) + + it('foldcolumn item can be clicked', function() + api.nvim_set_option_value('statuscolumn', '|%C|', {}) + api.nvim_set_option_value('foldcolumn', '2', {}) + api.nvim_set_option_value('mousetime', 0, {}) + feed('ggzfjzfjzo') + local s1 = [[ + {8:|}{7:-+}{8:|}{13:^+--- 2 lines: aaaaa·····························}| + {8:|}{7:│ }{8:|}aaaaa | + {8:|}{7: }{8:|}aaaaa |*11 + | + ]] + screen:expect(s1) + api.nvim_input_mouse('left', 'press', '', 0, 0, 2) + screen:expect([[ + {8:|}{7:--}{8:|}^aaaaa | + {8:|}{7:││}{8:|}aaaaa | + {8:|}{7:│ }{8:|}aaaaa | + {8:|}{7: }{8:|}aaaaa |*10 + | + ]]) + api.nvim_input_mouse('left', 'press', '', 0, 0, 1) + screen:expect(s1) + api.nvim_input_mouse('left', 'press', '', 0, 0, 1) + screen:expect([[ + {8:|}{7:+ }{8:|}{13:^+-- 3 lines: aaaaa······························}| + {8:|}{7: }{8:|}aaaaa |*12 + | + ]]) + end) end) end |