vim-patch:9.0.1061: cannot display 'showcmd' somewhere else

Problem:    Cannot display 'showcmd' somewhere else.
Solution:   Add the 'showcmdloc' option. (Luuk van Baal, closes vim/vim#11684)

ba936f6f4e

Co-authored-by: Luuk van Baal <luukvbaal@gmail.com>
This commit is contained in:
Luuk van Baal 2022-12-15 21:23:28 +01:00 committed by zeertzjq
parent 357aab4c65
commit 5b89d480e3
13 changed files with 228 additions and 15 deletions

View File

@ -86,7 +86,12 @@ The following new APIs or features were added.
• When using Nvim inside tmux 3.2 or later, the default clipboard provider
will now copy to the system clipboard. |provider-clipboard|
• 'splitkeep' option to control the scroll behavior of horizontal splits.
• |'showcmdloc'| option to display the 'showcmd' information in the
status line or tab line. A new %S statusline item is available to place
the 'showcmd' text in a custom 'statusline'. Useful for when |'cmdheight'|
is set to 0.
• |'splitkeep'| option to control the scroll behavior of horizontal splits.
• |nvim_select_popupmenu_item()| now supports |cmdline-completion| popup menu.

View File

@ -5641,7 +5641,6 @@ A jump table for the options with a short description can be found at |Q_op|.
global
Show (partial) command in the last line of the screen. Set this
option off if your terminal is slow.
The option has no effect when 'cmdheight' is zero.
In Visual mode the size of the selected area is shown:
- When selecting characters within a line, the number of characters.
If the number of bytes is different it is also displayed: "2-6"
@ -5649,6 +5648,22 @@ A jump table for the options with a short description can be found at |Q_op|.
- When selecting more than one line, the number of lines.
- When selecting a block, the size in screen characters:
{lines}x{columns}.
This information can be displayed in an alternative location using the
'showcmdloc' option, useful when 'cmdheight' is 0.
*'showcmdloc'* *'sloc'*
'showcmdloc' 'sloc' string (default "last")
This option can be used to display the (partially) entered command in
another location. Possible values are:
last Last line of the screen (default).
statusline Status line of the current window.
tabline First line of the screen if 'showtabline' is enabled.
Setting this option to "statusline" or "tabline" means that these will
be redrawn whenever the command changes, which can be on every key
pressed.
The %S 'statusline' item can be used in 'statusline' or 'tabline' to
place the text. Without a custom 'statusline' or 'tabline' it will be
displayed in a convenient location.
*'showfulltag'* *'sft'* *'noshowfulltag'* *'nosft'*
'showfulltag' 'sft' boolean (default off)
@ -6120,6 +6135,7 @@ A jump table for the options with a short description can be found at |Q_op|.
P S Percentage through file of displayed window. This is like the
percentage described for 'ruler'. Always 3 in length, unless
translated.
S S 'showcmd' content, see 'showcmdloc'.
a S Argument list status as in default title. ({current} of {max})
Empty if the argument file count is zero or one.
{ NF Evaluate expression between '%{' and '}' and substitute result.

View File

@ -68,6 +68,7 @@
#include "nvim/spellfile.h"
#include "nvim/spellsuggest.h"
#include "nvim/state.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/tag.h"
@ -1782,8 +1783,6 @@ void may_clear_cmdline(void)
}
// Routines for displaying a partly typed command
#define SHOWCMD_BUFLEN (SHOWCMD_COLS + 1 + 30)
static char showcmd_buf[SHOWCMD_BUFLEN];
static char_u old_showcmd_buf[SHOWCMD_BUFLEN]; // For push_showcmd()
static bool showcmd_is_clear = true;
static bool showcmd_visual = false;
@ -1977,14 +1976,20 @@ void pop_showcmd(void)
static void display_showcmd(void)
{
if (p_ch == 0 && !ui_has(kUIMessages)) {
// TODO(bfredl): would be nice to show in global statusline, perhaps
int len = (int)strlen(showcmd_buf);
showcmd_is_clear = (len == 0);
if (*p_sloc == 's') {
win_redr_status(curwin);
setcursor(); // put cursor back where it belongs
return;
}
int len;
len = (int)strlen(showcmd_buf);
showcmd_is_clear = (len == 0);
if (*p_sloc == 't') {
draw_tabline();
setcursor(); // put cursor back where it belongs
return;
}
// 'showcmdloc' is "last" or empty
if (ui_has(kUIMessages)) {
MAXSIZE_TEMP_ARRAY(content, 1);

View File

@ -72,6 +72,12 @@ typedef struct cmdarg_S {
#define CA_COMMAND_BUSY 1 // skip restarting edit() once
#define CA_NO_ADJ_OP_END 2 // don't adjust operator end
// columns needed by shown command
#define SHOWCMD_COLS 10
// 'showcmd' buffer shared between normal.c and statusline.c
#define SHOWCMD_BUFLEN (SHOWCMD_COLS + 1 + 30)
EXTERN char showcmd_buf[SHOWCMD_BUFLEN];
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "normal.h.generated.h"
#endif

View File

@ -336,6 +336,7 @@ enum {
STL_ALTPERCENT = 'P', ///< Percentage as TOP BOT ALL or NN%.
STL_ARGLISTSTAT = 'a', ///< Argument list status as (x of y).
STL_PAGENUM = 'N', ///< Page number (when printing).
STL_SHOWCMD = 'S', ///< 'showcmd' buffer
STL_VIM_EXPR = '{', ///< Start of expression to substitute.
STL_SEPARATE = '=', ///< Separation between alignment sections.
STL_TRUNCMARK = '<', ///< Truncation mark if line is too long.
@ -353,8 +354,8 @@ enum {
STL_HELPFLAG, STL_HELPFLAG_ALT, STL_FILETYPE, STL_FILETYPE_ALT, \
STL_PREVIEWFLAG, STL_PREVIEWFLAG_ALT, STL_MODIFIED, STL_MODIFIED_ALT, \
STL_QUICKFIX, STL_PERCENTAGE, STL_ALTPERCENT, STL_ARGLISTSTAT, STL_PAGENUM, \
STL_VIM_EXPR, STL_SEPARATE, STL_TRUNCMARK, STL_USER_HL, STL_HIGHLIGHT, \
STL_TABPAGENR, STL_TABCLOSENR, STL_CLICK_FUNC, \
STL_SHOWCMD, STL_VIM_EXPR, STL_SEPARATE, STL_TRUNCMARK, STL_USER_HL, \
STL_HIGHLIGHT, STL_TABPAGENR, STL_TABCLOSENR, STL_CLICK_FUNC, \
0, \
})
@ -696,6 +697,7 @@ EXTERN long p_sw; ///< 'shiftwidth'
EXTERN char *p_shm; // 'shortmess'
EXTERN char *p_sbr; // 'showbreak'
EXTERN int p_sc; // 'showcmd'
EXTERN char *p_sloc; // 'showcmdloc'
EXTERN int p_sft; // 'showfulltag'
EXTERN int p_sm; // 'showmatch'
EXTERN int p_smd; // 'showmode'

View File

@ -2183,6 +2183,13 @@ return {
varname='p_sc',
defaults={if_true=true}
},
{
full_name='showcmdloc', abbreviation='sloc',
short_desc=N_("change location of partial command"),
type='string', scope={'global'},
varname='p_sloc',
defaults={if_true="last"}
},
{
full_name='showfulltag', abbreviation='sft',
short_desc=N_("show full tag pattern when completing tag"),

View File

@ -126,6 +126,7 @@ static char *(p_icm_values[]) = { "nosplit", "split", NULL };
static char *(p_jop_values[]) = { "stack", "view", NULL };
static char *(p_tpf_values[]) = { "BS", "HT", "FF", "ESC", "DEL", "C0", "C1", NULL };
static char *(p_rdb_values[]) = { "compositor", "nothrottle", "invalid", "nodelta", NULL };
static char *(p_sloc_values[]) = { "last", "statusline", "tabline", NULL };
/// All possible flags for 'shm'.
static char SHM_ALL[] = { SHM_RO, SHM_MOD, SHM_FILE, SHM_LAST, SHM_TEXT, SHM_LINES, SHM_NEW,
@ -1275,6 +1276,10 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
&& (curwin->w_p_nu || curwin->w_p_rnu)) {
curwin->w_nrwidth_line_count = 0;
}
} else if (varp == &p_sloc) { // 'showcmdloc'
if (check_opt_strings(p_sloc, p_sloc_values, false) != OK) {
errmsg = e_invarg;
}
} else if (varp == &curwin->w_p_fdc
|| varp == &curwin->w_allbuf_opt.wo_fdc) {
// 'foldcolumn'

View File

@ -163,6 +163,16 @@ void win_redr_status(win_T *wp)
}
win_redr_ruler(wp, true);
// Draw the 'showcmd' information if 'showcmdloc' == "statusline".
if (p_sc && *p_sloc == 's') {
int sc_width = MIN(10, this_ru_col - len - 2);
if (width > 0) {
grid_puts_len(&default_grid, showcmd_buf, sc_width, row,
wp->w_wincol + this_ru_col - sc_width - 1, attr);
}
}
}
// May need to draw the character below the vertical separator.
@ -832,8 +842,18 @@ void draw_tabline(void)
}
grid_fill(&default_grid, 0, 1, col, Columns, c, c, attr_fill);
// Draw the 'showcmd' information if 'showcmdloc' == "tabline".
if (p_sc && *p_sloc == 't') {
int width = MIN(10, (int)Columns - col - (tabcount > 1) * 3);
if (width > 0) {
grid_puts_len(&default_grid, showcmd_buf, width, 0,
Columns - width - (tabcount > 1) * 2, attr_nosel);
}
}
// Put an "X" for closing the current tab if there are several.
if (first_tabpage->tp_next != NULL) {
if (tabcount > 1) {
grid_putchar(&default_grid, 'X', 0, Columns - 1, attr_nosel);
tab_page_click_defs[Columns - 1] = (StlClickDefinition) {
.type = kStlClickTabClose,
@ -1485,6 +1505,12 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
str = buf_tmp;
break;
case STL_SHOWCMD:
if (p_sc && strcmp(opt_name, p_sloc) == 0) {
str = showcmd_buf;
}
break;
case STL_ARGLISTSTAT:
fillable = false;

View File

@ -565,4 +565,26 @@ func Test_statusline_highlight_truncate()
call delete('XTest_statusline')
endfunc
func Test_statusline_showcmd()
CheckScreendump
let lines =<< trim END
set laststatus=2
set statusline=%S
set showcmdloc=statusline
call setline(1, ['a', 'b', 'c'])
END
call writefile(lines, 'XTest_statusline', 'D')
let buf = RunVimInTerminal('-S XTest_statusline', {'rows': 6})
call feedkeys("\<C-V>Gl", "xt")
call VerifyScreenDump(buf, 'Test_statusline_showcmd_1', {})
call feedkeys("\<Esc>1234", "xt")
call VerifyScreenDump(buf, 'Test_statusline_showcmd_2', {})
call feedkeys("\<Esc>:set statusline=\<CR>:\<CR>1234", "xt")
call VerifyScreenDump(buf, 'Test_statusline_showcmd_3', {})
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -1,6 +1,9 @@
" Test for tabline
source shared.vim
source view_util.vim
source check.vim
source screendump.vim
func TablineWithCaughtError()
let s:func_in_tabline_called = 1
@ -160,5 +163,23 @@ func Test_mouse_click_in_tab()
call delete('Xclickscript')
endfunc
func Test_tabline_showcmd()
CheckScreendump
let lines =<< trim END
set showtabline=2
set showcmdloc=tabline
call setline(1, ['a', 'b', 'c'])
END
call writefile(lines, 'XTest_tabline', 'D')
let buf = RunVimInTerminal('-S XTest_tabline', {'rows': 6})
call feedkeys("\<C-V>Gl", "xt")
call VerifyScreenDump(buf, 'Test_tabline_showcmd_1', {})
call feedkeys("\<Esc>1234", "xt")
call VerifyScreenDump(buf, 'Test_tabline_showcmd_2', {})
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -235,8 +235,6 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext()
// destination and mess up the screen.
#define PERROR(msg) (void)semsg("%s: %s", (msg), strerror(errno))
#define SHOWCMD_COLS 10 // columns needed by shown command
#include "nvim/path.h"
// Enums need a typecast to be used as array index.

View File

@ -68,4 +68,51 @@ describe('statusline', function()
|
]])
end)
-- oldtest: Test_statusline_showcmd()
it('showcmdloc=statusline works', function()
screen:set_default_attr_ids({
[0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
[1] = {background = Screen.colors.LightGrey}, -- Visual
[2] = {bold = true}, -- MoreMsg
[3] = {bold = true, reverse = true}, -- StatusLine
})
exec([[
set showcmd
set laststatus=2
set statusline=%S
set showcmdloc=statusline
call setline(1, ['a', 'b', 'c'])
]])
feed('<C-V>Gl')
screen:expect([[
{1:a} |
{1:b} |
{1:c}^ |
{0:~ }|
{0:~ }|
{3:3x2 }|
{2:-- VISUAL BLOCK --} |
]])
feed('<Esc>1234')
screen:expect([[
a |
b |
^c |
{0:~ }|
{0:~ }|
{3:1234 }|
|
]])
feed('<Esc>:set statusline=<CR>:<CR>1234')
screen:expect([[
a |
b |
^c |
{0:~ }|
{0:~ }|
{3:[No Name] [+] 1234 }|
: |
]])
end)
end)

View File

@ -0,0 +1,53 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local exec = helpers.exec
local feed = helpers.feed
before_each(clear)
describe('tabline', function()
local screen
before_each(function()
screen = Screen.new(50, 7)
screen:attach()
end)
-- oldtest: Test_tabline_showcmd()
it('showcmdloc=tabline works', function()
screen:set_default_attr_ids({
[0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
[1] = {background = Screen.colors.LightGrey}, -- Visual
[2] = {bold = true}, -- MoreMsg, TabLineSel
[3] = {reverse = true}, -- TabLineFill
[4] = {background = Screen.colors.LightGrey, underline = true}, -- TabLine
})
exec([[
set showcmd
set showtabline=2
set showcmdloc=tabline
call setline(1, ['a', 'b', 'c'])
]])
feed('<C-V>Gl')
screen:expect([[
{2: + [No Name] }{3: }{4:3x2}{3: }|
{1:a} |
{1:b} |
{1:c}^ |
{0:~ }|
{0:~ }|
{2:-- VISUAL BLOCK --} |
]])
feed('<Esc>1234')
screen:expect([[
{2: + [No Name] }{3: }{4:1234}{3: }|
a |
b |
^c |
{0:~ }|
{0:~ }|
|
]])
end)
end)