aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-12-26 13:40:33 +0800
committerGitHub <noreply@github.com>2022-12-26 13:40:33 +0800
commit522b15e2a4d0a0f5a9e5958efa4ffcbb3606f131 (patch)
tree455961489867e2fa0c489a2bd4ff779a90d792fd
parent357aab4c65c49a924481a67e17a10bd04c334ab9 (diff)
parent5b89d480e30367259f82680945572b1406219da5 (diff)
downloadrneovim-522b15e2a4d0a0f5a9e5958efa4ffcbb3606f131.tar.gz
rneovim-522b15e2a4d0a0f5a9e5958efa4ffcbb3606f131.tar.bz2
rneovim-522b15e2a4d0a0f5a9e5958efa4ffcbb3606f131.zip
Merge pull request #21202 from luukvbaal/statusline
feat: add 'showcmdloc' option and statusline item
-rw-r--r--runtime/doc/news.txt7
-rw-r--r--runtime/doc/options.txt18
-rw-r--r--src/nvim/normal.c21
-rw-r--r--src/nvim/normal.h6
-rw-r--r--src/nvim/option_defs.h6
-rw-r--r--src/nvim/options.lua7
-rw-r--r--src/nvim/optionstr.c5
-rw-r--r--src/nvim/statusline.c28
-rw-r--r--src/nvim/testdir/test_statusline.vim22
-rw-r--r--src/nvim/testdir/test_tabline.vim21
-rw-r--r--src/nvim/vim.h2
-rw-r--r--test/functional/legacy/statusline_spec.lua47
-rw-r--r--test/functional/legacy/tabline_spec.lua53
13 files changed, 228 insertions, 15 deletions
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 2ce0bd4de2..d6f6464f78 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -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.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index c3bec5a0c1..b0c4193927 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -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.
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index d6fa1f5a16..1f7cc6c4f6 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -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);
diff --git a/src/nvim/normal.h b/src/nvim/normal.h
index 43d892e49a..90a5c4103e 100644
--- a/src/nvim/normal.h
+++ b/src/nvim/normal.h
@@ -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
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index de07327416..34c1d3a255 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -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'
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 3c2fb1797b..232c645eb0 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2184,6 +2184,13 @@ return {
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"),
type='bool', scope={'global'},
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index cd87db9aa9..106a4fbadf 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -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'
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
index 34df46f448..6aaad8cc59 100644
--- a/src/nvim/statusline.c
+++ b/src/nvim/statusline.c
@@ -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;
diff --git a/src/nvim/testdir/test_statusline.vim b/src/nvim/testdir/test_statusline.vim
index 6bde052442..25ab1cf518 100644
--- a/src/nvim/testdir/test_statusline.vim
+++ b/src/nvim/testdir/test_statusline.vim
@@ -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
diff --git a/src/nvim/testdir/test_tabline.vim b/src/nvim/testdir/test_tabline.vim
index 556b85931c..20a9657f32 100644
--- a/src/nvim/testdir/test_tabline.vim
+++ b/src/nvim/testdir/test_tabline.vim
@@ -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
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index 59b818fad7..bfe75ef9f7 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -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.
diff --git a/test/functional/legacy/statusline_spec.lua b/test/functional/legacy/statusline_spec.lua
index e2b30a7c82..056209154e 100644
--- a/test/functional/legacy/statusline_spec.lua
+++ b/test/functional/legacy/statusline_spec.lua
@@ -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)
diff --git a/test/functional/legacy/tabline_spec.lua b/test/functional/legacy/tabline_spec.lua
new file mode 100644
index 0000000000..d858f137c5
--- /dev/null
+++ b/test/functional/legacy/tabline_spec.lua
@@ -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)