diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-12-26 13:40:33 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-26 13:40:33 +0800 |
commit | 522b15e2a4d0a0f5a9e5958efa4ffcbb3606f131 (patch) | |
tree | 455961489867e2fa0c489a2bd4ff779a90d792fd | |
parent | 357aab4c65c49a924481a67e17a10bd04c334ab9 (diff) | |
parent | 5b89d480e30367259f82680945572b1406219da5 (diff) | |
download | rneovim-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.txt | 7 | ||||
-rw-r--r-- | runtime/doc/options.txt | 18 | ||||
-rw-r--r-- | src/nvim/normal.c | 21 | ||||
-rw-r--r-- | src/nvim/normal.h | 6 | ||||
-rw-r--r-- | src/nvim/option_defs.h | 6 | ||||
-rw-r--r-- | src/nvim/options.lua | 7 | ||||
-rw-r--r-- | src/nvim/optionstr.c | 5 | ||||
-rw-r--r-- | src/nvim/statusline.c | 28 | ||||
-rw-r--r-- | src/nvim/testdir/test_statusline.vim | 22 | ||||
-rw-r--r-- | src/nvim/testdir/test_tabline.vim | 21 | ||||
-rw-r--r-- | src/nvim/vim.h | 2 | ||||
-rw-r--r-- | test/functional/legacy/statusline_spec.lua | 47 | ||||
-rw-r--r-- | test/functional/legacy/tabline_spec.lua | 53 |
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) |