1
mirror of https://github.com/neovim/neovim.git synced 2024-12-27 14:21:31 -07:00

Compare commits

...

17 Commits

Author SHA1 Message Date
glepnir
630e8b8919
Merge 2e94406ba0 into 02bc40c194 2024-12-18 23:58:42 -03:00
zeertzjq
02bc40c194
vim-patch:9.1.0945: ComplMatchIns highlight doesn't end after inserted text ()
Problem:  ComplMatchIns highlight doesn't end after inserted text.
Solution: Handle ComplMatchIns highlight more like search highlight.
          Fix off-by-one error. Handle deleting text properly.
          (zeertzjq)

closes: 

f25d8f9312
2024-12-18 23:59:03 +00:00
luukvbaal
160cbd0ef4
test(cursor_spec): global highlight definitions () 2024-12-18 19:06:16 +00:00
Gregory Anders
3db3947b0e
fix(terminal): restore cursor from 'guicursor' on TermLeave ()
Fixes: https://github.com/neovim/neovim/issues/31612
2024-12-18 11:41:05 -06:00
Lewis Russell
7121983c45 refactor(man.lua): various changes
- Replace all uses of vim.regex with simpler Lua patterns.
- Replace all uses of vim.fn.substitute with string.gsub.
- Rework error handling so expected errors are passed back via a return.
  - These get routed up an passed to `vim.notify()`
  - Any other errors will cause a stack trace.
- Reworked the module initialization of `localfile_arg`
- Updated all type annotations.
- Refactored CLI completion by introduction a parse_cmdline()
  function.
- Simplified `show_toc()`
- Refactor highlighting
- Inline some functions
- Fix completion on MacOS 13 and earlier.
  - Prefer `manpath -q` over `man -w`
- Make completion more efficient by avoiding vim.fn.sort and vim.fn.uniq
  - Reimplement using a single loop
2024-12-18 14:40:36 +00:00
phanium
888a803755
fix(lsp): vim.lsp.start fails if existing client has no workspace_folders
Problem:
regression since https://github.com/neovim/neovim/pull/31340

`nvim -l repro.lua`:
```lua
vim.lsp.start { cmd = { 'lua-language-server' }, name = 'lua_ls' }
vim.lsp.start { cmd = { 'lua-language-server' }, name = 'lua_ls', root_dir = 'foo' }

-- swapped case will be ok:
-- vim.lsp.start { cmd = { 'lua-language-server' }, name = 'lua_ls', root_dir = 'foo' }
-- vim.lsp.start { cmd = { 'lua-language-server' }, name = 'lua_ls' }
```

Failure:
```
E5113: Error while calling lua chunk: /…/lua/vim/lsp.lua:214: bad argument  to
'ipairs' (table expected, got nil)
stack traceback:
        [C]: in function 'ipairs'
        /…/lua/vim/lsp.lua:214: in function 'reuse_client'
        /…/lua/vim/lsp.lua:629: in function 'start'
        repro.lua:34: in main chunk
```
2024-12-18 06:37:12 -08:00
Peter Lithammer
07d5dc8938
feat(lsp): show server version in :checkhealth
Problem:
Language server version information missing from `:checkhealth vim.lsp`.

Solution:
Store `InitializeResult.serverInfo.version` from the `initialize`
response and display for each client in `:checkhealth vim.lsp`.
2024-12-18 06:31:25 -08:00
Justin M. Keyes
f9eb68f340
fix(coverity): error handling CHECKED_RETURN
CID 516406:  Error handling issues  (CHECKED_RETURN)
    /src/nvim/api/vimscript.c: 284 in nvim_call_dict_function()
    278       Object rv = OBJECT_INIT;
    279
    280       typval_T rettv;
    281       bool mustfree = false;
    282       switch (dict.type) {
    283       case kObjectTypeString:
    >>>     CID 516406:  Error handling issues  (CHECKED_RETURN)
    >>>     Calling "eval0" without checking return value (as is done elsewhere 10 out of 12 times).
    284         TRY_WRAP(err, {
    285           eval0(dict.data.string.data, &rettv, NULL, &EVALARG_EVALUATE);
    286           clear_evalarg(&EVALARG_EVALUATE, NULL);
    287         });
    288         if (ERROR_SET(err)) {
    289           return rv;
2024-12-18 06:05:37 -08:00
zeertzjq
738320188f
test(old): fix incorrect comment in test_preview.vim () 2024-12-18 10:21:52 +08:00
zeertzjq
38f554e9c4
vim-patch:a977883: runtime(doc): Fix style in fold.txt ()
closes: 

a977883ef3

Co-authored-by: h-east <h.east.727@gmail.com>
2024-12-18 09:12:04 +08:00
zeertzjq
f7c42433c5
vim-patch:9.1.0940: Wrong cursor shape with "gq" and 'indentexpr' executes :normal ()
Problem:  Wrong cursor shape with "gq" and 'indentexpr' executes :normal
Solution: Update cursor and mouse shape after restoring old_State.
          (zeertzjq)

closes: 

Solution: Update cursor and mouse shape after restoring old_State.

6c3027744e
2024-12-18 09:04:32 +08:00
zeertzjq
51c380238c
Merge pull request from zeertzjq/vim-9.1.0936
vim-patch:9.1.{0936,0941,0942}: ComplMatchIns highlight
2024-12-18 08:40:23 +08:00
zeertzjq
b7da54aa9e vim-patch:9.1.0942: a few typos were found
Problem:  a few typos were found
Solution: fix them (zeertzjq)

closes: 

d32bf0a067
2024-12-18 08:15:31 +08:00
zeertzjq
2f7b385f2e vim-patch:9.1.0941: ComplMatchIns doesn't work after multibyte chars
Problem:  ComplMatchIns doesn't work after multibyte chars
          (after v9.1.0936)
Solution: Use (ptr - line) instead of wlv.col (zeertzjq).

closes: 

f4ccada5c3
2024-12-18 08:15:31 +08:00
zeertzjq
c830901e8c vim-patch:9.1.0936: cannot highlight completed text
Problem:  cannot highlight completed text
Solution: (optionally) highlight auto-completed text using the
          ComplMatchIns highlight group (glepnir)

closes: 

6a38aff218

Co-authored-by: glepnir <glephunter@gmail.com>
2024-12-18 08:15:31 +08:00
Gregory Anders
0dd933265f
feat(terminal)!: cursor shape and blink ()
When a terminal application running inside the terminal emulator sets
the cursor shape or blink status of the cursor, update the cursor in the
parent terminal to match.

This removes the "virtual cursor" that has been in use by the terminal
emulator since the beginning. The original rationale for using the
virtual cursor was to avoid having to support additional UI methods to
change the cursor color for other (non-TUI) UIs, instead relying on the
TermCursor and TermCursorNC highlight groups.

The TermCursor highlight group is now used in the default 'guicursor'
value, which has a new entry for Terminal mode. However, the
TermCursorNC highlight group is no longer supported: since terminal
windows now use the real cursor, when the window is not focused there is
no cursor displayed in the window at all, so there is nothing to
highlight. Users can still use the StatusLineTermNC highlight group to
differentiate non-focused terminal windows.

BREAKING CHANGE: The TermCursorNC highlight group is no longer supported.
2024-12-17 07:11:41 -06:00
glepnir
2e94406ba0 feat(api): nvim_cmd support plus flags
Problem: currently nvim_cmd can not handle plus flags correct.

Solution: add plus flags support.
2024-09-01 21:31:16 +08:00
65 changed files with 1951 additions and 982 deletions

View File

@ -60,6 +60,7 @@ hi('PmenuMatch', { link = 'Pmenu' })
hi('PmenuMatchSel', { link = 'PmenuSel' }) hi('PmenuMatchSel', { link = 'PmenuSel' })
hi('PmenuExtra', { link = 'Pmenu' }) hi('PmenuExtra', { link = 'Pmenu' })
hi('PmenuExtraSel', { link = 'PmenuSel' }) hi('PmenuExtraSel', { link = 'PmenuSel' })
hi('ComplMatchIns', {})
hi('Substitute', { link = 'Search' }) hi('Substitute', { link = 'Search' })
hi('Whitespace', { link = 'NonText' }) hi('Whitespace', { link = 'NonText' })
hi('MsgSeparator', { link = 'StatusLine' }) hi('MsgSeparator', { link = 'StatusLine' })

View File

@ -38,6 +38,10 @@ DIAGNOSTICS
- The "cursor_position" parameter of |vim.diagnostic.JumpOpts| is renamed to - The "cursor_position" parameter of |vim.diagnostic.JumpOpts| is renamed to
"pos" "pos"
HIGHLIGHTS
• *TermCursorNC* As of Nvim 0.11, unfocused |terminal| windows no
longer have any cursor.
TREESITTER TREESITTER
• *TSNode:child_containing_descendant()* Use • *TSNode:child_containing_descendant()* Use
|TSNode:child_with_descendant()| instead; it is identical except that it can |TSNode:child_with_descendant()| instead; it is identical except that it can

View File

@ -101,7 +101,8 @@ The result of foldexpr then determines the fold level as follows:
"<1", "<2", .. a fold with this level ends at this line "<1", "<2", .. a fold with this level ends at this line
">1", ">2", .. a fold with this level starts at this line ">1", ">2", .. a fold with this level starts at this line
The result values "=", "s" and "a" are more expensive, please see |fold-expr-slow|. The result values "=", "s" and "a" are more expensive, please see
|fold-expr-slow|.
It is not required to mark the start (end) of a fold with ">1" ("<1"), a fold It is not required to mark the start (end) of a fold with ">1" ("<1"), a fold
will also start (end) when the fold level is higher (lower) than the fold will also start (end) when the fold level is higher (lower) than the fold
@ -141,7 +142,7 @@ end in that line.
It may happen that folds are not updated properly. You can use |zx| or |zX| It may happen that folds are not updated properly. You can use |zx| or |zX|
to force updating folds. to force updating folds.
Minimizing Computational Cost *fold-expr-slow* MINIMIZING COMPUTATIONAL COST *fold-expr-slow*
Due to its computational cost, this fold method can make Vim unresponsive, Due to its computational cost, this fold method can make Vim unresponsive,
especially when the fold level of all lines have to be initially computed. especially when the fold level of all lines have to be initially computed.
@ -149,13 +150,15 @@ Afterwards, after each change, Vim restricts the computation of foldlevels
to those lines whose fold level was affected by it (and reuses the known to those lines whose fold level was affected by it (and reuses the known
foldlevels of all the others). foldlevels of all the others).
The fold expression should therefore strive to minimize the number of dependent The fold expression should therefore strive to minimize the number of
lines needed for the computation of a given line: For example, try to avoid the dependent lines needed for the computation of a given line: For example, try
"=", "a" and "s" return values, because these will require the evaluation of the to avoid the "=", "a" and "s" return values, because these will require the
fold levels on previous lines until an independent fold level is found. evaluation of the fold levels on previous lines until an independent fold
level is found.
If this proves difficult, the next best thing could be to cache all fold levels If this proves difficult, the next best thing could be to cache all fold
in a buffer-local variable (b:foldlevels) that is only updated on |b:changedtick|: levels in a buffer-local variable (b:foldlevels) that is only updated on
|b:changedtick|:
>vim >vim
func MyFoldFunc() func MyFoldFunc()
if b:lasttick == b:changedtick if b:lasttick == b:changedtick
@ -406,8 +409,8 @@ zX Undo manually opened and closed folds: re-apply 'foldlevel'.
Also forces recomputing folds, like |zx|. Also forces recomputing folds, like |zx|.
*zm* *zm*
zm Fold more: Subtract |v:count1| from 'foldlevel'. If 'foldlevel' was zm Fold more: Subtract |v:count1| from 'foldlevel'. If
already zero nothing happens. 'foldlevel' was already zero nothing happens.
'foldenable' will be set. 'foldenable' will be set.
*zM* *zM*

View File

@ -1126,6 +1126,9 @@ Lua module: vim.lsp.client *lsp-client*
• {server_capabilities} (`lsp.ServerCapabilities?`) Response from the • {server_capabilities} (`lsp.ServerCapabilities?`) Response from the
server sent on `initialize` describing the server sent on `initialize` describing the
server's capabilities. server's capabilities.
• {server_info} (`lsp.ServerInfo?`) Response from the server
sent on `initialize` describing information
about the server.
• {progress} (`vim.lsp.Client.Progress`) A ring buffer • {progress} (`vim.lsp.Client.Progress`) A ring buffer
(|vim.ringbuf()|) containing progress messages (|vim.ringbuf()|) containing progress messages
sent by the server. See sent by the server. See

View File

@ -118,8 +118,8 @@ Note that when using ":" any motion becomes charwise exclusive.
*inclusive-motion-selection-exclusive* *inclusive-motion-selection-exclusive*
When 'selection' is "exclusive", |Visual| mode is active and an inclusive When 'selection' is "exclusive", |Visual| mode is active and an inclusive
motion has been used, the cursor position will be adjusted by another motion has been used, the cursor position will be adjusted by another
character to the right, so that visual selction includes the expected text and character to the right, so that the Visual selection includes the expected
can be acted upon. text and can be acted upon.
*forced-motion* *forced-motion*
FORCING A MOTION TO BE LINEWISE, CHARWISE OR BLOCKWISE FORCING A MOTION TO BE LINEWISE, CHARWISE OR BLOCKWISE

View File

@ -87,6 +87,11 @@ EVENTS
• |vim.ui_attach()| callbacks for |ui-messages| `msg_show` events are executed in • |vim.ui_attach()| callbacks for |ui-messages| `msg_show` events are executed in
|api-fast| context. |api-fast| context.
HIGHLIGHTS
• |TermCursorNC| is removed and no longer supported. Unfocused terminals no
longer have a cursor.
LSP LSP
• Improved rendering of LSP hover docs. |K-lsp-default| • Improved rendering of LSP hover docs. |K-lsp-default|
@ -110,6 +115,7 @@ LSP
• |vim.lsp.util.make_position_params()|, |vim.lsp.util.make_range_params()| • |vim.lsp.util.make_position_params()|, |vim.lsp.util.make_range_params()|
and |vim.lsp.util.make_given_range_params()| now require the `position_encoding` and |vim.lsp.util.make_given_range_params()| now require the `position_encoding`
parameter. parameter.
• `:checkhealth vim.lsp` displays the server version (if available).
LUA LUA
@ -211,6 +217,7 @@ EDITOR
• On Windows, filename arguments on the command-line prefixed with "~\" or • On Windows, filename arguments on the command-line prefixed with "~\" or
"~/" are now expanded to the user's profile directory, not a relative path "~/" are now expanded to the user's profile directory, not a relative path
to a literal "~" directory. to a literal "~" directory.
• |hl-ComplMatchIns| shows matched text of the currently inserted completion.
• |hl-PmenuMatch| and |hl-PmenuMatchSel| show matched text in completion popup. • |hl-PmenuMatch| and |hl-PmenuMatchSel| show matched text in completion popup.
EVENTS EVENTS
@ -281,6 +288,12 @@ TERMINAL
'scrollback' are not reflown. 'scrollback' are not reflown.
• The |terminal| now supports OSC 8 escape sequences and will display • The |terminal| now supports OSC 8 escape sequences and will display
hyperlinks in supporting host terminals. hyperlinks in supporting host terminals.
• The |terminal| now uses the actual cursor, rather than a "virtual" cursor.
This means that escape codes sent by applications running in a terminal
buffer can change the cursor shape and visibility. However, it also
means that the |TermCursorNC| highlight group is no longer supported: an
unfocused terminal window will have no cursor at all (so there is nothing to
highlight).
TREESITTER TREESITTER

View File

@ -2977,7 +2977,7 @@ A jump table for the options with a short description can be found at |Q_op|.
An |OptionSet| autocmd can be used to set it up to match automatically. An |OptionSet| autocmd can be used to set it up to match automatically.
*'guicursor'* *'gcr'* *E545* *E546* *E548* *E549* *'guicursor'* *'gcr'* *E545* *E546* *E548* *E549*
'guicursor' 'gcr' string (default "n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20") 'guicursor' 'gcr' string (default "n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20,t:block-blinkon500-blinkoff500-TermCursor")
global global
Configures the cursor style for each mode. Works in the GUI and many Configures the cursor style for each mode. Works in the GUI and many
terminals. See |tui-cursor-shape|. terminals. See |tui-cursor-shape|.
@ -3005,6 +3005,7 @@ A jump table for the options with a short description can be found at |Q_op|.
ci Command-line Insert mode ci Command-line Insert mode
cr Command-line Replace mode cr Command-line Replace mode
sm showmatch in Insert mode sm showmatch in Insert mode
t Terminal mode
a all modes a all modes
The argument-list is a dash separated list of these arguments: The argument-list is a dash separated list of these arguments:
hor{N} horizontal bar, {N} percent of the character height hor{N} horizontal bar, {N} percent of the character height
@ -3021,7 +3022,8 @@ A jump table for the options with a short description can be found at |Q_op|.
cursor is not shown. Times are in msec. When one of cursor is not shown. Times are in msec. When one of
the numbers is zero, there is no blinking. E.g.: >vim the numbers is zero, there is no blinking. E.g.: >vim
set guicursor=n:blinkon0 set guicursor=n:blinkon0
< - Default is "blinkon0" for each mode. <
Default is "blinkon0" for each mode.
{group-name} {group-name}
Highlight group that decides the color and font of the Highlight group that decides the color and font of the
cursor. cursor.

View File

@ -5162,8 +5162,6 @@ EndOfBuffer Filler lines (~) after the end of the buffer.
By default, this is highlighted like |hl-NonText|. By default, this is highlighted like |hl-NonText|.
*hl-TermCursor* *hl-TermCursor*
TermCursor Cursor in a focused terminal. TermCursor Cursor in a focused terminal.
*hl-TermCursorNC*
TermCursorNC Cursor in an unfocused terminal.
*hl-ErrorMsg* *hl-ErrorMsg*
ErrorMsg Error messages on the command line. ErrorMsg Error messages on the command line.
*hl-WinSeparator* *hl-WinSeparator*
@ -5245,6 +5243,8 @@ PmenuMatch Popup menu: Matched text in normal item. Combined with
*hl-PmenuMatchSel* *hl-PmenuMatchSel*
PmenuMatchSel Popup menu: Matched text in selected item. Combined with PmenuMatchSel Popup menu: Matched text in selected item. Combined with
|hl-PmenuMatch| and |hl-PmenuSel|. |hl-PmenuMatch| and |hl-PmenuSel|.
*hl-ComplMatchIns*
ComplMatchIns Matched text of the currently inserted completion.
*hl-Question* *hl-Question*
Question |hit-enter| prompt and yes/no questions. Question |hit-enter| prompt and yes/no questions.
*hl-QuickFixLine* *hl-QuickFixLine*

View File

@ -101,7 +101,7 @@ Configuration *terminal-config*
Options: 'modified', 'scrollback' Options: 'modified', 'scrollback'
Events: |TermOpen|, |TermEnter|, |TermLeave|, |TermClose| Events: |TermOpen|, |TermEnter|, |TermLeave|, |TermClose|
Highlight groups: |hl-TermCursor|, |hl-TermCursorNC| Highlight groups: |hl-TermCursor|
Terminal sets local defaults for some options, which may differ from your Terminal sets local defaults for some options, which may differ from your
global configuration. global configuration.

View File

@ -325,7 +325,6 @@ Highlight groups:
- |hl-MsgSeparator| highlights separator for scrolled messages - |hl-MsgSeparator| highlights separator for scrolled messages
- |hl-Substitute| - |hl-Substitute|
- |hl-TermCursor| - |hl-TermCursor|
- |hl-TermCursorNC|
- |hl-WinSeparator| highlights window separators - |hl-WinSeparator| highlights window separators
- |hl-Whitespace| highlights 'listchars' whitespace - |hl-Whitespace| highlights 'listchars' whitespace
- |hl-WinBar| highlights 'winbar' - |hl-WinBar| highlights 'winbar'

File diff suppressed because it is too large Load Diff

View File

@ -2783,6 +2783,7 @@ vim.go.gp = vim.go.grepprg
--- ci Command-line Insert mode --- ci Command-line Insert mode
--- cr Command-line Replace mode --- cr Command-line Replace mode
--- sm showmatch in Insert mode --- sm showmatch in Insert mode
--- t Terminal mode
--- a all modes --- a all modes
--- The argument-list is a dash separated list of these arguments: --- The argument-list is a dash separated list of these arguments:
--- hor{N} horizontal bar, {N} percent of the character height --- hor{N} horizontal bar, {N} percent of the character height
@ -2802,7 +2803,8 @@ vim.go.gp = vim.go.grepprg
--- ```vim --- ```vim
--- set guicursor=n:blinkon0 --- set guicursor=n:blinkon0
--- ``` --- ```
--- - Default is "blinkon0" for each mode. ---
--- Default is "blinkon0" for each mode.
--- {group-name} --- {group-name}
--- Highlight group that decides the color and font of the --- Highlight group that decides the color and font of the
--- cursor. --- cursor.
@ -2848,7 +2850,7 @@ vim.go.gp = vim.go.grepprg
--- ---
--- ---
--- @type string --- @type string
vim.o.guicursor = "n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20" vim.o.guicursor = "n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20,t:block-blinkon500-blinkoff500-TermCursor"
vim.o.gcr = vim.o.guicursor vim.o.gcr = vim.o.guicursor
vim.go.guicursor = vim.o.guicursor vim.go.guicursor = vim.o.guicursor
vim.go.gcr = vim.go.guicursor vim.go.gcr = vim.go.guicursor

View File

@ -211,7 +211,7 @@ local function reuse_client_default(client, config)
for _, config_folder in ipairs(config_folders) do for _, config_folder in ipairs(config_folders) do
local found = false local found = false
for _, client_folder in ipairs(client.workspace_folders) do for _, client_folder in ipairs(client.workspace_folders or {}) do
if config_folder.uri == client_folder.uri then if config_folder.uri == client_folder.uri then
found = true found = true
break break

View File

@ -174,6 +174,10 @@ local validate = vim.validate
--- capabilities. --- capabilities.
--- @field server_capabilities lsp.ServerCapabilities? --- @field server_capabilities lsp.ServerCapabilities?
--- ---
--- Response from the server sent on `initialize` describing information about
--- the server.
--- @field server_info lsp.ServerInfo?
---
--- A ring buffer (|vim.ringbuf()|) containing progress messages --- A ring buffer (|vim.ringbuf()|) containing progress messages
--- sent by the server. --- sent by the server.
--- @field progress vim.lsp.Client.Progress --- @field progress vim.lsp.Client.Progress
@ -556,6 +560,8 @@ function Client:initialize()
self.offset_encoding = self.server_capabilities.positionEncoding self.offset_encoding = self.server_capabilities.positionEncoding
end end
self.server_info = result.serverInfo
if next(self.settings) then if next(self.settings) then
self:notify(ms.workspace_didChangeConfiguration, { settings = self.settings }) self:notify(ms.workspace_didChangeConfiguration, { settings = self.settings })
end end

View File

@ -40,6 +40,8 @@ local function check_active_clients()
local clients = vim.lsp.get_clients() local clients = vim.lsp.get_clients()
if next(clients) then if next(clients) then
for _, client in pairs(clients) do for _, client in pairs(clients) do
local server_version = vim.tbl_get(client, 'server_info', 'version')
or '? (no serverInfo.version response)'
local cmd ---@type string local cmd ---@type string
local ccmd = client.config.cmd local ccmd = client.config.cmd
if type(ccmd) == 'table' then if type(ccmd) == 'table' then
@ -62,6 +64,7 @@ local function check_active_clients()
end end
report_info(table.concat({ report_info(table.concat({
string.format('%s (id: %d)', client.name, client.id), string.format('%s (id: %d)', client.name, client.id),
string.format('- Version: %s', server_version),
dirs_info, dirs_info,
string.format('- Command: %s', cmd), string.format('- Command: %s', cmd),
string.format('- Settings: %s', vim.inspect(client.settings, { newline = '\n ' })), string.format('- Settings: %s', vim.inspect(client.settings, { newline = '\n ' })),

View File

@ -8,9 +8,9 @@ vim.api.nvim_create_user_command('Man', function(params)
if params.bang then if params.bang then
man.init_pager() man.init_pager()
else else
local ok, err = pcall(man.open_page, params.count, params.smods, params.fargs) local err = man.open_page(params.count, params.smods, params.fargs)
if not ok then if err then
vim.notify(man.errormsg or err, vim.log.levels.ERROR) vim.notify('man.lua: ' .. err, vim.log.levels.ERROR)
end end
end end
end, { end, {
@ -31,6 +31,9 @@ vim.api.nvim_create_autocmd('BufReadCmd', {
pattern = 'man://*', pattern = 'man://*',
nested = true, nested = true,
callback = function(params) callback = function(params)
require('man').read_page(vim.fn.matchstr(params.match, 'man://\\zs.*')) local err = require('man').read_page(assert(params.match:match('man://(.*)')))
if err then
vim.notify('man.lua: ' .. err, vim.log.levels.ERROR)
end
end, end,
}) })

View File

@ -63,7 +63,7 @@ syn keyword vimGroup contained Comment Constant String Character Number Boolean
syn keyword vimHLGroup contained ErrorMsg IncSearch ModeMsg NonText StatusLine StatusLineNC EndOfBuffer VertSplit DiffText PmenuSbar TabLineSel TabLineFill Cursor lCursor QuickFixLine CursorLineSign CursorLineFold CurSearch PmenuKind PmenuKindSel PmenuMatch PmenuMatchSel PmenuExtra PmenuExtraSel Normal Directory LineNr CursorLineNr MoreMsg Question Search SpellBad SpellCap SpellRare SpellLocal PmenuThumb Pmenu PmenuSel SpecialKey Title WarningMsg WildMenu Folded FoldColumn SignColumn Visual DiffAdd DiffChange DiffDelete TabLine CursorColumn CursorLine ColorColumn MatchParen StatusLineTerm StatusLineTermNC CursorIM LineNrAbove LineNrBelow syn keyword vimHLGroup contained ErrorMsg IncSearch ModeMsg NonText StatusLine StatusLineNC EndOfBuffer VertSplit DiffText PmenuSbar TabLineSel TabLineFill Cursor lCursor QuickFixLine CursorLineSign CursorLineFold CurSearch PmenuKind PmenuKindSel PmenuMatch PmenuMatchSel PmenuExtra PmenuExtraSel Normal Directory LineNr CursorLineNr MoreMsg Question Search SpellBad SpellCap SpellRare SpellLocal PmenuThumb Pmenu PmenuSel SpecialKey Title WarningMsg WildMenu Folded FoldColumn SignColumn Visual DiffAdd DiffChange DiffDelete TabLine CursorColumn CursorLine ColorColumn MatchParen StatusLineTerm StatusLineTermNC CursorIM LineNrAbove LineNrBelow
syn match vimHLGroup contained "\<Conceal\>" syn match vimHLGroup contained "\<Conceal\>"
syn keyword vimOnlyHLGroup contained Menu Scrollbar ToolbarButton ToolbarLine Tooltip VisualNOS syn keyword vimOnlyHLGroup contained Menu Scrollbar ToolbarButton ToolbarLine Tooltip VisualNOS
syn keyword nvimHLGroup contained FloatBorder FloatFooter FloatTitle MsgSeparator NormalFloat NormalNC Substitute TermCursor TermCursorNC VisualNC Whitespace WinBar WinBarNC WinSeparator syn keyword nvimHLGroup contained FloatBorder FloatFooter FloatTitle MsgSeparator NormalFloat NormalNC Substitute TermCursor VisualNC Whitespace WinBar WinBarNC WinSeparator
"}}}2 "}}}2
syn case match syn case match

View File

@ -27,6 +27,7 @@
#include "nvim/mbyte.h" #include "nvim/mbyte.h"
#include "nvim/memory.h" #include "nvim/memory.h"
#include "nvim/ops.h" #include "nvim/ops.h"
#include "nvim/optionstr.h"
#include "nvim/pos_defs.h" #include "nvim/pos_defs.h"
#include "nvim/regexp.h" #include "nvim/regexp.h"
#include "nvim/strings.h" #include "nvim/strings.h"
@ -317,7 +318,6 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Arena
char *cmdline = NULL; char *cmdline = NULL;
char *cmdname = NULL; char *cmdname = NULL;
ArrayOf(String) args = ARRAY_DICT_INIT; ArrayOf(String) args = ARRAY_DICT_INIT;
String retv = (String)STRING_INIT; String retv = (String)STRING_INIT;
#define OBJ_TO_BOOL(var, value, default, varname) \ #define OBJ_TO_BOOL(var, value, default, varname) \
@ -633,6 +633,24 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Arena
build_cmdline_str(&cmdline, &ea, &cmdinfo, args); build_cmdline_str(&cmdline, &ea, &cmdinfo, args);
ea.cmdlinep = &cmdline; ea.cmdlinep = &cmdline;
// set when Not Implemented
const int ni = is_cmd_ni(ea.cmdidx);
// Check for "++opt=val" argument.
if (ea.argt & EX_ARGOPT) {
while (ea.arg[0] == '+' && ea.arg[1] == '+') {
if (getargopt(&ea) == FAIL && !ni) {
api_set_error(err, kErrorTypeValidation, "Invalid argument");
goto end;
}
}
}
// Check for "+command" argument.
if ((ea.argt & EX_CMDARG) && !ea.usefilter) {
ea.do_ecmd_cmd = getargcmd(&ea.arg);
}
garray_T capture_local; garray_T capture_local;
const int save_msg_silent = msg_silent; const int save_msg_silent = msg_silent;
garray_T * const save_capture_ga = capture_ga; garray_T * const save_capture_ga = capture_ga;

View File

@ -229,10 +229,9 @@ static Object _call_function(String fn, Array args, dict_T *self, Arena *arena,
funcexe.fe_selfdict = self; funcexe.fe_selfdict = self;
TRY_WRAP(err, { TRY_WRAP(err, {
// call_func() retval is deceptive, ignore it. Instead we set `msg_list` // call_func() retval is deceptive, ignore it. Instead TRY_WRAP sets `msg_list` to capture
// (see above) to capture abort-causing non-exception errors. // abort-causing non-exception errors.
call_func(fn.data, (int)fn.size, &rettv, (int)args.size, (void)call_func(fn.data, (int)fn.size, &rettv, (int)args.size, vim_args, &funcexe);
vim_args, &funcexe);
}); });
if (!ERROR_SET(err)) { if (!ERROR_SET(err)) {
@ -280,18 +279,23 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Arena *arena,
typval_T rettv; typval_T rettv;
bool mustfree = false; bool mustfree = false;
switch (dict.type) { switch (dict.type) {
case kObjectTypeString: case kObjectTypeString: {
int eval_ret;
TRY_WRAP(err, { TRY_WRAP(err, {
eval0(dict.data.string.data, &rettv, NULL, &EVALARG_EVALUATE); eval_ret = eval0(dict.data.string.data, &rettv, NULL, &EVALARG_EVALUATE);
clear_evalarg(&EVALARG_EVALUATE, NULL); clear_evalarg(&EVALARG_EVALUATE, NULL);
}); });
if (ERROR_SET(err)) { if (ERROR_SET(err)) {
return rv; return rv;
} }
if (eval_ret != OK) {
abort(); // Should not happen.
}
// Evaluation of the string arg created a new dict or increased the // Evaluation of the string arg created a new dict or increased the
// refcount of a dict. Not necessary for a RPC dict. // refcount of a dict. Not necessary for a RPC dict.
mustfree = true; mustfree = true;
break; break;
}
case kObjectTypeDict: case kObjectTypeDict:
object_to_vim(dict, &rettv, err); object_to_vim(dict, &rettv, err);
break; break;

View File

@ -341,9 +341,11 @@ void check_cursor_col(win_T *win)
} else if (win->w_cursor.col >= len) { } else if (win->w_cursor.col >= len) {
// Allow cursor past end-of-line when: // Allow cursor past end-of-line when:
// - in Insert mode or restarting Insert mode // - in Insert mode or restarting Insert mode
// - in Terminal mode
// - in Visual mode and 'selection' isn't "old" // - in Visual mode and 'selection' isn't "old"
// - 'virtualedit' is set // - 'virtualedit' is set
if ((State & MODE_INSERT) || restart_edit if ((State & MODE_INSERT) || restart_edit
|| (State & MODE_TERMINAL)
|| (VIsual_active && *p_sel != 'o') || (VIsual_active && *p_sel != 'o')
|| (cur_ve_flags & kOptVeFlagOnemore) || (cur_ve_flags & kOptVeFlagOnemore)
|| virtual_active(win)) { || virtual_active(win)) {

View File

@ -45,6 +45,7 @@ cursorentry_T shape_table[SHAPE_IDX_COUNT] = {
{ "more", 0, 0, 0, 0, 0, 0, 0, 0, "m", SHAPE_MOUSE }, { "more", 0, 0, 0, 0, 0, 0, 0, 0, "m", SHAPE_MOUSE },
{ "more_lastline", 0, 0, 0, 0, 0, 0, 0, 0, "ml", SHAPE_MOUSE }, { "more_lastline", 0, 0, 0, 0, 0, 0, 0, 0, "ml", SHAPE_MOUSE },
{ "showmatch", 0, 0, 0, 100, 100, 100, 0, 0, "sm", SHAPE_CURSOR }, { "showmatch", 0, 0, 0, 100, 100, 100, 0, 0, "sm", SHAPE_CURSOR },
{ "terminal", 0, 0, 0, 0, 0, 0, 0, 0, "t", SHAPE_CURSOR },
}; };
/// Converts cursor_shapes into an Array of Dictionaries /// Converts cursor_shapes into an Array of Dictionaries
@ -321,6 +322,8 @@ int cursor_get_mode_idx(void)
{ {
if (State == MODE_SHOWMATCH) { if (State == MODE_SHOWMATCH) {
return SHAPE_IDX_SM; return SHAPE_IDX_SM;
} else if (State == MODE_TERMINAL) {
return SHAPE_IDX_TERM;
} else if (State & VREPLACE_FLAG) { } else if (State & VREPLACE_FLAG) {
return SHAPE_IDX_R; return SHAPE_IDX_R;
} else if (State & REPLACE_FLAG) { } else if (State & REPLACE_FLAG) {

View File

@ -23,7 +23,8 @@ typedef enum {
SHAPE_IDX_MORE = 14, ///< Hit-return or More SHAPE_IDX_MORE = 14, ///< Hit-return or More
SHAPE_IDX_MOREL = 15, ///< Hit-return or More in last line SHAPE_IDX_MOREL = 15, ///< Hit-return or More in last line
SHAPE_IDX_SM = 16, ///< showing matching paren SHAPE_IDX_SM = 16, ///< showing matching paren
SHAPE_IDX_COUNT = 17, SHAPE_IDX_TERM = 17, ///< Terminal mode
SHAPE_IDX_COUNT = 18,
} ModeShape; } ModeShape;
typedef enum { typedef enum {

View File

@ -31,6 +31,7 @@
#include "nvim/highlight_defs.h" #include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h" #include "nvim/highlight_group.h"
#include "nvim/indent.h" #include "nvim/indent.h"
#include "nvim/insexpand.h"
#include "nvim/mark_defs.h" #include "nvim/mark_defs.h"
#include "nvim/marktree_defs.h" #include "nvim/marktree_defs.h"
#include "nvim/match.h" #include "nvim/match.h"
@ -934,6 +935,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
colnr_T vcol_prev = -1; // "wlv.vcol" of previous character colnr_T vcol_prev = -1; // "wlv.vcol" of previous character
ScreenGrid *grid = &wp->w_grid; // grid specific to the window ScreenGrid *grid = &wp->w_grid; // grid specific to the window
const bool in_curline = wp == curwin && lnum == curwin->w_cursor.lnum;
const bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0; const bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0;
const bool has_foldtext = has_fold && *wp->w_p_fdt != NUL; const bool has_foldtext = has_fold && *wp->w_p_fdt != NUL;
@ -953,7 +955,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
bool area_highlighting = false; // Visual or incsearch highlighting in this line bool area_highlighting = false; // Visual or incsearch highlighting in this line
int vi_attr = 0; // attributes for Visual and incsearch highlighting int vi_attr = 0; // attributes for Visual and incsearch highlighting
int area_attr = 0; // attributes desired by highlighting int area_attr = 0; // attributes desired by highlighting
int search_attr = 0; // attributes desired by 'hlsearch' int search_attr = 0; // attributes desired by 'hlsearch' or ComplMatchIns
int vcol_save_attr = 0; // saved attr for 'cursorcolumn' int vcol_save_attr = 0; // saved attr for 'cursorcolumn'
int decor_attr = 0; // attributes desired by syntax and extmarks int decor_attr = 0; // attributes desired by syntax and extmarks
bool has_syntax = false; // this buffer has syntax highl. bool has_syntax = false; // this buffer has syntax highl.
@ -967,7 +969,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
int spell_attr = 0; // attributes desired by spelling int spell_attr = 0; // attributes desired by spelling
int word_end = 0; // last byte with same spell_attr int word_end = 0; // last byte with same spell_attr
int cur_checked_col = 0; // checked column for current line int cur_checked_col = 0; // checked column for current line
bool extra_check = 0; // has syntax or linebreak bool extra_check = false; // has extra highlighting
int multi_attr = 0; // attributes desired by multibyte int multi_attr = 0; // attributes desired by multibyte
int mb_l = 1; // multi-byte byte length int mb_l = 1; // multi-byte byte length
int mb_c = 0; // decoded multi-byte character int mb_c = 0; // decoded multi-byte character
@ -1117,7 +1119,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
} }
// Check if the char under the cursor should be inverted (highlighted). // Check if the char under the cursor should be inverted (highlighted).
if (!highlight_match && lnum == curwin->w_cursor.lnum && wp == curwin if (!highlight_match && in_curline
&& cursor_is_block_during_visual(*p_sel == 'e')) { && cursor_is_block_during_visual(*p_sel == 'e')) {
noinvcur = true; noinvcur = true;
} }
@ -1493,6 +1495,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
ptr = line + v; // "line" may have been updated ptr = line + v; // "line" may have been updated
} }
if ((State & MODE_INSERT) && in_curline && ins_compl_active()) {
area_highlighting = true;
}
win_line_start(wp, &wlv); win_line_start(wp, &wlv);
bool draw_cols = true; bool draw_cols = true;
int leftcols_width = 0; int leftcols_width = 0;
@ -1629,8 +1635,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
} }
// When still displaying '$' of change command, stop at cursor. // When still displaying '$' of change command, stop at cursor.
if (dollar_vcol >= 0 && wp == curwin if (dollar_vcol >= 0 && in_curline && wlv.vcol >= wp->w_virtcol) {
&& lnum == wp->w_cursor.lnum && wlv.vcol >= wp->w_virtcol) {
draw_virt_text(wp, buf, win_col_offset, &wlv.col, wlv.row); draw_virt_text(wp, buf, win_col_offset, &wlv.col, wlv.row);
// don't clear anything after wlv.col // don't clear anything after wlv.col
wlv_put_linebuf(wp, &wlv, wlv.col, false, bg_attr, 0); wlv_put_linebuf(wp, &wlv, wlv.col, false, bg_attr, 0);
@ -1739,6 +1744,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
if (*ptr == NUL) { if (*ptr == NUL) {
has_match_conc = 0; has_match_conc = 0;
} }
// Check if ComplMatchIns highlight is needed.
if ((State & MODE_INSERT) && in_curline && ins_compl_active()) {
int ins_match_attr = ins_compl_col_range_attr((int)(ptr - line));
if (ins_match_attr > 0) {
search_attr = hl_combine_attr(search_attr, ins_match_attr);
}
}
} }
if (wlv.diff_hlf != (hlf_T)0) { if (wlv.diff_hlf != (hlf_T)0) {
@ -2446,8 +2459,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
// With 'virtualedit' we may never reach cursor position, but we still // With 'virtualedit' we may never reach cursor position, but we still
// need to correct the cursor column, so do that at end of line. // need to correct the cursor column, so do that at end of line.
if (!did_wcol && wlv.filler_todo <= 0 if (!did_wcol && wlv.filler_todo <= 0
&& wp == curwin && lnum == wp->w_cursor.lnum && in_curline && conceal_cursor_line(wp)
&& conceal_cursor_line(wp)
&& (wlv.vcol + wlv.skip_cells >= wp->w_virtcol || mb_schar == NUL)) { && (wlv.vcol + wlv.skip_cells >= wp->w_virtcol || mb_schar == NUL)) {
wp->w_wcol = wlv.col - wlv.boguscols; wp->w_wcol = wlv.col - wlv.boguscols;
if (wlv.vcol + wlv.skip_cells < wp->w_virtcol) { if (wlv.vcol + wlv.skip_cells < wp->w_virtcol) {
@ -2640,7 +2652,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
// Update w_cline_height and w_cline_folded if the cursor line was // Update w_cline_height and w_cline_folded if the cursor line was
// updated (saves a call to plines_win() later). // updated (saves a call to plines_win() later).
if (wp == curwin && lnum == curwin->w_cursor.lnum) { if (in_curline) {
curwin->w_cline_row = startrow; curwin->w_cline_row = startrow;
curwin->w_cline_height = wlv.row - startrow; curwin->w_cline_height = wlv.row - startrow;
curwin->w_cline_folded = has_fold; curwin->w_cline_folded = has_fold;

View File

@ -4135,7 +4135,7 @@ void separate_nextcmd(exarg_T *eap)
} }
/// get + command from ex argument /// get + command from ex argument
static char *getargcmd(char **argp) char *getargcmd(char **argp)
{ {
char *arg = *argp; char *arg = *argp;
char *command = NULL; char *command = NULL;
@ -4210,7 +4210,7 @@ static char *get_bad_name(expand_T *xp FUNC_ATTR_UNUSED, int idx)
/// Get "++opt=arg" argument. /// Get "++opt=arg" argument.
/// ///
/// @return FAIL or OK. /// @return FAIL or OK.
static int getargopt(exarg_T *eap) int getargopt(exarg_T *eap)
{ {
char *arg = eap->arg + 2; char *arg = eap->arg + 2;
int *pp = NULL; int *pp = NULL;

View File

@ -15,7 +15,6 @@ EXTERN const char *hlf_names[] INIT( = {
[HLF_8] = "SpecialKey", [HLF_8] = "SpecialKey",
[HLF_EOB] = "EndOfBuffer", [HLF_EOB] = "EndOfBuffer",
[HLF_TERM] = "TermCursor", [HLF_TERM] = "TermCursor",
[HLF_TERMNC] = "TermCursorNC",
[HLF_AT] = "NonText", [HLF_AT] = "NonText",
[HLF_D] = "Directory", [HLF_D] = "Directory",
[HLF_E] = "ErrorMsg", [HLF_E] = "ErrorMsg",

View File

@ -63,7 +63,6 @@ typedef enum {
///< displayed different from what it is ///< displayed different from what it is
HLF_EOB, ///< after the last line in the buffer HLF_EOB, ///< after the last line in the buffer
HLF_TERM, ///< terminal cursor focused HLF_TERM, ///< terminal cursor focused
HLF_TERMNC, ///< terminal cursor unfocused
HLF_AT, ///< @ characters at end of screen, characters that don't really exist in the text HLF_AT, ///< @ characters at end of screen, characters that don't really exist in the text
HLF_D, ///< directories in CTRL-D listing HLF_D, ///< directories in CTRL-D listing
HLF_E, ///< error messages HLF_E, ///< error messages

View File

@ -173,12 +173,12 @@ static const char *highlight_init_both[] = {
"default link PmenuKind Pmenu", "default link PmenuKind Pmenu",
"default link PmenuKindSel PmenuSel", "default link PmenuKindSel PmenuSel",
"default link PmenuSbar Pmenu", "default link PmenuSbar Pmenu",
"default link ComplMatchIns NONE",
"default link Substitute Search", "default link Substitute Search",
"default link StatusLineTerm StatusLine", "default link StatusLineTerm StatusLine",
"default link StatusLineTermNC StatusLineNC", "default link StatusLineTermNC StatusLineNC",
"default link TabLine StatusLineNC", "default link TabLine StatusLineNC",
"default link TabLineFill TabLine", "default link TabLineFill TabLine",
"default link TermCursorNC NONE",
"default link VertSplit WinSeparator", "default link VertSplit WinSeparator",
"default link VisualNOS Visual", "default link VisualNOS Visual",
"default link Whitespace NonText", "default link Whitespace NonText",

View File

@ -256,6 +256,7 @@ static pos_T compl_startpos;
static int compl_length = 0; static int compl_length = 0;
static colnr_T compl_col = 0; ///< column where the text starts static colnr_T compl_col = 0; ///< column where the text starts
///< that is being completed ///< that is being completed
static colnr_T compl_ins_end_col = 0;
static char *compl_orig_text = NULL; ///< text as it was before static char *compl_orig_text = NULL; ///< text as it was before
///< completion started ///< completion started
/// Undo information to restore extmarks for original text. /// Undo information to restore extmarks for original text.
@ -282,6 +283,11 @@ static size_t spell_bad_len = 0; // length of located bad word
static int compl_selected_item = -1; static int compl_selected_item = -1;
// "compl_match_array" points the currently displayed list of entries in the
// popup menu. It is NULL when there is no popup menu.
static pumitem_T *compl_match_array = NULL;
static int compl_match_arraysize;
/// CTRL-X pressed in Insert mode. /// CTRL-X pressed in Insert mode.
void ins_ctrl_x(void) void ins_ctrl_x(void)
{ {
@ -943,6 +949,30 @@ static bool ins_compl_equal(compl_T *match, char *str, size_t len)
return strncmp(match->cp_str, str, len) == 0; return strncmp(match->cp_str, str, len) == 0;
} }
/// when len is -1 mean use whole length of p otherwise part of p
static void ins_compl_insert_bytes(char *p, int len)
FUNC_ATTR_NONNULL_ALL
{
if (len == -1) {
len = (int)strlen(p);
}
assert(len >= 0);
ins_bytes_len(p, (size_t)len);
compl_ins_end_col = curwin->w_cursor.col;
}
/// Checks if the column is within the currently inserted completion text
/// column range. If it is, it returns a special highlight attribute.
/// -1 mean normal item.
int ins_compl_col_range_attr(int col)
{
if (col >= compl_col && col < compl_ins_end_col) {
return syn_name2attr("ComplMatchIns");
}
return -1;
}
/// Reduce the longest common string for match "match". /// Reduce the longest common string for match "match".
static void ins_compl_longest_match(compl_T *match) static void ins_compl_longest_match(compl_T *match)
{ {
@ -952,7 +982,7 @@ static void ins_compl_longest_match(compl_T *match)
bool had_match = (curwin->w_cursor.col > compl_col); bool had_match = (curwin->w_cursor.col > compl_col);
ins_compl_delete(false); ins_compl_delete(false);
ins_bytes(compl_leader + get_compl_len()); ins_compl_insert_bytes(compl_leader + get_compl_len(), -1);
ins_redraw(false); ins_redraw(false);
// When the match isn't there (to avoid matching itself) remove it // When the match isn't there (to avoid matching itself) remove it
@ -986,7 +1016,7 @@ static void ins_compl_longest_match(compl_T *match)
*p = NUL; *p = NUL;
bool had_match = (curwin->w_cursor.col > compl_col); bool had_match = (curwin->w_cursor.col > compl_col);
ins_compl_delete(false); ins_compl_delete(false);
ins_bytes(compl_leader + get_compl_len()); ins_compl_insert_bytes(compl_leader + get_compl_len(), -1);
ins_redraw(false); ins_redraw(false);
// When the match isn't there (to avoid matching itself) remove it // When the match isn't there (to avoid matching itself) remove it
@ -1058,11 +1088,6 @@ unsigned get_cot_flags(void)
return curbuf->b_cot_flags != 0 ? curbuf->b_cot_flags : cot_flags; return curbuf->b_cot_flags != 0 ? curbuf->b_cot_flags : cot_flags;
} }
/// "compl_match_array" points the currently displayed list of entries in the
/// popup menu. It is NULL when there is no popup menu.
static pumitem_T *compl_match_array = NULL;
static int compl_match_arraysize;
/// Remove any popup menu. /// Remove any popup menu.
static void ins_compl_del_pum(void) static void ins_compl_del_pum(void)
{ {
@ -1678,6 +1703,7 @@ void ins_compl_clear(void)
compl_cont_status = 0; compl_cont_status = 0;
compl_started = false; compl_started = false;
compl_matches = 0; compl_matches = 0;
compl_ins_end_col = 0;
XFREE_CLEAR(compl_pattern); XFREE_CLEAR(compl_pattern);
compl_patternlen = 0; compl_patternlen = 0;
XFREE_CLEAR(compl_leader); XFREE_CLEAR(compl_leader);
@ -1802,7 +1828,7 @@ static void ins_compl_new_leader(void)
{ {
ins_compl_del_pum(); ins_compl_del_pum();
ins_compl_delete(true); ins_compl_delete(true);
ins_bytes(compl_leader + get_compl_len()); ins_compl_insert_bytes(compl_leader + get_compl_len(), -1);
compl_used_match = false; compl_used_match = false;
if (compl_started) { if (compl_started) {
@ -2121,6 +2147,8 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval)
&& pum_visible()) { && pum_visible()) {
word = xstrdup(compl_shown_match->cp_str); word = xstrdup(compl_shown_match->cp_str);
retval = true; retval = true;
// May need to remove ComplMatchIns highlight.
redrawWinline(curwin, curwin->w_cursor.lnum);
} }
// CTRL-E means completion is Ended, go back to the typed text. // CTRL-E means completion is Ended, go back to the typed text.
@ -2137,7 +2165,7 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval)
const int compl_len = get_compl_len(); const int compl_len = get_compl_len();
const int len = (int)strlen(p); const int len = (int)strlen(p);
if (len > compl_len) { if (len > compl_len) {
ins_bytes_len(p + compl_len, (size_t)(len - compl_len)); ins_compl_insert_bytes(p + compl_len, len - compl_len);
} }
} }
restore_orig_extmarks(); restore_orig_extmarks();
@ -3622,6 +3650,7 @@ void ins_compl_delete(bool new_leader)
return; return;
} }
backspace_until_column(col); backspace_until_column(col);
compl_ins_end_col = curwin->w_cursor.col;
} }
// TODO(vim): is this sufficient for redrawing? Redrawing everything // TODO(vim): is this sufficient for redrawing? Redrawing everything
@ -3639,7 +3668,7 @@ void ins_compl_insert(bool in_compl_func)
// Make sure we don't go over the end of the string, this can happen with // Make sure we don't go over the end of the string, this can happen with
// illegal bytes. // illegal bytes.
if (compl_len < (int)strlen(compl_shown_match->cp_str)) { if (compl_len < (int)strlen(compl_shown_match->cp_str)) {
ins_bytes(compl_shown_match->cp_str + compl_len); ins_compl_insert_bytes(compl_shown_match->cp_str + compl_len, -1);
} }
compl_used_match = !match_at_original_text(compl_shown_match); compl_used_match = !match_at_original_text(compl_shown_match);
@ -3888,14 +3917,15 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
// Insert the text of the new completion, or the compl_leader. // Insert the text of the new completion, or the compl_leader.
if (compl_no_insert && !started) { if (compl_no_insert && !started) {
ins_bytes(compl_orig_text + get_compl_len()); ins_compl_insert_bytes(compl_orig_text + get_compl_len(), -1);
compl_used_match = false; compl_used_match = false;
restore_orig_extmarks(); restore_orig_extmarks();
} else if (insert_match) { } else if (insert_match) {
if (!compl_get_longest || compl_used_match) { if (!compl_get_longest || compl_used_match) {
ins_compl_insert(in_compl_func); ins_compl_insert(in_compl_func);
} else { } else {
ins_bytes(compl_leader + get_compl_len()); assert(compl_leader != NULL);
ins_compl_insert_bytes(compl_leader + get_compl_len(), -1);
} }
if (!strcmp(compl_curr_match->cp_str, compl_orig_text)) { if (!strcmp(compl_curr_match->cp_str, compl_orig_text)) {
restore_orig_extmarks(); restore_orig_extmarks();

View File

@ -12,7 +12,7 @@
// option_vars.h: definition of global variables for settable options // option_vars.h: definition of global variables for settable options
#define HIGHLIGHT_INIT \ #define HIGHLIGHT_INIT \
"8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText,d:Directory,e:ErrorMsg," \ "8:SpecialKey,~:EndOfBuffer,z:TermCursor,@:NonText,d:Directory,e:ErrorMsg," \
"i:IncSearch,l:Search,y:CurSearch,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow," \ "i:IncSearch,l:Search,y:CurSearch,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow," \
"N:CursorLineNr,G:CursorLineSign,O:CursorLineFold,r:Question,s:StatusLine,S:StatusLineNC," \ "N:CursorLineNr,G:CursorLineSign,O:CursorLineFold,r:Question,s:StatusLine,S:StatusLineNC," \
"c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn," \ "c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn," \

View File

@ -3631,7 +3631,9 @@ return {
{ {
abbreviation = 'gcr', abbreviation = 'gcr',
cb = 'did_set_guicursor', cb = 'did_set_guicursor',
defaults = { if_true = 'n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20' }, defaults = {
if_true = 'n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20,t:block-blinkon500-blinkoff500-TermCursor',
},
deny_duplicates = true, deny_duplicates = true,
desc = [=[ desc = [=[
Configures the cursor style for each mode. Works in the GUI and many Configures the cursor style for each mode. Works in the GUI and many
@ -3660,6 +3662,7 @@ return {
ci Command-line Insert mode ci Command-line Insert mode
cr Command-line Replace mode cr Command-line Replace mode
sm showmatch in Insert mode sm showmatch in Insert mode
t Terminal mode
a all modes a all modes
The argument-list is a dash separated list of these arguments: The argument-list is a dash separated list of these arguments:
hor{N} horizontal bar, {N} percent of the character height hor{N} horizontal bar, {N} percent of the character height
@ -3676,7 +3679,8 @@ return {
cursor is not shown. Times are in msec. When one of cursor is not shown. Times are in msec. When one of
the numbers is zero, there is no blinking. E.g.: >vim the numbers is zero, there is no blinking. E.g.: >vim
set guicursor=n:blinkon0 set guicursor=n:blinkon0
< - Default is "blinkon0" for each mode. <
Default is "blinkon0" for each mode.
{group-name} {group-name}
Highlight group that decides the color and font of the Highlight group that decides the color and font of the
cursor. cursor.

View File

@ -138,14 +138,20 @@ void state_handle_k_event(void)
/// Return true if in the current mode we need to use virtual. /// Return true if in the current mode we need to use virtual.
bool virtual_active(win_T *wp) bool virtual_active(win_T *wp)
{ {
unsigned cur_ve_flags = get_ve_flags(wp);
// While an operator is being executed we return "virtual_op", because // While an operator is being executed we return "virtual_op", because
// VIsual_active has already been reset, thus we can't check for "block" // VIsual_active has already been reset, thus we can't check for "block"
// being used. // being used.
if (virtual_op != kNone) { if (virtual_op != kNone) {
return virtual_op; return virtual_op;
} }
// In Terminal mode the cursor can be positioned anywhere by the application
if (State & MODE_TERMINAL) {
return true;
}
unsigned cur_ve_flags = get_ve_flags(wp);
return cur_ve_flags == kOptVeFlagAll return cur_ve_flags == kOptVeFlagAll
|| ((cur_ve_flags & kOptVeFlagBlock) && VIsual_active && VIsual_mode == Ctrl_V) || ((cur_ve_flags & kOptVeFlagBlock) && VIsual_active && VIsual_mode == Ctrl_V)
|| ((cur_ve_flags & kOptVeFlagInsert) && (State & MODE_INSERT)); || ((cur_ve_flags & kOptVeFlagInsert) && (State & MODE_INSERT));

View File

@ -52,6 +52,7 @@
#include "nvim/channel.h" #include "nvim/channel.h"
#include "nvim/channel_defs.h" #include "nvim/channel_defs.h"
#include "nvim/cursor.h" #include "nvim/cursor.h"
#include "nvim/cursor_shape.h"
#include "nvim/drawline.h" #include "nvim/drawline.h"
#include "nvim/drawscreen.h" #include "nvim/drawscreen.h"
#include "nvim/eval.h" #include "nvim/eval.h"
@ -160,15 +161,19 @@ struct terminal {
int invalid_start, invalid_end; // invalid rows in libvterm screen int invalid_start, invalid_end; // invalid rows in libvterm screen
struct { struct {
int row, col; int row, col;
int shape;
bool visible; bool visible;
bool blink;
} cursor; } cursor;
bool pending_resize; // pending width/height
struct {
bool resize; ///< pending width/height
bool cursor; ///< pending cursor shape or blink change
StringBuilder *send; ///< When there is a pending TermRequest autocommand, block and store input.
} pending;
bool color_set[16]; bool color_set[16];
// When there is a pending TermRequest autocommand, block and store input.
StringBuilder *pending_send;
char *selection_buffer; /// libvterm selection buffer char *selection_buffer; /// libvterm selection buffer
StringBuilder selection; /// Growable array containing full selection data StringBuilder selection; /// Growable array containing full selection data
@ -207,24 +212,24 @@ static void emit_termrequest(void **argv)
apply_autocmds_group(EVENT_TERMREQUEST, NULL, NULL, false, AUGROUP_ALL, buf, NULL, &data); apply_autocmds_group(EVENT_TERMREQUEST, NULL, NULL, false, AUGROUP_ALL, buf, NULL, &data);
xfree(payload); xfree(payload);
StringBuilder *term_pending_send = term->pending_send; StringBuilder *term_pending_send = term->pending.send;
term->pending_send = NULL; term->pending.send = NULL;
if (kv_size(*pending_send)) { if (kv_size(*pending_send)) {
terminal_send(term, pending_send->items, pending_send->size); terminal_send(term, pending_send->items, pending_send->size);
kv_destroy(*pending_send); kv_destroy(*pending_send);
} }
if (term_pending_send != pending_send) { if (term_pending_send != pending_send) {
term->pending_send = term_pending_send; term->pending.send = term_pending_send;
} }
xfree(pending_send); xfree(pending_send);
} }
static void schedule_termrequest(Terminal *term, char *payload, size_t payload_length) static void schedule_termrequest(Terminal *term, char *payload, size_t payload_length)
{ {
term->pending_send = xmalloc(sizeof(StringBuilder)); term->pending.send = xmalloc(sizeof(StringBuilder));
kv_init(*term->pending_send); kv_init(*term->pending.send);
multiqueue_put(main_loop.events, emit_termrequest, term, payload, (void *)payload_length, multiqueue_put(main_loop.events, emit_termrequest, term, payload, (void *)payload_length,
term->pending_send); term->pending.send);
} }
static int parse_osc8(VTermStringFragment frag, int *attr) static int parse_osc8(VTermStringFragment frag, int *attr)
@ -363,7 +368,7 @@ void terminal_open(Terminal **termpp, buf_T *buf, TerminalOptions opts)
// Create a new terminal instance and configure it // Create a new terminal instance and configure it
Terminal *term = *termpp = xcalloc(1, sizeof(Terminal)); Terminal *term = *termpp = xcalloc(1, sizeof(Terminal));
term->opts = opts; term->opts = opts;
term->cursor.visible = true;
// Associate the terminal instance with the new buffer // Associate the terminal instance with the new buffer
term->buf_handle = buf->handle; term->buf_handle = buf->handle;
buf->terminal = term; buf->terminal = term;
@ -387,6 +392,28 @@ void terminal_open(Terminal **termpp, buf_T *buf, TerminalOptions opts)
vterm_state_set_selection_callbacks(state, &vterm_selection_callbacks, term, vterm_state_set_selection_callbacks(state, &vterm_selection_callbacks, term,
term->selection_buffer, SELECTIONBUF_SIZE); term->selection_buffer, SELECTIONBUF_SIZE);
VTermValue cursor_shape;
switch (shape_table[SHAPE_IDX_TERM].shape) {
case SHAPE_BLOCK:
cursor_shape.number = VTERM_PROP_CURSORSHAPE_BLOCK;
break;
case SHAPE_HOR:
cursor_shape.number = VTERM_PROP_CURSORSHAPE_UNDERLINE;
break;
case SHAPE_VER:
cursor_shape.number = VTERM_PROP_CURSORSHAPE_BAR_LEFT;
break;
}
vterm_state_set_termprop(state, VTERM_PROP_CURSORSHAPE, &cursor_shape);
VTermValue cursor_blink;
if (shape_table[SHAPE_IDX_TERM].blinkon != 0 && shape_table[SHAPE_IDX_TERM].blinkoff != 0) {
cursor_blink.boolean = true;
} else {
cursor_blink.boolean = false;
}
vterm_state_set_termprop(state, VTERM_PROP_CURSORBLINK, &cursor_blink);
// force a initial refresh of the screen to ensure the buffer will always // force a initial refresh of the screen to ensure the buffer will always
// have as many lines as screen rows when refresh_scrollback is called // have as many lines as screen rows when refresh_scrollback is called
term->invalid_start = 0; term->invalid_start = 0;
@ -565,7 +592,7 @@ void terminal_check_size(Terminal *term)
vterm_set_size(term->vt, height, width); vterm_set_size(term->vt, height, width);
vterm_screen_flush_damage(term->vts); vterm_screen_flush_damage(term->vts);
term->pending_resize = true; term->pending.resize = true;
invalidate_terminal(term, -1, -1); invalidate_terminal(term, -1, -1);
} }
@ -614,16 +641,25 @@ bool terminal_enter(void)
curwin->w_p_so = 0; curwin->w_p_so = 0;
curwin->w_p_siso = 0; curwin->w_p_siso = 0;
// Update the cursor shape table and flush changes to the UI
s->term->pending.cursor = true;
refresh_cursor(s->term);
adjust_topline(s->term, buf, 0); // scroll to end adjust_topline(s->term, buf, 0); // scroll to end
// erase the unfocused cursor
invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1);
showmode(); showmode();
curwin->w_redr_status = true; // For mode() in statusline. #8323 curwin->w_redr_status = true; // For mode() in statusline. #8323
redraw_custom_title_later(); redraw_custom_title_later();
if (!s->term->cursor.visible) {
// Hide cursor if it should be hidden
ui_busy_start(); ui_busy_start();
}
ui_cursor_shape();
apply_autocmds(EVENT_TERMENTER, NULL, NULL, false, curbuf); apply_autocmds(EVENT_TERMENTER, NULL, NULL, false, curbuf);
may_trigger_modechanged(); may_trigger_modechanged();
// Tell the terminal it has focus
terminal_focus(s->term, true);
s->state.execute = terminal_execute; s->state.execute = terminal_execute;
s->state.check = terminal_check; s->state.check = terminal_check;
state_enter(&s->state); state_enter(&s->state);
@ -635,6 +671,9 @@ bool terminal_enter(void)
RedrawingDisabled = s->save_rd; RedrawingDisabled = s->save_rd;
apply_autocmds(EVENT_TERMLEAVE, NULL, NULL, false, curbuf); apply_autocmds(EVENT_TERMLEAVE, NULL, NULL, false, curbuf);
// Restore the terminal cursor to what is set in 'guicursor'
(void)parse_shape_opt(SHAPE_CURSOR);
if (save_curwin == curwin->handle) { // Else: window was closed. if (save_curwin == curwin->handle) { // Else: window was closed.
curwin->w_p_cul = save_w_p_cul; curwin->w_p_cul = save_w_p_cul;
if (save_w_p_culopt) { if (save_w_p_culopt) {
@ -649,8 +688,9 @@ bool terminal_enter(void)
free_string_option(save_w_p_culopt); free_string_option(save_w_p_culopt);
} }
// draw the unfocused cursor // Tell the terminal it lost focus
invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1); terminal_focus(s->term, false);
if (curbuf->terminal == s->term && !s->close) { if (curbuf->terminal == s->term && !s->close) {
terminal_check_cursor(); terminal_check_cursor();
} }
@ -659,7 +699,11 @@ bool terminal_enter(void)
} else { } else {
unshowmode(true); unshowmode(true);
} }
if (!s->term->cursor.visible) {
// If cursor was hidden, show it again
ui_busy_stop(); ui_busy_stop();
}
ui_cursor_shape();
if (s->close) { if (s->close) {
bool wipe = s->term->buf_handle != 0; bool wipe = s->term->buf_handle != 0;
s->term->destroy = true; s->term->destroy = true;
@ -810,6 +854,19 @@ static int terminal_execute(VimState *state, int key)
return 0; return 0;
} }
if (s->term != curbuf->terminal) { if (s->term != curbuf->terminal) {
// Active terminal buffer changed, flush terminal's cursor state to the UI
curbuf->terminal->pending.cursor = true;
if (!s->term->cursor.visible) {
// If cursor was hidden, show it again
ui_busy_stop();
}
if (!curbuf->terminal->cursor.visible) {
// Hide cursor if it should be hidden
ui_busy_start();
}
invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1); invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1);
invalidate_terminal(curbuf->terminal, invalidate_terminal(curbuf->terminal,
curbuf->terminal->cursor.row, curbuf->terminal->cursor.row,
@ -857,8 +914,8 @@ static void terminal_send(Terminal *term, const char *data, size_t size)
if (term->closed) { if (term->closed) {
return; return;
} }
if (term->pending_send) { if (term->pending.send) {
kv_concat_len(*term->pending_send, data, size); kv_concat_len(*term->pending.send, data, size);
return; return;
} }
term->opts.write_cb(data, size, term->opts.data); term->opts.write_cb(data, size, term->opts.data);
@ -1063,14 +1120,6 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, int *te
attr_id = hl_combine_attr(attr_id, cell.uri); attr_id = hl_combine_attr(attr_id, cell.uri);
} }
if (term->cursor.visible && term->cursor.row == row
&& term->cursor.col == col) {
attr_id = hl_combine_attr(attr_id,
is_focused(term) && wp == curwin
? win_hl_attr(wp, HLF_TERM)
: win_hl_attr(wp, HLF_TERMNC));
}
term_attrs[col] = attr_id; term_attrs[col] = attr_id;
} }
} }
@ -1085,6 +1134,17 @@ bool terminal_running(const Terminal *term)
return !term->closed; return !term->closed;
} }
static void terminal_focus(const Terminal *term, bool focus)
FUNC_ATTR_NONNULL_ALL
{
VTermState *state = vterm_obtain_state(term->vt);
if (focus) {
vterm_state_focus_in(state);
} else {
vterm_state_focus_out(state);
}
}
// }}} // }}}
// libvterm callbacks {{{ // libvterm callbacks {{{
@ -1106,8 +1166,7 @@ static int term_movecursor(VTermPos new_pos, VTermPos old_pos, int visible, void
Terminal *term = data; Terminal *term = data;
term->cursor.row = new_pos.row; term->cursor.row = new_pos.row;
term->cursor.col = new_pos.col; term->cursor.col = new_pos.col;
invalidate_terminal(term, old_pos.row, old_pos.row + 1); invalidate_terminal(term, -1, -1);
invalidate_terminal(term, new_pos.row, new_pos.row + 1);
return 1; return 1;
} }
@ -1135,8 +1194,17 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data)
break; break;
case VTERM_PROP_CURSORVISIBLE: case VTERM_PROP_CURSORVISIBLE:
if (is_focused(term)) {
if (!val->boolean && term->cursor.visible) {
// Hide the cursor
ui_busy_start();
} else if (val->boolean && !term->cursor.visible) {
// Unhide the cursor
ui_busy_stop();
}
invalidate_terminal(term, -1, -1);
}
term->cursor.visible = val->boolean; term->cursor.visible = val->boolean;
invalidate_terminal(term, term->cursor.row, term->cursor.row + 1);
break; break;
case VTERM_PROP_TITLE: { case VTERM_PROP_TITLE: {
@ -1172,6 +1240,18 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data)
term->forward_mouse = (bool)val->number; term->forward_mouse = (bool)val->number;
break; break;
case VTERM_PROP_CURSORBLINK:
term->cursor.blink = val->boolean;
term->pending.cursor = true;
invalidate_terminal(term, -1, -1);
break;
case VTERM_PROP_CURSORSHAPE:
term->cursor.shape = val->number;
term->pending.cursor = true;
invalidate_terminal(term, -1, -1);
break;
default: default:
return 0; return 0;
} }
@ -1849,12 +1929,47 @@ static void refresh_terminal(Terminal *term)
refresh_size(term, buf); refresh_size(term, buf);
refresh_scrollback(term, buf); refresh_scrollback(term, buf);
refresh_screen(term, buf); refresh_screen(term, buf);
refresh_cursor(term);
aucmd_restbuf(&aco); aucmd_restbuf(&aco);
int ml_added = buf->b_ml.ml_line_count - ml_before; int ml_added = buf->b_ml.ml_line_count - ml_before;
adjust_topline(term, buf, ml_added); adjust_topline(term, buf, ml_added);
} }
static void refresh_cursor(Terminal *term)
FUNC_ATTR_NONNULL_ALL
{
if (!is_focused(term) || !term->pending.cursor) {
return;
}
term->pending.cursor = false;
if (term->cursor.blink) {
// For the TUI, this value doesn't actually matter, as long as it's non-zero. The terminal
// emulator dictates the blink frequency, not the application.
// For GUIs we just pick an arbitrary value, for now.
shape_table[SHAPE_IDX_TERM].blinkon = 500;
shape_table[SHAPE_IDX_TERM].blinkoff = 500;
} else {
shape_table[SHAPE_IDX_TERM].blinkon = 0;
shape_table[SHAPE_IDX_TERM].blinkoff = 0;
}
switch (term->cursor.shape) {
case VTERM_PROP_CURSORSHAPE_BLOCK:
shape_table[SHAPE_IDX_TERM].shape = SHAPE_BLOCK;
break;
case VTERM_PROP_CURSORSHAPE_UNDERLINE:
shape_table[SHAPE_IDX_TERM].shape = SHAPE_HOR;
break;
case VTERM_PROP_CURSORSHAPE_BAR_LEFT:
shape_table[SHAPE_IDX_TERM].shape = SHAPE_VER;
break;
}
ui_mode_info_set();
}
/// Calls refresh_terminal() on all invalidated_terminals. /// Calls refresh_terminal() on all invalidated_terminals.
static void refresh_timer_cb(TimeWatcher *watcher, void *data) static void refresh_timer_cb(TimeWatcher *watcher, void *data)
{ {
@ -1875,11 +1990,11 @@ static void refresh_timer_cb(TimeWatcher *watcher, void *data)
static void refresh_size(Terminal *term, buf_T *buf) static void refresh_size(Terminal *term, buf_T *buf)
{ {
if (!term->pending_resize || term->closed) { if (!term->pending.resize || term->closed) {
return; return;
} }
term->pending_resize = false; term->pending.resize = false;
int width, height; int width, height;
vterm_get_size(term->vt, &height, &width); vterm_get_size(term->vt, &height, &width);
term->invalid_start = 0; term->invalid_start = 0;

View File

@ -35,6 +35,7 @@
#include "nvim/strings.h" #include "nvim/strings.h"
#include "nvim/textformat.h" #include "nvim/textformat.h"
#include "nvim/textobject.h" #include "nvim/textobject.h"
#include "nvim/ui.h"
#include "nvim/undo.h" #include "nvim/undo.h"
#include "nvim/vim_defs.h" #include "nvim/vim_defs.h"
#include "nvim/window.h" #include "nvim/window.h"
@ -1049,12 +1050,18 @@ void format_lines(linenr_T line_count, bool avoid_fex)
State = MODE_INSERT; // for open_line() State = MODE_INSERT; // for open_line()
smd_save = p_smd; smd_save = p_smd;
p_smd = false; p_smd = false;
insertchar(NUL, INSCHAR_FORMAT insertchar(NUL, INSCHAR_FORMAT
+ (do_comments ? INSCHAR_DO_COM : 0) + (do_comments ? INSCHAR_DO_COM : 0)
+ (do_comments && do_comments_list ? INSCHAR_COM_LIST : 0) + (do_comments && do_comments_list ? INSCHAR_COM_LIST : 0)
+ (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent); + (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent);
State = old_State; State = old_State;
p_smd = smd_save; p_smd = smd_save;
// Cursor shape may have been updated (e.g. by :normal) in insertchar(),
// so it needs to be updated here.
ui_cursor_shape();
second_indent = -1; second_indent = -1;
// at end of par.: need to set indent of next par. // at end of par.: need to set indent of next par.
need_set_indent = is_end_par; need_set_indent = is_end_par;

View File

@ -1339,7 +1339,7 @@ static void tui_set_mode(TUIData *tui, ModeShape mode)
case SHAPE_VER: case SHAPE_VER:
shape = 5; break; shape = 5; break;
} }
UNIBI_SET_NUM_VAR(tui->params[0], shape + (int)(c.blinkon == 0)); UNIBI_SET_NUM_VAR(tui->params[0], shape + (int)(c.blinkon == 0 || c.blinkoff == 0));
unibi_out_ext(tui, tui->unibi_ext.set_cursor_style); unibi_out_ext(tui, tui->unibi_ext.set_cursor_style);
} }

View File

@ -3785,7 +3785,7 @@ describe('API', function()
screen:expect { screen:expect {
grid = [[ grid = [[
| |
{1:~}{102: }{4: }{1: }| {1:~}{4:^ }{1: }|
{1:~}{4: }{1: }|*4 {1:~}{4: }{1: }|*4
{1:~ }|*3 {1:~ }|*3
{5:-- TERMINAL --} | {5:-- TERMINAL --} |
@ -3801,7 +3801,7 @@ describe('API', function()
screen:expect { screen:expect {
grid = [[ grid = [[
| |
{1:~}{4:herrejösses!}{102: }{4: }{1: }| {1:~}{4:herrejösses!^ }{1: }|
{1:~}{4: }{1: }|*4 {1:~}{4: }{1: }|*4
{1:~ }|*3 {1:~ }|*3
{5:-- TERMINAL --} | {5:-- TERMINAL --} |
@ -5388,4 +5388,156 @@ describe('API', function()
api.nvim__redraw({ win = 0, range = { 0, -1 } }) api.nvim__redraw({ win = 0, range = { 0, -1 } })
n.assert_alive() n.assert_alive()
end) end)
describe('nvim_cmd with plus #flags', function()
it('handles +flags correctly', function()
-- Write a file for testing +flags
command(':call writefile(["Line 1", "Line 2", "Line 3"], "testfile")')
-- Test + command (go to the last line)
local result = exec_lua([[
vim.cmd(vim.api.nvim_parse_cmd('edit + testfile', {}))
return vim.fn.line('.')
]])
eq(3, result)
-- Test +{num} command (go to line number)
result = exec_lua([[
vim.cmd(vim.api.nvim_parse_cmd('edit +1 testfile', {}))
return vim.fn.line('.')
]])
eq(1, result)
-- Test +/{pattern} command (go to line with pattern)
result = exec_lua([[
vim.cmd(vim.api.nvim_parse_cmd('edit +/Line\\ 2 testfile', {}))
return vim.fn.line('.')
]])
eq(2, result)
-- Test +{command} command (execute a command after opening the file)
result = exec_lua([[
vim.cmd(vim.api.nvim_parse_cmd('edit +set\\ nomodifiable testfile', {}))
return vim.bo.modifiable
]])
eq(false, result)
-- Clean up
os.remove('testfile')
end)
it('handles various ++ flags correctly', function()
-- Test ++ff flag
exec_lua [[
vim.cmd(vim.api.nvim_parse_cmd('edit ++ff=mac test_ff_mac.txt', {}))
]]
eq('mac', api.nvim_get_option_value('fileformat', {}))
eq('test_ff_mac.txt', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
exec_lua [[
vim.cmd(vim.api.nvim_parse_cmd('edit ++fileformat=unix test_ff_unix.txt', {}))
]]
eq('unix', api.nvim_get_option_value('fileformat', {}))
eq('test_ff_unix.txt', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
-- Test ++enc flag
exec_lua [[
vim.cmd(vim.api.nvim_parse_cmd('edit ++enc=utf-32 test_enc.txt', {}))
]]
eq('ucs-4', api.nvim_get_option_value('fileencoding', {}))
eq('test_enc.txt', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
-- Test ++bin and ++nobin flags
exec_lua [[
vim.cmd(vim.api.nvim_parse_cmd('edit ++bin test_bin.txt', {}))
]]
eq(true, api.nvim_get_option_value('binary', {}))
eq('test_bin.txt', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
exec_lua [[
vim.cmd(vim.api.nvim_parse_cmd('edit ++nobin test_nobin.txt', {}))
]]
eq(false, api.nvim_get_option_value('binary', {}))
eq('test_nobin.txt', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
-- Test multiple flags together
exec_lua [[
vim.cmd(vim.api.nvim_parse_cmd('edit ++ff=mac ++enc=utf-32 ++bin test_multi.txt', {}))
]]
eq(true, api.nvim_get_option_value('binary', {}))
eq('mac', api.nvim_get_option_value('fileformat', {}))
eq('ucs-4', api.nvim_get_option_value('fileencoding', {}))
eq('test_multi.txt', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
end)
it('handles invalid and incorrect ++ flags gracefully', function()
-- Test invalid ++ff flag
local result = exec_lua [[
local cmd = vim.api.nvim_parse_cmd('edit ++ff=invalid test_invalid_ff.txt', {})
local _, err = pcall(vim.cmd, cmd)
return err
]]
eq('Invalid argument', result)
-- Test incorrect ++ syntax
result = exec_lua [[
local cmd = vim.api.nvim_parse_cmd('edit ++unknown=test_unknown.txt', {})
local _, err = pcall(vim.cmd, cmd)
return err
]]
eq('Invalid argument', result)
-- Test invalid ++bin flag
result = exec_lua [[
local cmd = vim.api.nvim_parse_cmd('edit ++binabc test_invalid_bin.txt', {})
local _, err = pcall(vim.cmd, cmd)
return err
]]
eq('Invalid argument', result)
end)
it('handles ++p for creating parent directory', function()
exec_lua [[
vim.cmd('edit flags_dir/test_create.txt')
vim.cmd(vim.api.nvim_parse_cmd('write! ++p', {}))
]]
eq(true, fn.isdirectory('flags_dir') == 1)
fn.delete('flags_dir', 'rf')
end)
it('tests editing files with bad utf8 sequences', function()
-- Write a file with bad utf8 sequences
local file = io.open('Xfile', 'wb')
file:write('[\255][\192][\226\137\240][\194\194]')
file:close()
exec_lua([[
vim.cmd(vim.api.nvim_parse_cmd('edit! ++enc=utf8 Xfile', {}))
]])
eq('[?][?][???][??]', api.nvim_get_current_line())
exec_lua([[
vim.cmd(vim.api.nvim_parse_cmd('edit! ++enc=utf8 ++bad=_ Xfile', {}))
]])
eq('[_][_][___][__]', api.nvim_get_current_line())
exec_lua([[
vim.cmd(vim.api.nvim_parse_cmd('edit! ++enc=utf8 ++bad=drop Xfile', {}))
]])
eq('[][][][]', api.nvim_get_current_line())
exec_lua([[
vim.cmd(vim.api.nvim_parse_cmd('edit! ++enc=utf8 ++bad=keep Xfile', {}))
]])
eq('[\255][\192][\226\137\240][\194\194]', api.nvim_get_current_line())
local result = exec_lua([[
local _, err = pcall(vim.cmd, vim.api.nvim_parse_cmd('edit ++enc=utf8 ++bad=foo Xfile', {}))
return err
]])
eq('Invalid argument', result)
-- Clean up
os.remove('Xfile')
end)
end)
end) end)

View File

@ -47,7 +47,7 @@ describe('autoread TUI FocusGained/FocusLost', function()
screen:expect { screen:expect {
grid = [[ grid = [[
{1: } | ^ |
{4:~ }|*3 {4:~ }|*3
{5:[No Name] }| {5:[No Name] }|
| |
@ -57,7 +57,7 @@ describe('autoread TUI FocusGained/FocusLost', function()
feed_command('edit ' .. path) feed_command('edit ' .. path)
screen:expect { screen:expect {
grid = [[ grid = [[
{1: } | ^ |
{4:~ }|*3 {4:~ }|*3
{5:xtest-foo }| {5:xtest-foo }|
:edit xtest-foo | :edit xtest-foo |
@ -68,7 +68,7 @@ describe('autoread TUI FocusGained/FocusLost', function()
feed_data('\027[O') feed_data('\027[O')
screen:expect { screen:expect {
grid = [[ grid = [[
{1: } | ^ |
{4:~ }|*3 {4:~ }|*3
{5:xtest-foo }| {5:xtest-foo }|
:edit xtest-foo | :edit xtest-foo |
@ -83,7 +83,7 @@ describe('autoread TUI FocusGained/FocusLost', function()
screen:expect { screen:expect {
grid = [[ grid = [[
{1:l}ine 1 | ^line 1 |
line 2 | line 2 |
line 3 | line 3 |
line 4 | line 4 |

View File

@ -1198,7 +1198,7 @@ describe('jobs', function()
}) })
-- Wait for startup to complete, so that all terminal responses are received. -- Wait for startup to complete, so that all terminal responses are received.
screen:expect([[ screen:expect([[
{1: } | ^ |
~ |*3 ~ |*3
{1:[No Name] 0,0-1 All}| {1:[No Name] 0,0-1 All}|
| |
@ -1208,7 +1208,7 @@ describe('jobs', function()
feed(':q<CR>') feed(':q<CR>')
screen:expect([[ screen:expect([[
| |
[Process exited 0]{1: } | [Process exited 0]^ |
|*4 |*4
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])

View File

@ -46,7 +46,7 @@ describe('log', function()
env = env, env = env,
}) })
screen:expect([[ screen:expect([[
{1: } | ^ |
~ |*4 ~ |*4
| |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |

View File

@ -120,7 +120,7 @@ describe('command-line option', function()
feed('i:cq<CR>') feed('i:cq<CR>')
screen:expect([[ screen:expect([[
| |
[Process exited 1]{2: } | [Process exited 1]^ |
|*5 |*5
{5:-- TERMINAL --} | {5:-- TERMINAL --} |
]]) ]])

View File

@ -1153,7 +1153,7 @@ describe('user config init', function()
-- `i` to enter Terminal mode, `a` to allow -- `i` to enter Terminal mode, `a` to allow
feed('ia') feed('ia')
screen:expect([[ screen:expect([[
| ^ |
~ |*4 ~ |*4
[No Name] 0,0-1 All| [No Name] 0,0-1 All|
| |
@ -1162,7 +1162,7 @@ describe('user config init', function()
feed(':echo g:exrc_file<CR>') feed(':echo g:exrc_file<CR>')
screen:expect(string.format( screen:expect(string.format(
[[ [[
| ^ |
~ |*4 ~ |*4
[No Name] 0,0-1 All| [No Name] 0,0-1 All|
%s%s| %s%s|

View File

@ -29,8 +29,8 @@ describe(':highlight', function()
| |
TermCursor {2:xxx} {18:cterm=}reverse | TermCursor {2:xxx} {18:cterm=}reverse |
{18:gui=}reverse | {18:gui=}reverse |
TermCursorNC xxx cleared |
NonText {1:xxx} {18:ctermfg=}12 | NonText {1:xxx} {18:ctermfg=}12 |
{18:gui=}bold |
{6:-- More --}^ | {6:-- More --}^ |
]]) ]])
feed('q') feed('q')

View File

@ -263,7 +263,7 @@ describe('vim.ui_attach', function()
]], ]],
messages = { messages = {
{ {
content = { { 'E122: Function Foo already exists, add ! to replace it', 9, 7 } }, content = { { 'E122: Function Foo already exists, add ! to replace it', 9, 6 } },
kind = 'emsg', kind = 'emsg',
}, },
}, },
@ -280,7 +280,7 @@ describe('vim.ui_attach', function()
]], ]],
messages = { messages = {
{ {
content = { { 'replace with Replacement (y/n/a/q/l/^E/^Y)?', 6, 19 } }, content = { { 'replace with Replacement (y/n/a/q/l/^E/^Y)?', 6, 18 } },
kind = 'confirm_sub', kind = 'confirm_sub',
}, },
}, },
@ -348,7 +348,7 @@ describe('vim.ui_attach', function()
foo^ | foo^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
showmode = { { '-- INSERT --', 5, 12 } }, showmode = { { '-- INSERT --', 5, 11 } },
}) })
feed('<esc>:1mes clear<cr>:mes<cr>') feed('<esc>:1mes clear<cr>:mes<cr>')
screen:expect({ screen:expect({
@ -375,7 +375,7 @@ describe('vim.ui_attach', function()
{ {
'Error executing vim.schedule lua callback: [string "<nvim>"]:2: attempt to index global \'err\' (a nil value)\nstack traceback:\n\t[string "<nvim>"]:2: in function <[string "<nvim>"]:2>', 'Error executing vim.schedule lua callback: [string "<nvim>"]:2: attempt to index global \'err\' (a nil value)\nstack traceback:\n\t[string "<nvim>"]:2: in function <[string "<nvim>"]:2>',
9, 9,
7, 6,
}, },
}, },
kind = 'lua_error', kind = 'lua_error',
@ -385,13 +385,13 @@ describe('vim.ui_attach', function()
{ {
'Error executing vim.schedule lua callback: [string "<nvim>"]:2: attempt to index global \'err\' (a nil value)\nstack traceback:\n\t[string "<nvim>"]:2: in function <[string "<nvim>"]:2>', 'Error executing vim.schedule lua callback: [string "<nvim>"]:2: attempt to index global \'err\' (a nil value)\nstack traceback:\n\t[string "<nvim>"]:2: in function <[string "<nvim>"]:2>',
9, 9,
7, 6,
}, },
}, },
kind = 'lua_error', kind = 'lua_error',
}, },
{ {
content = { { 'Press ENTER or type command to continue', 100, 19 } }, content = { { 'Press ENTER or type command to continue', 100, 18 } },
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },

View File

@ -1854,6 +1854,20 @@ describe('LSP', function()
end, end,
} }
end) end)
it('vim.lsp.start when existing client has no workspace_folders', function()
exec_lua(create_server_definition)
eq(
{ 2, 'foo', 'foo' },
exec_lua(function()
local server = _G._create_server()
vim.lsp.start { cmd = server.cmd, name = 'foo' }
vim.lsp.start { cmd = server.cmd, name = 'foo', root_dir = 'bar' }
local foos = vim.lsp.get_clients()
return { #foos, foos[1].name, foos[2].name }
end)
)
end)
end) end)
describe('parsing tests', function() describe('parsing tests', function()

View File

@ -21,13 +21,12 @@ local function get_search_history(name)
local man = require('man') local man = require('man')
local res = {} local res = {}
--- @diagnostic disable-next-line:duplicate-set-field --- @diagnostic disable-next-line:duplicate-set-field
man.find_path = function(sect, name0) man._find_path = function(name0, sect)
table.insert(res, { sect, name0 }) table.insert(res, { sect, name0 })
return nil return nil
end end
local ok, rv = pcall(man.open_page, -1, { tab = 0 }, args) local err = man.open_page(-1, { tab = 0 }, args)
assert(not ok) assert(err and err:match('no manual entry'))
assert(rv and rv:match('no manual entry'))
return res return res
end) end)
end end
@ -225,7 +224,7 @@ describe(':Man', function()
matches('^/.+', actual_file) matches('^/.+', actual_file)
local args = { nvim_prog, '--headless', '+:Man ' .. actual_file, '+q' } local args = { nvim_prog, '--headless', '+:Man ' .. actual_file, '+q' }
matches( matches(
('Error detected while processing command line:\r\n' .. 'man.lua: "no manual entry for %s"'):format( ('Error detected while processing command line:\r\n' .. 'man.lua: no manual entry for %s'):format(
pesc(actual_file) pesc(actual_file)
), ),
fn.system(args, { '' }) fn.system(args, { '' })
@ -235,8 +234,8 @@ describe(':Man', function()
it('tries variants with spaces, underscores #22503', function() it('tries variants with spaces, underscores #22503', function()
eq({ eq({
{ '', 'NAME WITH SPACES' }, { vim.NIL, 'NAME WITH SPACES' },
{ '', 'NAME_WITH_SPACES' }, { vim.NIL, 'NAME_WITH_SPACES' },
}, get_search_history('NAME WITH SPACES')) }, get_search_history('NAME WITH SPACES'))
eq({ eq({
{ '3', 'some other man' }, { '3', 'some other man' },
@ -255,8 +254,8 @@ describe(':Man', function()
{ 'n', 'some_other_man' }, { 'n', 'some_other_man' },
}, get_search_history('n some other man')) }, get_search_history('n some other man'))
eq({ eq({
{ '', '123some other man' }, { vim.NIL, '123some other man' },
{ '', '123some_other_man' }, { vim.NIL, '123some_other_man' },
}, get_search_history('123some other man')) }, get_search_history('123some other man'))
eq({ eq({
{ '1', 'other_man' }, { '1', 'other_man' },
@ -265,11 +264,10 @@ describe(':Man', function()
end) end)
it('can complete', function() it('can complete', function()
t.skip(t.is_os('mac') and t.is_arch('x86_64'), 'not supported on intel mac')
eq( eq(
true, true,
exec_lua(function() exec_lua(function()
return #require('man').man_complete('f', 'Man g') > 0 return #require('man').man_complete('f', 'Man f') > 0
end) end)
) )
end) end)

View File

@ -35,13 +35,13 @@ describe(':terminal altscreen', function()
line6 | line6 |
line7 | line7 |
line8 | line8 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
enter_altscreen() enter_altscreen()
screen:expect([[ screen:expect([[
|*5 |*5
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq(10, api.nvim_buf_line_count(0)) eq(10, api.nvim_buf_line_count(0))
@ -68,7 +68,7 @@ describe(':terminal altscreen', function()
line6 | line6 |
line7 | line7 |
line8 | line8 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
feed('<c-\\><c-n>gg') feed('<c-\\><c-n>gg')
@ -103,7 +103,7 @@ describe(':terminal altscreen', function()
line14 | line14 |
line15 | line15 |
line16 | line16 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
@ -132,7 +132,7 @@ describe(':terminal altscreen', function()
screen:expect([[ screen:expect([[
|*2 |*2
rows: 4, cols: 50 | rows: 4, cols: 50 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end end
@ -160,7 +160,7 @@ describe(':terminal altscreen', function()
line5 | line5 |
line6 | line6 |
line7 | line7 |
line8 | ^line8 |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)

View File

@ -33,7 +33,7 @@ describe('api', function()
it('qa! RPC request during insert-mode', function() it('qa! RPC request during insert-mode', function()
screen:expect { screen:expect {
grid = [[ grid = [[
{1: } | ^ |
{4:~ }|*4 {4:~ }|*4
| |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
@ -45,7 +45,7 @@ describe('api', function()
-- Wait for socket creation. -- Wait for socket creation.
screen:expect([[ screen:expect([[
{1: } | ^ |
{4:~ }|*4 {4:~ }|*4
]] .. socket_name .. [[ | ]] .. socket_name .. [[ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
@ -57,7 +57,7 @@ describe('api', function()
tt.feed_data('i[tui] insert-mode') tt.feed_data('i[tui] insert-mode')
-- Wait for stdin to be processed. -- Wait for stdin to be processed.
screen:expect([[ screen:expect([[
[tui] insert-mode{1: } | [tui] insert-mode^ |
{4:~ }|*4 {4:~ }|*4
{3:-- INSERT --} | {3:-- INSERT --} |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
@ -73,7 +73,7 @@ describe('api', function()
[tui] insert-mode | [tui] insert-mode |
[socket 1] this is more t | [socket 1] this is more t |
han 25 columns | han 25 columns |
[socket 2] input{1: } | [socket 2] input^ |
{4:~ } | {4:~ } |
{3:-- INSERT --} | {3:-- INSERT --} |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |

View File

@ -89,7 +89,7 @@ describe(':terminal buffer', function()
feed('<c-\\><c-n>') feed('<c-\\><c-n>')
screen:expect([[ screen:expect([[
tty ready | tty ready |
{2:^ } | ^ |
|*5 |*5
]]) ]])
end) end)
@ -109,7 +109,7 @@ describe(':terminal buffer', function()
feed('<c-\\><c-n>dd') feed('<c-\\><c-n>dd')
screen:expect([[ screen:expect([[
tty ready | tty ready |
{2:^ } | ^ |
|*4 |*4
{8:E21: Cannot make changes, 'modifiable' is off} | {8:E21: Cannot make changes, 'modifiable' is off} |
]]) ]])
@ -122,7 +122,7 @@ describe(':terminal buffer', function()
screen:expect([[ screen:expect([[
^tty ready | ^tty ready |
appended tty ready |*2 appended tty ready |*2
{2: } | |
|*2 |*2
:let @a = "appended " . @a | :let @a = "appended " . @a |
]]) ]])
@ -142,7 +142,7 @@ describe(':terminal buffer', function()
screen:expect([[ screen:expect([[
^tty ready | ^tty ready |
appended tty ready | appended tty ready |
{2: } | |
|*3 |*3
:put a | :put a |
]]) ]])
@ -151,7 +151,7 @@ describe(':terminal buffer', function()
screen:expect([[ screen:expect([[
tty ready | tty ready |
appended tty ready |*2 appended tty ready |*2
{2: } | |
| |
^ | ^ |
:6put a | :6put a |
@ -198,7 +198,7 @@ describe(':terminal buffer', function()
{4:~ }| {4:~ }|
{5:========== }| {5:========== }|
rows: 2, cols: 50 | rows: 2, cols: 50 |
{2: } | |
{18:========== }| {18:========== }|
| |
]]) ]])
@ -234,7 +234,7 @@ describe(':terminal buffer', function()
command('set rightleft') command('set rightleft')
screen:expect([[ screen:expect([[
ydaer ytt| ydaer ytt|
{1:a}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|*4 |*4
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -277,7 +277,7 @@ describe(':terminal buffer', function()
screen:expect { screen:expect {
grid = [[ grid = [[
tty ready | tty ready |
{2:^ } | ^ |
|*4 |*4
{3:-- (terminal) --} | {3:-- (terminal) --} |
]], ]],
@ -288,7 +288,7 @@ describe(':terminal buffer', function()
screen:expect { screen:expect {
grid = [[ grid = [[
tty ready | tty ready |
{2: } | |
|*4 |*4
:let g:x = 17^ | :let g:x = 17^ |
]], ]],
@ -298,7 +298,7 @@ describe(':terminal buffer', function()
screen:expect { screen:expect {
grid = [[ grid = [[
tty ready | tty ready |
{1: } | ^ |
|*4 |*4
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]], ]],
@ -534,7 +534,7 @@ describe('terminal input', function()
'while 1 | redraw | echo keytrans(getcharstr()) | endwhile', 'while 1 | redraw | echo keytrans(getcharstr()) | endwhile',
}) })
screen:expect([[ screen:expect([[
{1: } | ^ |
{4:~ }|*3 {4:~ }|*3
{5:[No Name] 0,0-1 All}| {5:[No Name] 0,0-1 All}|
| |
@ -594,7 +594,7 @@ describe('terminal input', function()
| |
{4:~ }|*3 {4:~ }|*3
{5:[No Name] 0,0-1 All}| {5:[No Name] 0,0-1 All}|
%s{1: }{MATCH: *}| %s^ {MATCH: *}|
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]):format(key)) ]]):format(key))
end end
@ -624,7 +624,7 @@ if is_os('win') then
> :: appended :: tty ready | > :: appended :: tty ready |
> :: tty ready | > :: tty ready |
> :: appended :: tty ready | > :: appended :: tty ready |
^> {2: } | ^> |
:let @a = @a . "\n:: appended " . @a . "\n\n" | :let @a = @a . "\n:: appended " . @a . "\n\n" |
]]) ]])
-- operator count is also taken into consideration -- operator count is also taken into consideration
@ -635,7 +635,7 @@ if is_os('win') then
> :: appended :: tty ready | > :: appended :: tty ready |
> :: tty ready | > :: tty ready |
> :: appended :: tty ready | > :: appended :: tty ready |
^> {2: } | ^> |
:let @a = @a . "\n:: appended " . @a . "\n\n" | :let @a = @a . "\n:: appended " . @a . "\n\n" |
]]) ]])
end) end)
@ -649,7 +649,7 @@ if is_os('win') then
| |
> :: tty ready | > :: tty ready |
> :: appended :: tty ready | > :: appended :: tty ready |
> {2: } | > |
| |
^ | ^ |
:put a | :put a |
@ -662,7 +662,7 @@ if is_os('win') then
> :: appended :: tty ready | > :: appended :: tty ready |
> :: tty ready | > :: tty ready |
> :: appended :: tty ready | > :: appended :: tty ready |
^> {2: } | ^> |
:6put a | :6put a |
]]) ]])
end) end)

View File

@ -1,13 +1,12 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.testterm') local tt = require('test.functional.testterm')
local feed, clear = n.feed, n.clear local feed, clear = n.feed, n.clear
local testprg, command = n.testprg, n.command local testprg, command = n.testprg, n.command
local eq, eval = t.eq, n.eval local eq, eval = t.eq, n.eval
local matches = t.matches local matches = t.matches
local poke_eventloop = n.poke_eventloop local call = n.call
local hide_cursor = tt.hide_cursor local hide_cursor = tt.hide_cursor
local show_cursor = tt.show_cursor local show_cursor = tt.show_cursor
local is_os = t.is_os local is_os = t.is_os
@ -16,16 +15,27 @@ local skip = t.skip
describe(':terminal cursor', function() describe(':terminal cursor', function()
local screen local screen
local terminal_mode_idx ---@type number
before_each(function() before_each(function()
clear() clear()
screen = tt.setup_screen() screen = tt.setup_screen()
if terminal_mode_idx == nil then
for i, v in ipairs(screen._mode_info) do
if v.name == 'terminal' then
terminal_mode_idx = i
end
end
assert(terminal_mode_idx)
end
end) end)
it('moves the screen cursor when focused', function() it('moves the screen cursor when focused', function()
tt.feed_data('testing cursor') tt.feed_data('testing cursor')
screen:expect([[ screen:expect([[
tty ready | tty ready |
testing cursor{1: } | testing cursor^ |
|*4 |*4
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -35,7 +45,7 @@ describe(':terminal cursor', function()
feed('<c-\\><c-n>') feed('<c-\\><c-n>')
screen:expect([[ screen:expect([[
tty ready | tty ready |
{2:^ } | ^ |
|*5 |*5
]]) ]])
end) end)
@ -49,7 +59,7 @@ describe(':terminal cursor', function()
screen:expect([[ screen:expect([[
{7: 1 }tty ready | {7: 1 }tty ready |
{7: 2 }^rows: 6, cols: 46 | {7: 2 }^rows: 6, cols: 46 |
{7: 3 }{2: } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 } | {7: 5 } |
{7: 6 } | {7: 6 } |
@ -61,7 +71,7 @@ describe(':terminal cursor', function()
screen:expect([[ screen:expect([[
{7: 1 }tty ready | {7: 1 }tty ready |
{7: 2 }^rows: 6, cols: 46 | {7: 2 }^rows: 6, cols: 46 |
{7: 3 }{2: } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 } | {7: 5 } |
{7: 6 } | {7: 6 } |
@ -72,7 +82,7 @@ describe(':terminal cursor', function()
screen:expect([[ screen:expect([[
{7: 1 }tty ready | {7: 1 }tty ready |
{7: 2 }rows: 6, cols: 46 | {7: 2 }rows: 6, cols: 46 |
{7: 3 }{1: } | {7: 3 }^ |
{7: 4 } | {7: 4 } |
{7: 5 } | {7: 5 } |
{7: 6 } | {7: 6 } |
@ -82,8 +92,8 @@ describe(':terminal cursor', function()
end) end)
describe('when invisible', function() describe('when invisible', function()
it('is not highlighted and is detached from screen cursor', function() it('is not highlighted', function()
skip(is_os('win')) skip(is_os('win'), '#31587')
hide_cursor() hide_cursor()
screen:expect([[ screen:expect([[
tty ready | tty ready |
@ -93,59 +103,251 @@ describe(':terminal cursor', function()
show_cursor() show_cursor()
screen:expect([[ screen:expect([[
tty ready | tty ready |
{1: } | ^ |
|*4 |*4
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
-- same for when the terminal is unfocused -- same for when the terminal is unfocused
feed('<c-\\><c-n>') feed('<c-\\><c-n>')
hide_cursor() hide_cursor()
screen:expect([[ screen:expect({
grid = [[
tty ready | tty ready |
^ | ^ |
|*5 |*5
]]) ]],
show_cursor() unchanged = true,
screen:expect([[ })
tty ready | show_cursor()
{2:^ } | screen:expect({
|*5 grid = [[
]]) tty ready |
end) ^ |
end) |*5
end) ]],
unchanged = true,
describe('cursor with customized highlighting', function()
local screen
before_each(function()
clear()
command('highlight TermCursor ctermfg=45 ctermbg=46 cterm=NONE')
command('highlight TermCursorNC ctermfg=55 ctermbg=56 cterm=NONE')
screen = Screen.new(50, 7, { rgb = false })
screen:set_default_attr_ids({
[1] = { foreground = 45, background = 46 },
[2] = { foreground = 55, background = 56 },
[3] = { bold = true },
}) })
command('call termopen(["' .. testprg('tty-test') .. '"])')
feed('i')
poke_eventloop()
end) end)
it('overrides the default highlighting', function() it('becomes visible when exiting Terminal mode', function()
skip(is_os('win'), '#31587')
hide_cursor()
screen:expect([[ screen:expect([[
tty ready | tty ready |
{1: } | |*5
|*4
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
feed('<c-\\><c-n>') feed('<c-\\><c-n>')
screen:expect([[ screen:expect([[
tty ready | tty ready |
{2:^ } | ^ |
|*5 |*5
]]) ]])
feed('i')
screen:expect([[
tty ready |
|*5
{3:-- TERMINAL --} |
]])
end)
end)
it('can be modified by application #3681', function()
skip(is_os('win'), '#31587')
local states = {
[1] = { blink = true, shape = 'block' },
[2] = { blink = false, shape = 'block' },
[3] = { blink = true, shape = 'horizontal' },
[4] = { blink = false, shape = 'horizontal' },
[5] = { blink = true, shape = 'vertical' },
[6] = { blink = false, shape = 'vertical' },
}
for k, v in pairs(states) do
tt.feed_csi(('%d q'):format(k))
screen:expect({
grid = [[
tty ready |
^ |
|*4
{3:-- TERMINAL --} |
]],
condition = function()
if v.blink then
eq(500, screen._mode_info[terminal_mode_idx].blinkon)
eq(500, screen._mode_info[terminal_mode_idx].blinkoff)
else
eq(0, screen._mode_info[terminal_mode_idx].blinkon)
eq(0, screen._mode_info[terminal_mode_idx].blinkoff)
end
eq(v.shape, screen._mode_info[terminal_mode_idx].cursor_shape)
end,
})
end
feed([[<C-\><C-N>]])
screen:expect([[
tty ready |
^ |
|*5
]])
-- Cursor returns to default on TermLeave
eq(500, screen._mode_info[terminal_mode_idx].blinkon)
eq(500, screen._mode_info[terminal_mode_idx].blinkoff)
eq('block', screen._mode_info[terminal_mode_idx].cursor_shape)
end)
it('can be modified per terminal', function()
skip(is_os('win'), '#31587')
-- Set cursor to vertical bar with blink
tt.feed_csi('5 q')
screen:expect({
grid = [[
tty ready |
^ |
|*4
{3:-- TERMINAL --} |
]],
condition = function()
eq(500, screen._mode_info[terminal_mode_idx].blinkon)
eq(500, screen._mode_info[terminal_mode_idx].blinkoff)
eq('vertical', screen._mode_info[terminal_mode_idx].cursor_shape)
end,
})
tt.hide_cursor()
screen:expect({
grid = [[
tty ready |
|
|*4
{3:-- TERMINAL --} |
]],
condition = function()
eq(500, screen._mode_info[terminal_mode_idx].blinkon)
eq(500, screen._mode_info[terminal_mode_idx].blinkoff)
eq('vertical', screen._mode_info[terminal_mode_idx].cursor_shape)
end,
})
-- Exit terminal mode to reset terminal cursor settings to default and
-- create a new terminal window
feed([[<C-\><C-N>]])
command('set statusline=~~~')
command('new')
call('termopen', { testprg('tty-test') })
feed('i')
screen:expect({
grid = [[
tty ready |
^ |
{17:~~~ }|
rows: 2, cols: 50 |
|
{18:~~~ }|
{3:-- TERMINAL --} |
]],
condition = function()
-- New terminal, cursor resets to defaults
eq(500, screen._mode_info[terminal_mode_idx].blinkon)
eq(500, screen._mode_info[terminal_mode_idx].blinkoff)
eq('block', screen._mode_info[terminal_mode_idx].cursor_shape)
end,
})
-- Set cursor to underline, no blink
tt.feed_csi('4 q')
screen:expect({
grid = [[
tty ready |
^ |
{17:~~~ }|
rows: 2, cols: 50 |
|
{18:~~~ }|
{3:-- TERMINAL --} |
]],
condition = function()
eq(0, screen._mode_info[terminal_mode_idx].blinkon)
eq(0, screen._mode_info[terminal_mode_idx].blinkoff)
eq('horizontal', screen._mode_info[terminal_mode_idx].cursor_shape)
end,
})
-- Switch back to first terminal, cursor should still be hidden
command('wincmd p')
screen:expect({
grid = [[
tty ready |
|
{18:~~~ }|
rows: 2, cols: 50 |
|
{17:~~~ }|
{3:-- TERMINAL --} |
]],
condition = function()
eq(500, screen._mode_info[terminal_mode_idx].blinkon)
eq(500, screen._mode_info[terminal_mode_idx].blinkoff)
eq('vertical', screen._mode_info[terminal_mode_idx].cursor_shape)
end,
})
end)
it('can be positioned arbitrarily', function()
clear()
screen = tt.setup_child_nvim({
'-u',
'NONE',
'-i',
'NONE',
'--cmd',
n.nvim_set .. ' noshowmode',
})
screen:expect([[
^ |
~ |*4
|
{3:-- TERMINAL --} |
]])
feed('i<Tab>')
screen:expect([[
^ |
~ |*4
|
{3:-- TERMINAL --} |
]])
end)
it('preserves guicursor value on TermLeave #31612', function()
eq(3, screen._mode_info[terminal_mode_idx].hl_id)
-- Change 'guicursor' while terminal mode is active
command('set guicursor+=t:Error')
local error_hl_id = call('hlID', 'Error')
screen:expect({
condition = function()
eq(error_hl_id, screen._mode_info[terminal_mode_idx].hl_id)
end,
})
-- Exit terminal mode
feed([[<C-\><C-N>]])
screen:expect([[
tty ready |
^ |
|*5
]])
eq(error_hl_id, screen._mode_info[terminal_mode_idx].hl_id)
end) end)
end) end)
@ -171,19 +373,13 @@ describe('buffer cursor position is correct in terminal without number column',
}, { }, {
cols = 70, cols = 70,
}) })
screen:set_default_attr_ids({
[1] = { foreground = 253, background = 11 },
[2] = { reverse = true },
[3] = { bold = true },
[4] = { background = 11 },
})
-- Also check for real cursor position, as it is used for stuff like input methods -- Also check for real cursor position, as it is used for stuff like input methods
screen._handle_busy_start = function() end screen._handle_busy_start = function() end
screen._handle_busy_stop = function() end screen._handle_busy_stop = function() end
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:{2:^ } | :^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end end
@ -200,7 +396,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:aaaaaaaa{2:^ } | :aaaaaaaa^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 9 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 9 }, eval('nvim_win_get_cursor(0)'))
@ -208,7 +404,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:aaaaaaa^a{4: } | :aaaaaaa^a |
| |
]]) ]])
eq({ 6, 8 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 8 }, eval('nvim_win_get_cursor(0)'))
@ -219,7 +415,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:aaaaaa{2:^a}a | :aaaaaa^aa |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 7 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 7 }, eval('nvim_win_get_cursor(0)'))
@ -227,7 +423,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:aaaaa^a{4:a}a | :aaaaa^aaa |
| |
]]) ]])
eq({ 6, 6 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 6 }, eval('nvim_win_get_cursor(0)'))
@ -238,7 +434,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:a{2:^a}aaaaaa | :a^aaaaaaa |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 2 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 2 }, eval('nvim_win_get_cursor(0)'))
@ -246,7 +442,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:^a{4:a}aaaaaa | :^aaaaaaaa |
| |
]]) ]])
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
@ -263,7 +459,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:µµµµµµµµ{2:^ } | :µµµµµµµµ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 17 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 17 }, eval('nvim_win_get_cursor(0)'))
@ -271,7 +467,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:µµµµµµµ^µ{4: } | :µµµµµµµ^µ |
| |
]]) ]])
eq({ 6, 15 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 15 }, eval('nvim_win_get_cursor(0)'))
@ -282,7 +478,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:µµµµµµ{2:^µ}µ | :µµµµµµ^µµ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 13 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 13 }, eval('nvim_win_get_cursor(0)'))
@ -290,7 +486,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:µµµµµ^µ{4:µ}µ | :µµµµµ^µµµ |
| |
]]) ]])
eq({ 6, 11 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 11 }, eval('nvim_win_get_cursor(0)'))
@ -301,7 +497,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:µ{2:^µ}µµµµµµ | :µ^µµµµµµµ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 3 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 3 }, eval('nvim_win_get_cursor(0)'))
@ -309,7 +505,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:^µ{4:µ}µµµµµµ | :^µµµµµµµµ |
| |
]]) ]])
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
@ -326,7 +522,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{2:^ } | :µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 33 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 33 }, eval('nvim_win_get_cursor(0)'))
@ -334,7 +530,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:µ̳µ̳µ̳µ̳µ̳µ̳µ̳^µ̳{4: } | :µ̳µ̳µ̳µ̳µ̳µ̳µ̳^µ̳ |
| |
]]) ]])
eq({ 6, 29 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 29 }, eval('nvim_win_get_cursor(0)'))
@ -346,7 +542,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:µ̳µ̳µ̳µ̳µ̳µ̳{2:^µ̳}µ̳ | :µ̳µ̳µ̳µ̳µ̳µ̳^µ̳µ̳ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 25 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 25 }, eval('nvim_win_get_cursor(0)'))
@ -354,7 +550,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:µ̳µ̳µ̳µ̳µ̳^µ̳{4:µ̳}µ̳ | :µ̳µ̳µ̳µ̳µ̳^µ̳µ̳µ̳ |
| |
]]) ]])
eq({ 6, 21 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 21 }, eval('nvim_win_get_cursor(0)'))
@ -366,7 +562,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:µ̳{2:^µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ | :µ̳^µ̳µ̳µ̳µ̳µ̳µ̳µ̳ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 5 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 5 }, eval('nvim_win_get_cursor(0)'))
@ -374,7 +570,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:^µ̳{4:µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ | :^µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳ |
| |
]]) ]])
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
@ -391,7 +587,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:{2:^ } | :^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 25 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 25 }, eval('nvim_win_get_cursor(0)'))
@ -399,7 +595,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:^{4: } | :^ |
| |
]]) ]])
eq({ 6, 22 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 22 }, eval('nvim_win_get_cursor(0)'))
@ -410,7 +606,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:{2:^} | :^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 19 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 19 }, eval('nvim_win_get_cursor(0)'))
@ -418,7 +614,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:^{4:} | :^ |
| |
]]) ]])
eq({ 6, 16 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 16 }, eval('nvim_win_get_cursor(0)'))
@ -429,7 +625,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:{2:^} | :^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 4 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 4 }, eval('nvim_win_get_cursor(0)'))
@ -437,7 +633,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:^{4:} | :^ |
| |
]]) ]])
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
@ -450,7 +646,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:aaaaaaaa {2:^ } | :aaaaaaaa ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()')) matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()'))
@ -459,7 +655,7 @@ describe('buffer cursor position is correct in terminal without number column',
screen:expect([[ screen:expect([[
|*4 |*4
Entering Ex mode. Type "visual" to go to Normal mode. | Entering Ex mode. Type "visual" to go to Normal mode. |
:aaaaaaaa ^ {4: } | :aaaaaaaa ^ |
| |
]]) ]])
eq({ 6, 12 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 12 }, eval('nvim_win_get_cursor(0)'))
@ -488,13 +684,6 @@ describe('buffer cursor position is correct in terminal with number column', fun
}, { }, {
cols = 70, cols = 70,
}) })
screen:set_default_attr_ids({
[1] = { foreground = 253, background = 11 },
[2] = { reverse = true },
[3] = { bold = true },
[4] = { background = 11 },
[7] = { foreground = 130 },
})
-- Also check for real cursor position, as it is used for stuff like input methods -- Also check for real cursor position, as it is used for stuff like input methods
screen._handle_busy_start = function() end screen._handle_busy_start = function() end
screen._handle_busy_stop = function() end screen._handle_busy_stop = function() end
@ -504,7 +693,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:{2:^ } | {7: 6 }:^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end end
@ -527,7 +716,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:aaaaaaaa{2:^ } | {7: 6 }:aaaaaaaa^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 9 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 9 }, eval('nvim_win_get_cursor(0)'))
@ -538,7 +727,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:aaaaaaa^a{4: } | {7: 6 }:aaaaaaa^a |
| |
]]) ]])
eq({ 6, 8 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 8 }, eval('nvim_win_get_cursor(0)'))
@ -552,7 +741,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:aaaaaa{2:^a}a | {7: 6 }:aaaaaa^aa |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 7 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 7 }, eval('nvim_win_get_cursor(0)'))
@ -563,7 +752,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:aaaaa^a{4:a}a | {7: 6 }:aaaaa^aaa |
| |
]]) ]])
eq({ 6, 6 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 6 }, eval('nvim_win_get_cursor(0)'))
@ -577,7 +766,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:a{2:^a}aaaaaa | {7: 6 }:a^aaaaaaa |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 2 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 2 }, eval('nvim_win_get_cursor(0)'))
@ -588,7 +777,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:^a{4:a}aaaaaa | {7: 6 }:^aaaaaaaa |
| |
]]) ]])
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
@ -608,7 +797,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:µµµµµµµµ{2:^ } | {7: 6 }:µµµµµµµµ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 17 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 17 }, eval('nvim_win_get_cursor(0)'))
@ -619,7 +808,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:µµµµµµµ^µ{4: } | {7: 6 }:µµµµµµµ^µ |
| |
]]) ]])
eq({ 6, 15 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 15 }, eval('nvim_win_get_cursor(0)'))
@ -633,7 +822,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:µµµµµµ{2:^µ}µ | {7: 6 }:µµµµµµ^µµ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 13 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 13 }, eval('nvim_win_get_cursor(0)'))
@ -644,7 +833,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:µµµµµ^µ{4:µ}µ | {7: 6 }:µµµµµ^µµµ |
| |
]]) ]])
eq({ 6, 11 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 11 }, eval('nvim_win_get_cursor(0)'))
@ -658,7 +847,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:µ{2:^µ}µµµµµµ | {7: 6 }:µ^µµµµµµµ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 3 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 3 }, eval('nvim_win_get_cursor(0)'))
@ -669,7 +858,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:^µ{4:µ}µµµµµµ | {7: 6 }:^µµµµµµµµ |
| |
]]) ]])
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
@ -689,7 +878,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{2:^ } | {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 33 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 33 }, eval('nvim_win_get_cursor(0)'))
@ -700,7 +889,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳^µ̳{4: } | {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳^µ̳ |
| |
]]) ]])
eq({ 6, 29 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 29 }, eval('nvim_win_get_cursor(0)'))
@ -715,7 +904,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳{2:^µ̳}µ̳ | {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳^µ̳µ̳ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 25 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 25 }, eval('nvim_win_get_cursor(0)'))
@ -726,7 +915,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:µ̳µ̳µ̳µ̳µ̳^µ̳{4:µ̳}µ̳ | {7: 6 }:µ̳µ̳µ̳µ̳µ̳^µ̳µ̳µ̳ |
| |
]]) ]])
eq({ 6, 21 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 21 }, eval('nvim_win_get_cursor(0)'))
@ -741,7 +930,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:µ̳{2:^µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ | {7: 6 }:µ̳^µ̳µ̳µ̳µ̳µ̳µ̳µ̳ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 5 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 5 }, eval('nvim_win_get_cursor(0)'))
@ -752,7 +941,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:^µ̳{4:µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ | {7: 6 }:^µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳ |
| |
]]) ]])
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
@ -772,7 +961,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:{2:^ } | {7: 6 }:^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 25 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 25 }, eval('nvim_win_get_cursor(0)'))
@ -783,7 +972,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:^{4: } | {7: 6 }:^ |
| |
]]) ]])
eq({ 6, 22 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 22 }, eval('nvim_win_get_cursor(0)'))
@ -797,7 +986,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:{2:^} | {7: 6 }:^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 19 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 19 }, eval('nvim_win_get_cursor(0)'))
@ -808,7 +997,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:^{4:} | {7: 6 }:^ |
| |
]]) ]])
eq({ 6, 16 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 16 }, eval('nvim_win_get_cursor(0)'))
@ -822,7 +1011,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:{2:^} | {7: 6 }:^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq({ 6, 4 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 4 }, eval('nvim_win_get_cursor(0)'))
@ -833,7 +1022,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:^{4:} | {7: 6 }:^ |
| |
]]) ]])
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
@ -849,7 +1038,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:aaaaaaaa {2:^ } | {7: 6 }:aaaaaaaa ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()')) matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()'))
@ -861,7 +1050,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } | {7: 3 } |
{7: 4 } | {7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
{7: 6 }:aaaaaaaa ^ {4: } | {7: 6 }:aaaaaaaa ^ |
| |
]]) ]])
eq({ 6, 12 }, eval('nvim_win_get_cursor(0)')) eq({ 6, 12 }, eval('nvim_win_get_cursor(0)'))

View File

@ -37,7 +37,7 @@ describe(':terminal highlight', function()
feed('i') feed('i')
screen:expect([[ screen:expect([[
tty ready | tty ready |
{10: } | ^ |
|*4 |*4
{5:-- TERMINAL --} | {5:-- TERMINAL --} |
]]) ]])
@ -61,7 +61,7 @@ describe(':terminal highlight', function()
skip(is_os('win')) skip(is_os('win'))
screen:expect(sub([[ screen:expect(sub([[
tty ready | tty ready |
{NUM:text}text{10: } | {NUM:text}text^ |
|*4 |*4
{5:-- TERMINAL --} | {5:-- TERMINAL --} |
]])) ]]))
@ -84,7 +84,7 @@ describe(':terminal highlight', function()
line6 | line6 |
line7 | line7 |
line8 | line8 |
{10: } | ^ |
{5:-- TERMINAL --} | {5:-- TERMINAL --} |
]]) ]])
feed('<c-\\><c-n>gg') feed('<c-\\><c-n>gg')
@ -195,7 +195,7 @@ it('CursorLine and CursorColumn work in :terminal buffer in Normal mode', functi
local screen = Screen.new(50, 7) local screen = Screen.new(50, 7)
screen:set_default_attr_ids({ screen:set_default_attr_ids({
[1] = { background = Screen.colors.Grey90 }, -- CursorLine, CursorColumn [1] = { background = Screen.colors.Grey90 }, -- CursorLine, CursorColumn
[2] = { reverse = true }, -- TermCursor [2] = { reverse = true },
[3] = { bold = true }, -- ModeMsg [3] = { bold = true }, -- ModeMsg
[4] = { background = Screen.colors.Grey90, reverse = true }, [4] = { background = Screen.colors.Grey90, reverse = true },
[5] = { background = Screen.colors.Red }, [5] = { background = Screen.colors.Red },
@ -234,7 +234,7 @@ it('CursorLine and CursorColumn work in :terminal buffer in Normal mode', functi
foobar foobar foobar foobar foobar foobar foobar f| foobar foobar foobar foobar foobar foobar foobar f|
oobar foobar foobar foobar foobar foobar foobar fo| oobar foobar foobar foobar foobar foobar foobar fo|
obar foobar foobar foobar foobar foobar foobar foo| obar foobar foobar foobar foobar foobar foobar foo|
bar foobar{2: } | bar foobar^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
-- Leaving terminal mode restores old values. -- Leaving terminal mode restores old values.
@ -248,46 +248,60 @@ it('CursorLine and CursorColumn work in :terminal buffer in Normal mode', functi
{1:bar fooba^r }| {1:bar fooba^r }|
| |
]]) ]])
-- CursorLine and CursorColumn are combined with TermCursorNC.
command('highlight TermCursorNC gui=reverse') -- Skip the rest of these tests on Windows #31587
if is_os('win') then
return
end
-- CursorLine and CursorColumn are combined with terminal colors.
tt.set_reverse()
tt.feed_data(' foobar')
tt.clear_attrs()
screen:expect([[ screen:expect([[
tty ready{1: } | tty ready{1: } |
foobar f{1:o}obar foobar foobar foobar foobar foobar | foobar f{1:o}obar foobar foobar foobar foobar foobar |
foobar fo{1:o}bar foobar foobar foobar foobar foobar f| foobar fo{1:o}bar foobar foobar foobar foobar foobar f|
oobar foo{1:b}ar foobar foobar foobar foobar foobar fo| oobar foo{1:b}ar foobar foobar foobar foobar foobar fo|
obar foob{1:a}r foobar foobar foobar foobar foobar foo| obar foob{1:a}r foobar foobar foobar foobar foobar foo|
{1:bar fooba^r}{4: }{1: }| {1:bar fooba^r}{4: foobar}{1: }|
| |
]]) ]])
feed('2gg11|') feed('2gg15|')
screen:expect([[ screen:expect([[
tty ready {1: } | tty ready {1: } |
{1: foobar fo^obar foobar foobar foobar foobar foobar }| {1: foobar foobar^ foobar foobar foobar foobar foobar }|
foobar foo{1:b}ar foobar foobar foobar foobar foobar f| foobar foobar {1:f}oobar foobar foobar foobar foobar f|
oobar foob{1:a}r foobar foobar foobar foobar foobar fo| oobar foobar f{1:o}obar foobar foobar foobar foobar fo|
obar fooba{1:r} foobar foobar foobar foobar foobar foo| obar foobar fo{1:o}bar foobar foobar foobar foobar foo|
bar foobar{4: } | bar foobar{2: foo}{4:b}{2:ar} |
| |
]]) ]])
-- TermCursorNC has higher precedence.
command('highlight TermCursorNC gui=NONE guibg=Red') -- Set bg color to red
tt.feed_csi('48;2;255:0:0m')
tt.feed_data(' foobar')
tt.clear_attrs()
feed('2gg20|')
-- Terminal color has higher precedence
screen:expect([[ screen:expect([[
tty ready {1: } | tty ready {1: } |
{1: foobar fo^obar foobar foobar foobar foobar foobar }| {1: foobar foobar foob^ar foobar foobar foobar foobar }|
foobar foo{1:b}ar foobar foobar foobar foobar foobar f| foobar foobar fooba{1:r} foobar foobar foobar foobar f|
oobar foob{1:a}r foobar foobar foobar foobar foobar fo| oobar foobar foobar{1: }foobar foobar foobar foobar fo|
obar fooba{1:r} foobar foobar foobar foobar foobar foo| obar foobar foobar {1:f}oobar foobar foobar foobar foo|
bar foobar{5: } | bar foobar{2: foobar}{5: foobar} |
| |
]]) ]])
feed('G$') feed('G$')
screen:expect([[ screen:expect([[
tty ready{1: } | tty ready {1: } |
foobar f{1:o}obar foobar foobar foobar foobar foobar | foobar foobar foobar f{1:o}obar foobar foobar foobar |
foobar fo{1:o}bar foobar foobar foobar foobar foobar f| foobar foobar foobar fo{1:o}bar foobar foobar foobar f|
oobar foo{1:b}ar foobar foobar foobar foobar foobar fo| oobar foobar foobar foo{1:b}ar foobar foobar foobar fo|
obar foob{1:a}r foobar foobar foobar foobar foobar foo| obar foobar foobar foob{1:a}r foobar foobar foobar foo|
{1:bar fooba^r}{5: }{1: }| {1:bar foobar}{4: foobar}{5: fooba^r}{1: }|
| |
]]) ]])
end) end)
@ -300,18 +314,17 @@ describe(':terminal highlight forwarding', function()
screen = Screen.new(50, 7) screen = Screen.new(50, 7)
screen:set_rgb_cterm(true) screen:set_rgb_cterm(true)
screen:set_default_attr_ids({ screen:set_default_attr_ids({
[1] = { { reverse = true }, { reverse = true } }, [1] = { { bold = true }, { bold = true } },
[2] = { { bold = true }, { bold = true } }, [2] = { { fg_indexed = true, foreground = tonumber('0xe0e000') }, { foreground = 3 } },
[3] = { { fg_indexed = true, foreground = tonumber('0xe0e000') }, { foreground = 3 } }, [3] = { { foreground = tonumber('0xff8000') }, {} },
[4] = { { foreground = tonumber('0xff8000') }, {} },
}) })
command(("enew | call termopen(['%s'])"):format(testprg('tty-test'))) command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
feed('i') feed('i')
screen:expect([[ screen:expect([[
tty ready | tty ready |
{1: } | ^ |
|*4 |*4
{2:-- TERMINAL --} | {1:-- TERMINAL --} |
]]) ]])
end) end)
@ -326,9 +339,9 @@ describe(':terminal highlight forwarding', function()
screen:expect { screen:expect {
grid = [[ grid = [[
tty ready | tty ready |
{3:text}{4:color}text{1: } | {2:text}{3:color}text^ |
|*4 |*4
{2:-- TERMINAL --} | {1:-- TERMINAL --} |
]], ]],
} }
end) end)
@ -355,7 +368,7 @@ describe(':terminal highlight with custom palette', function()
feed('i') feed('i')
screen:expect([[ screen:expect([[
tty ready | tty ready |
{7: } | ^ |
|*4 |*4
{9:-- TERMINAL --} | {9:-- TERMINAL --} |
]]) ]])
@ -369,7 +382,7 @@ describe(':terminal highlight with custom palette', function()
tt.feed_data('text') tt.feed_data('text')
screen:expect([[ screen:expect([[
tty ready | tty ready |
{1:text}text{7: } | {1:text}text^ |
|*4 |*4
{9:-- TERMINAL --} | {9:-- TERMINAL --} |
]]) ]])

View File

@ -32,7 +32,7 @@ describe(':terminal mouse', function()
line28 | line28 |
line29 | line29 |
line30 | line30 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
@ -107,7 +107,7 @@ describe(':terminal mouse', function()
line29 | line29 |
line30 | line30 |
mouse enabled | mouse enabled |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
@ -121,7 +121,7 @@ describe(':terminal mouse', function()
line29 | line29 |
line30 | line30 |
mouse enabled | mouse enabled |
"#{1: } | "#^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
feed('<LeftDrag><2,2>') feed('<LeftDrag><2,2>')
@ -131,7 +131,7 @@ describe(':terminal mouse', function()
line29 | line29 |
line30 | line30 |
mouse enabled | mouse enabled |
@##{1: } | @##^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
feed('<LeftDrag><3,2>') feed('<LeftDrag><3,2>')
@ -141,7 +141,7 @@ describe(':terminal mouse', function()
line29 | line29 |
line30 | line30 |
mouse enabled | mouse enabled |
@$#{1: } | @$#^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
feed('<LeftRelease><3,2>') feed('<LeftRelease><3,2>')
@ -151,7 +151,7 @@ describe(':terminal mouse', function()
line29 | line29 |
line30 | line30 |
mouse enabled | mouse enabled |
#$#{1: } | #$#^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
@ -165,7 +165,7 @@ describe(':terminal mouse', function()
line29 | line29 |
line30 | line30 |
mouse enabled | mouse enabled |
`!!{1: } | `!!^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
@ -179,7 +179,7 @@ describe(':terminal mouse', function()
line29 | line29 |
line30 | line30 |
mouse enabled | mouse enabled |
"#{1: } | "#^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
feed('<ScrollWheelUp><1,2>') feed('<ScrollWheelUp><1,2>')
@ -189,7 +189,7 @@ describe(':terminal mouse', function()
line29 | line29 |
line30 | line30 |
mouse enabled | mouse enabled |
`"#{1: } | `"#^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
feed('<LeftDrag><2,2>') feed('<LeftDrag><2,2>')
@ -199,7 +199,7 @@ describe(':terminal mouse', function()
line29 | line29 |
line30 | line30 |
mouse enabled | mouse enabled |
@##{1: } | @##^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
feed('<ScrollWheelUp><2,2>') feed('<ScrollWheelUp><2,2>')
@ -209,7 +209,7 @@ describe(':terminal mouse', function()
line29 | line29 |
line30 | line30 |
mouse enabled | mouse enabled |
`##{1: } | `##^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
feed('<LeftRelease><2,2>') feed('<LeftRelease><2,2>')
@ -219,7 +219,7 @@ describe(':terminal mouse', function()
line29 | line29 |
line30 | line30 |
mouse enabled | mouse enabled |
###{1: } | ###^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
@ -237,7 +237,7 @@ describe(':terminal mouse', function()
{7: 13 }line30 | {7: 13 }line30 |
{7: 14 }mouse enabled | {7: 14 }mouse enabled |
{7: 15 }rows: 6, cols: 46 | {7: 15 }rows: 6, cols: 46 |
{7: 16 }{2: } | {7: 16 } |
| |
]]) ]])
-- If click on the coordinate (0,1) of the region of the terminal -- If click on the coordinate (0,1) of the region of the terminal
@ -249,7 +249,7 @@ describe(':terminal mouse', function()
{7: 13 }line30 | {7: 13 }line30 |
{7: 14 }mouse enabled | {7: 14 }mouse enabled |
{7: 15 }rows: 6, cols: 46 | {7: 15 }rows: 6, cols: 46 |
{7: 16 } !"{1: } | {7: 16 } !"^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
@ -261,7 +261,7 @@ describe(':terminal mouse', function()
line30 | line30 |
mouse enabled | mouse enabled |
rows: 5, cols: 50 | rows: 5, cols: 50 |
{1: } | ^ |
========== | ========== |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -271,7 +271,7 @@ describe(':terminal mouse', function()
line30 | line30 |
mouse enabled | mouse enabled |
rows: 5, cols: 50 | rows: 5, cols: 50 |
{2:^ } | ^ |
========== | ========== |
| |
]]) ]])
@ -280,7 +280,7 @@ describe(':terminal mouse', function()
mouse enabled | mouse enabled |
rows: 5, cols: 50 | rows: 5, cols: 50 |
rows: 4, cols: 50 | rows: 4, cols: 50 |
{2:^ } | ^ |
========== | ========== |
|*2 |*2
]]) ]])
@ -293,7 +293,7 @@ describe(':terminal mouse', function()
line30 {4:~ }| line30 {4:~ }|
mouse enabled {4:~ }| mouse enabled {4:~ }|
rows: 5, cols: 24 {4:~ }| rows: 5, cols: 24 {4:~ }|
{1: } {4:~ }| ^ {4:~ }|
========== ========== | ========== ========== |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -303,7 +303,7 @@ describe(':terminal mouse', function()
line30 {4:~ }| line30 {4:~ }|
mouse enabled {4:~ }| mouse enabled {4:~ }|
rows: 5, cols: 24 {4:~ }| rows: 5, cols: 24 {4:~ }|
{2:^ } {4:~ }| ^ {4:~ }|
========== ========== | ========== ========== |
| |
]]) ]])
@ -313,7 +313,7 @@ describe(':terminal mouse', function()
mouse enabled {4:~ }| mouse enabled {4:~ }|
rows: 5, cols: 24 {4:~ }| rows: 5, cols: 24 {4:~ }|
rows: 5, cols: 23 {4:~ }| rows: 5, cols: 23 {4:~ }|
{2:^ } {4:~ }| ^ {4:~ }|
========== ========== | ========== ========== |
| |
]]) ]])
@ -327,7 +327,7 @@ describe(':terminal mouse', function()
line30 | line30 |
mouse enabled | mouse enabled |
rows: 5, cols: 50 | rows: 5, cols: 50 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
feed('<LeftMouse><0,0>') feed('<LeftMouse><0,0>')
@ -337,7 +337,7 @@ describe(':terminal mouse', function()
line30 | line30 |
mouse enabled | mouse enabled |
rows: 5, cols: 50 | rows: 5, cols: 50 |
{2:^ } | ^ |
| |
]]) ]])
command('set showtabline=2 tabline=TABLINE | startinsert') command('set showtabline=2 tabline=TABLINE | startinsert')
@ -347,7 +347,7 @@ describe(':terminal mouse', function()
mouse enabled | mouse enabled |
rows: 5, cols: 50 | rows: 5, cols: 50 |
rows: 4, cols: 50 | rows: 4, cols: 50 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
feed('<LeftMouse><0,0>') feed('<LeftMouse><0,0>')
@ -357,7 +357,7 @@ describe(':terminal mouse', function()
mouse enabled | mouse enabled |
rows: 5, cols: 50 | rows: 5, cols: 50 |
rows: 4, cols: 50 | rows: 4, cols: 50 |
{2:^ } | ^ |
| |
]]) ]])
command('setlocal winbar= | startinsert') command('setlocal winbar= | startinsert')
@ -367,7 +367,7 @@ describe(':terminal mouse', function()
rows: 5, cols: 50 | rows: 5, cols: 50 |
rows: 4, cols: 50 | rows: 4, cols: 50 |
rows: 5, cols: 50 | rows: 5, cols: 50 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
feed('<LeftMouse><0,0>') feed('<LeftMouse><0,0>')
@ -377,7 +377,7 @@ describe(':terminal mouse', function()
rows: 5, cols: 50 | rows: 5, cols: 50 |
rows: 4, cols: 50 | rows: 4, cols: 50 |
rows: 5, cols: 50 | rows: 5, cols: 50 |
{2:^ } | ^ |
| |
]]) ]])
end) end)
@ -391,7 +391,7 @@ describe(':terminal mouse', function()
line29 line29 | line29 line29 |
line30 line30 | line30 line30 |
rows: 5, cols: 25 rows: 5, cols: 25 | rows: 5, cols: 25 rows: 5, cols: 25 |
{2:^ } {2: } | ^ |
========== ========== | ========== ========== |
:vsp | :vsp |
]]) ]])
@ -401,7 +401,7 @@ describe(':terminal mouse', function()
{4:~ }line30 | {4:~ }line30 |
{4:~ }rows: 5, cols: 25 | {4:~ }rows: 5, cols: 25 |
{4:~ }rows: 5, cols: 24 | {4:~ }rows: 5, cols: 24 |
{4:~ }{2: } | {4:~ } |
========== ========== | ========== ========== |
:enew | set number | :enew | set number |
]]) ]])
@ -411,7 +411,7 @@ describe(':terminal mouse', function()
{7: 28 }line line30 | {7: 28 }line line30 |
{7: 29 }line rows: 5, cols: 25 | {7: 29 }line rows: 5, cols: 25 |
{7: 30 }line rows: 5, cols: 24 | {7: 30 }line rows: 5, cols: 24 |
{7: 31 }^ {2: } | {7: 31 }^ |
========== ========== | ========== ========== |
| |
]]) ]])
@ -421,7 +421,7 @@ describe(':terminal mouse', function()
{7: 28 }line line30 | {7: 28 }line line30 |
{7: 29 }line rows: 5, cols: 25 | {7: 29 }line rows: 5, cols: 25 |
{7: 30 }line rows: 5, cols: 24 | {7: 30 }line rows: 5, cols: 24 |
{7: 31 } {1: } | {7: 31 } ^ |
========== ========== | ========== ========== |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -434,7 +434,7 @@ describe(':terminal mouse', function()
{7: 28 }line rows: 5, cols: 25 | {7: 28 }line rows: 5, cols: 25 |
{7: 29 }line rows: 5, cols: 24 | {7: 29 }line rows: 5, cols: 24 |
{7: 30 }line mouse enabled | {7: 30 }line mouse enabled |
{7: 31 } {1: } | {7: 31 } ^ |
========== ========== | ========== ========== |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -447,7 +447,7 @@ describe(':terminal mouse', function()
{7: 22 }line rows: 5, cols: 25 | {7: 22 }line rows: 5, cols: 25 |
{7: 23 }line rows: 5, cols: 24 | {7: 23 }line rows: 5, cols: 24 |
{7: 24 }line mouse enabled | {7: 24 }line mouse enabled |
{7: 25 }line {1: } | {7: 25 }line ^ |
========== ========== | ========== ========== |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -457,7 +457,7 @@ describe(':terminal mouse', function()
{7: 27 }line rows: 5, cols: 25 | {7: 27 }line rows: 5, cols: 25 |
{7: 28 }line rows: 5, cols: 24 | {7: 28 }line rows: 5, cols: 24 |
{7: 29 }line mouse enabled | {7: 29 }line mouse enabled |
{7: 30 }line {1: } | {7: 30 }line ^ |
========== ========== | ========== ========== |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -468,7 +468,7 @@ describe(':terminal mouse', function()
{7: 17 }line rows: 5, cols: 25 | {7: 17 }line rows: 5, cols: 25 |
{7: 18 }line rows: 5, cols: 24 | {7: 18 }line rows: 5, cols: 24 |
{7: 19 }line mouse enabled | {7: 19 }line mouse enabled |
{7: 20 }line {1: } | {7: 20 }line ^ |
========== ========== | ========== ========== |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -483,7 +483,7 @@ describe(':terminal mouse', function()
{7: 2 }linelinelinelineline rows: 5, cols: 25 | {7: 2 }linelinelinelineline rows: 5, cols: 25 |
{7: 3 }linelinelinelineline rows: 5, cols: 24 | {7: 3 }linelinelinelineline rows: 5, cols: 24 |
{7: 4 }linelinelinelineline mouse enabled | {7: 4 }linelinelinelineline mouse enabled |
{7: 5 }linelinelinelineline {1: } | {7: 5 }linelinelinelineline ^ |
========== ========== | ========== ========== |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -493,7 +493,7 @@ describe(':terminal mouse', function()
{7: 2 }nelinelineline rows: 5, cols: 25 | {7: 2 }nelinelineline rows: 5, cols: 25 |
{7: 3 }nelinelineline rows: 5, cols: 24 | {7: 3 }nelinelineline rows: 5, cols: 24 |
{7: 4 }nelinelineline mouse enabled | {7: 4 }nelinelineline mouse enabled |
{7: 5 }nelinelineline {1: } | {7: 5 }nelinelineline ^ |
========== ========== | ========== ========== |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -504,7 +504,7 @@ describe(':terminal mouse', function()
{7: 2 }nelinelinelineline rows: 5, cols: 25 | {7: 2 }nelinelinelineline rows: 5, cols: 25 |
{7: 3 }nelinelinelineline rows: 5, cols: 24 | {7: 3 }nelinelinelineline rows: 5, cols: 24 |
{7: 4 }nelinelinelineline mouse enabled | {7: 4 }nelinelinelineline mouse enabled |
{7: 5 }nelinelinelineline {1: } | {7: 5 }nelinelinelineline ^ |
========== ========== | ========== ========== |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -517,7 +517,7 @@ describe(':terminal mouse', function()
{7: 28 }l^ine rows: 5, cols: 25 | {7: 28 }l^ine rows: 5, cols: 25 |
{7: 29 }line rows: 5, cols: 24 | {7: 29 }line rows: 5, cols: 24 |
{7: 30 }line mouse enabled | {7: 30 }line mouse enabled |
{7: 31 } {2: } | {7: 31 } |
========== ========== | ========== ========== |
| |
]]) ]])
@ -531,7 +531,7 @@ describe(':terminal mouse', function()
{7: 28 }line rows: 5, cols: 25 | {7: 28 }line rows: 5, cols: 25 |
{7: 29 }line rows: 5, cols: 24 | {7: 29 }line rows: 5, cols: 24 |
{7: 30 }line mouse enabled | {7: 30 }line mouse enabled |
{7: 31 }^ {2: } | {7: 31 }^ |
========== ========== | ========== ========== |
| |
]]) ]])
@ -541,7 +541,7 @@ describe(':terminal mouse', function()
rows: 5, cols: 24 rows: 5, cols: 24 | rows: 5, cols: 24 rows: 5, cols: 24 |
mouse enabled mouse enabled | mouse enabled mouse enabled |
rows: 5, cols: 25 rows: 5, cols: 25 | rows: 5, cols: 25 rows: 5, cols: 25 |
{2:^ } {2: } | ^ |
========== ========== | ========== ========== |
:bn | :bn |
]]) ]])
@ -551,7 +551,7 @@ describe(':terminal mouse', function()
{7: 28 }line mouse enabled | {7: 28 }line mouse enabled |
{7: 29 }line rows: 5, cols: 25 | {7: 29 }line rows: 5, cols: 25 |
{7: 30 }line rows: 5, cols: 24 | {7: 30 }line rows: 5, cols: 24 |
{7: 31 }^ {2: } | {7: 31 }^ |
========== ========== | ========== ========== |
:bn | :bn |
]]) ]])

View File

@ -39,7 +39,7 @@ describe(':terminal scrollback', function()
line28 | line28 |
line29 | line29 |
line30 | line30 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
@ -67,7 +67,7 @@ describe(':terminal scrollback', function()
line2 | line2 |
line3 | line3 |
line4 | line4 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
@ -84,7 +84,7 @@ describe(':terminal scrollback', function()
line3 | line3 |
line4 | line4 |
line5 | line5 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq(7, api.nvim_buf_line_count(0)) eq(7, api.nvim_buf_line_count(0))
@ -102,7 +102,7 @@ describe(':terminal scrollback', function()
line5 | line5 |
line6 | line6 |
line7 | line7 |
line8{1: } | line8^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -135,7 +135,7 @@ describe(':terminal scrollback', function()
line5 | line5 |
line6 | line6 |
line7 | line7 |
^line8{2: } | ^line8 |
| |
]]) ]])
end) end)
@ -151,7 +151,7 @@ describe(':terminal scrollback', function()
line3 | line3 |
line4 | line4 |
rows: 5, cols: 28 | rows: 5, cols: 28 |
{2:^ } | ^ |
| |
]]) ]])
end end
@ -168,7 +168,7 @@ describe(':terminal scrollback', function()
screen:expect([[ screen:expect([[
rows: 5, cols: 28 | rows: 5, cols: 28 |
rows: 3, cols: 26 | rows: 3, cols: 26 |
{2:^ } | ^ |
| |
]]) ]])
eq(8, api.nvim_buf_line_count(0)) eq(8, api.nvim_buf_line_count(0))
@ -201,7 +201,7 @@ describe(':terminal scrollback', function()
screen:expect([[ screen:expect([[
tty ready | tty ready |
rows: 4, cols: 30 | rows: 4, cols: 30 |
{1: } | ^ |
| |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -220,7 +220,7 @@ describe(':terminal scrollback', function()
screen:expect([[ screen:expect([[
rows: 4, cols: 30 | rows: 4, cols: 30 |
rows: 3, cols: 30 | rows: 3, cols: 30 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq(4, api.nvim_buf_line_count(0)) eq(4, api.nvim_buf_line_count(0))
@ -235,7 +235,7 @@ describe(':terminal scrollback', function()
screen:expect([[ screen:expect([[
rows: 4, cols: 30 | rows: 4, cols: 30 |
rows: 3, cols: 30 | rows: 3, cols: 30 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
@ -252,14 +252,14 @@ describe(':terminal scrollback', function()
line2 | line2 |
line3 | line3 |
line4 | line4 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
screen:try_resize(screen._width, screen._height - 3) screen:try_resize(screen._width, screen._height - 3)
screen:expect([[ screen:expect([[
line4 | line4 |
rows: 3, cols: 30 | rows: 3, cols: 30 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq(7, api.nvim_buf_line_count(0)) eq(7, api.nvim_buf_line_count(0))
@ -278,7 +278,7 @@ describe(':terminal scrollback', function()
line4 | line4 |
rows: 3, cols: 30 | rows: 3, cols: 30 |
rows: 4, cols: 30 | rows: 4, cols: 30 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end end
@ -300,7 +300,7 @@ describe(':terminal scrollback', function()
rows: 3, cols: 30 | rows: 3, cols: 30 |
rows: 4, cols: 30 | rows: 4, cols: 30 |
rows: 7, cols: 30 | rows: 7, cols: 30 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
eq(9, api.nvim_buf_line_count(0)) eq(9, api.nvim_buf_line_count(0))
@ -337,7 +337,7 @@ describe(':terminal scrollback', function()
rows: 4, cols: 30 | rows: 4, cols: 30 |
rows: 7, cols: 30 | rows: 7, cols: 30 |
rows: 11, cols: 30 | rows: 11, cols: 30 |
{1: } | ^ |
| |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -362,7 +362,7 @@ describe(':terminal prints more lines than the screen height and exits', functio
line8 | line8 |
line9 | line9 |
| |
[Process exited 0]{2: } | [Process exited 0]^ |
{5:-- TERMINAL --} | {5:-- TERMINAL --} |
]]) ]])
feed('<cr>') feed('<cr>')
@ -454,7 +454,7 @@ describe("'scrollback' option", function()
39: line | 39: line |
40: line | 40: line |
| |
${1: } | $^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]], ]],
} }
@ -493,7 +493,7 @@ describe("'scrollback' option", function()
line28 | line28 |
line29 | line29 |
line30 | line30 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
local term_height = 6 -- Actual terminal screen height, not the scrollback local term_height = 6 -- Actual terminal screen height, not the scrollback
@ -634,7 +634,7 @@ describe('pending scrollback line handling', function()
screen:expect [[ screen:expect [[
hi |*4 hi |*4
| |
[Process exited 0]{2: } | [Process exited 0]^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]] ]]
assert_alive() assert_alive()

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,7 @@ describe(':terminal window', function()
screen:expect([[ screen:expect([[
{7:1 }tty ready | {7:1 }tty ready |
{7:2 }rows: 6, cols: 48 | {7:2 }rows: 6, cols: 48 |
{7:3 }{1: } | {7:3 }^ |
{7:4 } | {7:4 } |
{7:5 } | {7:5 } |
{7:6 } | {7:6 } |
@ -73,7 +73,7 @@ describe(':terminal window', function()
{7:1 }tty ready | {7:1 }tty ready |
{7:2 }rows: 6, cols: 48 | {7:2 }rows: 6, cols: 48 |
{7:3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV| {7:3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV|
{7:4 }WXYZ{1: } | {7:4 }WXYZ^ |
{7:5 } | {7:5 } |
{7:6 } | {7:6 } |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
@ -87,7 +87,7 @@ describe(':terminal window', function()
{7: 2 }rows: 6, cols: 48 | {7: 2 }rows: 6, cols: 48 |
{7: 3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO| {7: 3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO|
{7: 4 }PQRSTUVWXYZrows: 6, cols: 41 | {7: 4 }PQRSTUVWXYZrows: 6, cols: 41 |
{7: 5 }{1: } | {7: 5 }^ |
{7: 6 } | {7: 6 } |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -98,7 +98,7 @@ describe(':terminal window', function()
{7: 3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO| {7: 3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO|
{7: 4 }PQRSTUVWXYZrows: 6, cols: 41 | {7: 4 }PQRSTUVWXYZrows: 6, cols: 41 |
{7: 5 } abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN| {7: 5 } abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN|
{7: 6 }OPQRSTUVWXYZ{1: } | {7: 6 }OPQRSTUVWXYZ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
@ -110,7 +110,7 @@ describe(':terminal window', function()
screen:expect([[ screen:expect([[
{7:++1 }tty ready | {7:++1 }tty ready |
{7:++2 }rows: 6, cols: 45 | {7:++2 }rows: 6, cols: 45 |
{7:++3 }{1: } | {7:++3 }^ |
{7:++4 } | {7:++4 } |
{7:++5 } | {7:++5 } |
{7:++6 } | {7:++6 } |
@ -123,7 +123,7 @@ describe(':terminal window', function()
{7:++6 } | {7:++6 } |
{7:++7 } | {7:++7 } |
{7:++8 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS| {7:++8 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS|
{7:++9 }TUVWXYZ{1: } | {7:++9 }TUVWXYZ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
feed_data('\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') feed_data('\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
@ -133,7 +133,7 @@ describe(':terminal window', function()
{7:++ 9 }STUVWXYZ | {7:++ 9 }STUVWXYZ |
{7:++10 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR| {7:++10 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR|
{7:++11 }STUVWXYZrows: 6, cols: 44 | {7:++11 }STUVWXYZrows: 6, cols: 44 |
{7:++12 }{1: } | {7:++12 }^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
@ -144,7 +144,7 @@ describe(':terminal window', function()
feed([[<C-\><C-N>]]) feed([[<C-\><C-N>]])
screen:expect([[ screen:expect([[
tty ready | tty ready |
{2:^ } | ^ |
|*5 |*5
]]) ]])
feed(':set colorcolumn=20<CR>i') feed(':set colorcolumn=20<CR>i')
@ -153,7 +153,7 @@ describe(':terminal window', function()
it('wont show the color column', function() it('wont show the color column', function()
screen:expect([[ screen:expect([[
tty ready | tty ready |
{1: } | ^ |
|*4 |*4
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -170,7 +170,7 @@ describe(':terminal window', function()
line2 | line2 |
line3 | line3 |
line4 | line4 |
{1: } | ^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
@ -184,7 +184,7 @@ describe(':terminal window', function()
line2 | line2 |
line3 | line3 |
line4 | line4 |
{2: } | |
| |
]]) ]])
end) end)
@ -206,7 +206,7 @@ describe(':terminal with multigrid', function()
[3:--------------------------------------------------]| [3:--------------------------------------------------]|
## grid 2 ## grid 2
tty ready | tty ready |
{1: } | ^ |
|*4 |*4
## grid 3 ## grid 3
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
@ -223,7 +223,7 @@ describe(':terminal with multigrid', function()
## grid 2 ## grid 2
tty ready | tty ready |
rows: 10, cols: 20 | rows: 10, cols: 20 |
{1: } | ^ |
|*7 |*7
## grid 3 ## grid 3
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
@ -241,7 +241,7 @@ describe(':terminal with multigrid', function()
## grid 2 ## grid 2
rows: 10, cols: 20 | rows: 10, cols: 20 |
rows: 3, cols: 70 | rows: 3, cols: 70 |
{1: } | ^ |
## grid 3 ## grid 3
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
@ -260,7 +260,7 @@ describe(':terminal with multigrid', function()
rows: 10, cols: 20 | rows: 10, cols: 20 |
rows: 3, cols: 70 | rows: 3, cols: 70 |
rows: 6, cols: 50 | rows: 6, cols: 50 |
{1: } | ^ |
| |
## grid 3 ## grid 3
{3:-- TERMINAL --} | {3:-- TERMINAL --} |

View File

@ -49,7 +49,7 @@ describe(':terminal', function()
========== | ========== |
tty ready | tty ready |
rows: 5, cols: 50 | rows: 5, cols: 50 |
{2: } | |
|*2 |*2
========== | ========== |
:2split | :2split |
@ -61,7 +61,7 @@ describe(':terminal', function()
========== | ========== |
^tty ready | ^tty ready |
rows: 5, cols: 50 | rows: 5, cols: 50 |
{2: } | |
|*2 |*2
========== | ========== |
:wincmd p | :wincmd p |
@ -77,7 +77,7 @@ describe(':terminal', function()
command('bprevious') command('bprevious')
screen:expect([[ screen:expect([[
tty ready | tty ready |
^foo{2: } | ^foo |
|*8 |*8
]]) ]])
end) end)
@ -102,7 +102,7 @@ describe(':terminal', function()
screen:expect([[ screen:expect([[
tty ready | tty ready |
rows: 7, cols: 47 | rows: 7, cols: 47 |
{2: } | |
|*3 |*3
^ | ^ |
| |
@ -112,7 +112,7 @@ describe(':terminal', function()
tty ready | tty ready |
rows: 7, cols: 47 | rows: 7, cols: 47 |
rows: 4, cols: 41 | rows: 4, cols: 41 |
{2:^ } | ^ |
| |
]]) ]])
end) end)

View File

@ -29,6 +29,10 @@ function M.feed_termcode(data)
M.feed_data('\027' .. data) M.feed_data('\027' .. data)
end end
function M.feed_csi(data)
M.feed_termcode('[' .. data)
end
function M.make_lua_executor(session) function M.make_lua_executor(session)
return function(code, ...) return function(code, ...)
local status, rv = session:request('nvim_exec_lua', code, { ... }) local status, rv = session:request('nvim_exec_lua', code, { ... })
@ -78,6 +82,9 @@ end
function M.set_undercurl() function M.set_undercurl()
M.feed_termcode('[4:3m') M.feed_termcode('[4:3m')
end end
function M.set_reverse()
M.feed_termcode('[7m')
end
function M.set_strikethrough() function M.set_strikethrough()
M.feed_termcode('[9m') M.feed_termcode('[9m')
end end
@ -108,7 +115,6 @@ function M.setup_screen(extra_rows, cmd, cols, env, screen_opts)
cols = cols and cols or 50 cols = cols and cols or 50
api.nvim_command('highlight TermCursor cterm=reverse') api.nvim_command('highlight TermCursor cterm=reverse')
api.nvim_command('highlight TermCursorNC ctermbg=11')
api.nvim_command('highlight StatusLineTerm ctermbg=2 ctermfg=0') api.nvim_command('highlight StatusLineTerm ctermbg=2 ctermfg=0')
api.nvim_command('highlight StatusLineTermNC ctermbg=2 ctermfg=8') api.nvim_command('highlight StatusLineTermNC ctermbg=2 ctermfg=8')
@ -154,7 +160,7 @@ function M.setup_screen(extra_rows, cmd, cols, env, screen_opts)
local empty_line = (' '):rep(cols) local empty_line = (' '):rep(cols)
local expected = { local expected = {
'tty ready' .. (' '):rep(cols - 9), 'tty ready' .. (' '):rep(cols - 9),
'{1: }' .. (' '):rep(cols - 1), '^' .. (' '):rep(cols),
empty_line, empty_line,
empty_line, empty_line,
empty_line, empty_line,

View File

@ -190,6 +190,19 @@ describe('ui/cursor', function()
attr_lm = {}, attr_lm = {},
short_name = 'sm', short_name = 'sm',
}, },
[18] = {
blinkoff = 500,
blinkon = 500,
blinkwait = 0,
cell_percentage = 0,
cursor_shape = 'block',
name = 'terminal',
hl_id = 3,
id_lm = 3,
attr = { reverse = true },
attr_lm = { reverse = true },
short_name = 't',
},
} }
screen:expect(function() screen:expect(function()
@ -245,17 +258,20 @@ describe('ui/cursor', function()
end end
end end
if m.hl_id then if m.hl_id then
m.hl_id = 66 m.hl_id = 65
m.attr = { background = Screen.colors.DarkGray } m.attr = { background = Screen.colors.DarkGray }
end end
if m.id_lm then if m.id_lm then
m.id_lm = 73 m.id_lm = 72
m.attr_lm = {}
end end
end end
-- Assert the new expectation. -- Assert the new expectation.
screen:expect(function() screen:expect(function()
eq(expected_mode_info, screen._mode_info) for i, v in ipairs(expected_mode_info) do
eq(v, screen._mode_info[i])
end
eq(true, screen._cursor_style_enabled) eq(true, screen._cursor_style_enabled)
eq('normal', screen.mode) eq('normal', screen.mode)
end) end)

View File

@ -227,7 +227,7 @@ describe('ext_hlstate detailed highlights', function()
command(("enew | call termopen(['%s'])"):format(testprg('tty-test'))) command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
screen:expect([[ screen:expect([[
^tty ready | ^tty ready |
{1: } | |
|*5 |*5
{7: }| {7: }|
]]) ]])
@ -242,7 +242,7 @@ describe('ext_hlstate detailed highlights', function()
screen:expect([[ screen:expect([[
^tty ready | ^tty ready |
x {5:y z} | x {5:y z} |
{1: } | |
|*4 |*4
{7: }| {7: }|
]]) ]])
@ -250,7 +250,7 @@ describe('ext_hlstate detailed highlights', function()
screen:expect([[ screen:expect([[
^tty ready | ^tty ready |
x {2:y }{3:z} | x {2:y }{3:z} |
{1: } | |
|*4 |*4
{7: }| {7: }|
]]) ]])
@ -268,7 +268,7 @@ describe('ext_hlstate detailed highlights', function()
else else
screen:expect([[ screen:expect([[
^tty ready | ^tty ready |
x {4:y}{2: }{3:z} | x {2:y }{3:z} |
|*5 |*5
{7: }| {7: }|
]]) ]])

View File

@ -49,7 +49,7 @@ describe('ui/ext_messages', function()
]], ]],
messages = { messages = {
{ {
content = { { '\ntest\n[O]k: ', 6, 11 } }, content = { { '\ntest\n[O]k: ', 6, 10 } },
kind = 'confirm', kind = 'confirm',
}, },
}, },
@ -77,7 +77,7 @@ describe('ui/ext_messages', function()
]], ]],
messages = { messages = {
{ {
content = { { '\ntest\n[O]k: ', 6, 11 } }, content = { { '\ntest\n[O]k: ', 6, 10 } },
kind = 'confirm', kind = 'confirm',
}, },
}, },
@ -91,7 +91,7 @@ describe('ui/ext_messages', function()
]], ]],
messages = { messages = {
{ {
content = { { '\ntest\n[O]k: ', 6, 11 } }, content = { { '\ntest\n[O]k: ', 6, 10 } },
kind = 'confirm', kind = 'confirm',
}, },
{ {
@ -99,7 +99,7 @@ describe('ui/ext_messages', function()
kind = 'echo', kind = 'echo',
}, },
{ {
content = { { 'Press ENTER or type command to continue', 6, 19 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@ -116,7 +116,7 @@ describe('ui/ext_messages', function()
]], ]],
messages = { messages = {
{ {
content = { { 'replace with X (y/n/a/q/l/^E/^Y)?', 6, 19 } }, content = { { 'replace with X (y/n/a/q/l/^E/^Y)?', 6, 18 } },
kind = 'confirm_sub', kind = 'confirm_sub',
}, },
}, },
@ -135,7 +135,7 @@ describe('ui/ext_messages', function()
]], ]],
messages = { messages = {
{ {
content = { { 'W10: Warning: Changing a readonly file', 19, 27 } }, content = { { 'W10: Warning: Changing a readonly file', 19, 26 } },
kind = 'wmsg', kind = 'wmsg',
}, },
}, },
@ -151,7 +151,7 @@ describe('ui/ext_messages', function()
]], ]],
messages = { messages = {
{ {
content = { { 'search hit BOTTOM, continuing at TOP', 19, 27 } }, content = { { 'search hit BOTTOM, continuing at TOP', 19, 26 } },
kind = 'wmsg', kind = 'wmsg',
}, },
}, },
@ -167,15 +167,15 @@ describe('ui/ext_messages', function()
]], ]],
messages = { messages = {
{ {
content = { { 'Error detected while processing :', 9, 7 } }, content = { { 'Error detected while processing :', 9, 6 } },
kind = 'emsg', kind = 'emsg',
}, },
{ {
content = { { 'E605: Exception not caught: foo', 9, 7 } }, content = { { 'E605: Exception not caught: foo', 9, 6 } },
kind = 'emsg', kind = 'emsg',
}, },
{ {
content = { { 'Press ENTER or type command to continue', 6, 19 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@ -225,15 +225,15 @@ describe('ui/ext_messages', function()
{ {
content = { content = {
{ '\nErrorMsg ' }, { '\nErrorMsg ' },
{ 'xxx', 9, 7 }, { 'xxx', 9, 6 },
{ ' ' }, { ' ' },
{ 'ctermfg=', 18, 6 }, { 'ctermfg=', 18, 5 },
{ '15 ' }, { '15 ' },
{ 'ctermbg=', 18, 6 }, { 'ctermbg=', 18, 5 },
{ '1 ' }, { '1 ' },
{ 'guifg=', 18, 6 }, { 'guifg=', 18, 5 },
{ 'White ' }, { 'White ' },
{ 'guibg=', 18, 6 }, { 'guibg=', 18, 5 },
{ 'Red' }, { 'Red' },
}, },
kind = 'list_cmd', kind = 'list_cmd',
@ -280,7 +280,7 @@ describe('ui/ext_messages', function()
{1:~ }|*4 {1:~ }|*4
]], ]],
messages = { { messages = { {
content = { { 'raa', 9, 7 } }, content = { { 'raa', 9, 6 } },
kind = 'echoerr', kind = 'echoerr',
} }, } },
} }
@ -307,15 +307,15 @@ describe('ui/ext_messages', function()
]], ]],
messages = { messages = {
{ {
content = { { 'bork', 9, 7 } }, content = { { 'bork', 9, 6 } },
kind = 'echoerr', kind = 'echoerr',
}, },
{ {
content = { { 'fail', 9, 7 } }, content = { { 'fail', 9, 6 } },
kind = 'echoerr', kind = 'echoerr',
}, },
{ {
content = { { 'Press ENTER or type command to continue', 6, 19 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@ -329,19 +329,19 @@ describe('ui/ext_messages', function()
]], ]],
messages = { messages = {
{ {
content = { { 'bork', 9, 7 } }, content = { { 'bork', 9, 6 } },
kind = 'echoerr', kind = 'echoerr',
}, },
{ {
content = { { 'fail', 9, 7 } }, content = { { 'fail', 9, 6 } },
kind = 'echoerr', kind = 'echoerr',
}, },
{ {
content = { { 'extrafail', 9, 7 } }, content = { { 'extrafail', 9, 6 } },
kind = 'echoerr', kind = 'echoerr',
}, },
{ {
content = { { 'Press ENTER or type command to continue', 6, 19 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@ -363,7 +363,7 @@ describe('ui/ext_messages', function()
{1:~ }|*4 {1:~ }|*4
]], ]],
messages = { { messages = { {
content = { { 'problem', 9, 7 } }, content = { { 'problem', 9, 6 } },
kind = 'echoerr', kind = 'echoerr',
} }, } },
cmdline = { cmdline = {
@ -391,15 +391,15 @@ describe('ui/ext_messages', function()
{1:~ }|*4 {1:~ }|*4
]], ]],
msg_history = { msg_history = {
{ kind = 'echoerr', content = { { 'raa', 9, 7 } } }, { kind = 'echoerr', content = { { 'raa', 9, 6 } } },
{ kind = 'echoerr', content = { { 'bork', 9, 7 } } }, { kind = 'echoerr', content = { { 'bork', 9, 6 } } },
{ kind = 'echoerr', content = { { 'fail', 9, 7 } } }, { kind = 'echoerr', content = { { 'fail', 9, 6 } } },
{ kind = 'echoerr', content = { { 'extrafail', 9, 7 } } }, { kind = 'echoerr', content = { { 'extrafail', 9, 6 } } },
{ kind = 'echoerr', content = { { 'problem', 9, 7 } } }, { kind = 'echoerr', content = { { 'problem', 9, 6 } } },
}, },
messages = { messages = {
{ {
content = { { 'Press ENTER or type command to continue', 6, 19 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@ -424,7 +424,7 @@ describe('ui/ext_messages', function()
]], ]],
messages = { messages = {
{ {
content = { { 'bork\nfail', 9, 7 } }, content = { { 'bork\nfail', 9, 6 } },
kind = 'echoerr', kind = 'echoerr',
}, },
}, },
@ -438,13 +438,13 @@ describe('ui/ext_messages', function()
]], ]],
messages = { messages = {
{ {
content = { { 'Press ENTER or type command to continue', 6, 19 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
msg_history = { msg_history = {
{ {
content = { { 'bork\nfail', 9, 7 } }, content = { { 'bork\nfail', 9, 6 } },
kind = 'echoerr', kind = 'echoerr',
}, },
}, },
@ -492,7 +492,7 @@ describe('ui/ext_messages', function()
{ content = { { 'x #1' } }, kind = 'list_cmd' }, { content = { { 'x #1' } }, kind = 'list_cmd' },
{ content = { { 'y #2' } }, kind = 'list_cmd' }, { content = { { 'y #2' } }, kind = 'list_cmd' },
{ {
content = { { 'Press ENTER or type command to continue', 6, 19 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@ -507,7 +507,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
showmode = { { '-- INSERT --', 5, 12 } }, showmode = { { '-- INSERT --', 5, 11 } },
} }
feed('alphpabet<cr>alphanum<cr>') feed('alphpabet<cr>alphanum<cr>')
@ -518,7 +518,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*2 {1:~ }|*2
]], ]],
showmode = { { '-- INSERT --', 5, 12 } }, showmode = { { '-- INSERT --', 5, 11 } },
} }
feed('<c-x>') feed('<c-x>')
@ -529,7 +529,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*2 {1:~ }|*2
]], ]],
showmode = { { '-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)', 5, 12 } }, showmode = { { '-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)', 5, 11 } },
} }
feed('<c-p>') feed('<c-p>')
@ -545,7 +545,7 @@ describe('ui/ext_messages', function()
items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } }, items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } },
pos = 1, pos = 1,
}, },
showmode = { { '-- Keyword Local completion (^N^P) ', 5, 12 }, { 'match 1 of 2', 6, 19 } }, showmode = { { '-- Keyword Local completion (^N^P) ', 5, 11 }, { 'match 1 of 2', 6, 18 } },
} }
-- echomsg and showmode don't overwrite each other, this is the same -- echomsg and showmode don't overwrite each other, this is the same
@ -567,7 +567,7 @@ describe('ui/ext_messages', function()
content = { { 'stuff' } }, content = { { 'stuff' } },
kind = 'echomsg', kind = 'echomsg',
} }, } },
showmode = { { '-- Keyword Local completion (^N^P) ', 5, 12 }, { 'match 1 of 2', 6, 19 } }, showmode = { { '-- Keyword Local completion (^N^P) ', 5, 11 }, { 'match 1 of 2', 6, 18 } },
} }
feed('<c-p>') feed('<c-p>')
@ -587,7 +587,7 @@ describe('ui/ext_messages', function()
content = { { 'stuff' } }, content = { { 'stuff' } },
kind = 'echomsg', kind = 'echomsg',
} }, } },
showmode = { { '-- Keyword Local completion (^N^P) ', 5, 12 }, { 'match 2 of 2', 6, 19 } }, showmode = { { '-- Keyword Local completion (^N^P) ', 5, 11 }, { 'match 2 of 2', 6, 18 } },
} }
feed('<esc>:messages<cr>') feed('<esc>:messages<cr>')
@ -604,7 +604,7 @@ describe('ui/ext_messages', function()
} }, } },
messages = { messages = {
{ {
content = { { 'Press ENTER or type command to continue', 6, 19 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@ -618,7 +618,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
showmode = { { 'recording @q', 5, 12 } }, showmode = { { 'recording @q', 5, 11 } },
} }
feed('i') feed('i')
@ -627,7 +627,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
showmode = { { '-- INSERT --recording @q', 5, 12 } }, showmode = { { '-- INSERT --recording @q', 5, 11 } },
} }
feed('<esc>') feed('<esc>')
@ -636,7 +636,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
showmode = { { 'recording @q', 5, 12 } }, showmode = { { 'recording @q', 5, 11 } },
} }
feed('q') feed('q')
@ -655,7 +655,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
showmode = { { 'recording @q', 5, 12 } }, showmode = { { 'recording @q', 5, 11 } },
mode = 'normal', mode = 'normal',
} }
@ -665,7 +665,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
showmode = { { 'recording @q', 5, 12 } }, showmode = { { 'recording @q', 5, 11 } },
mode = 'insert', mode = 'insert',
} }
@ -675,7 +675,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
showmode = { { 'recording @q', 5, 12 } }, showmode = { { 'recording @q', 5, 11 } },
mode = 'normal', mode = 'normal',
} }
@ -697,7 +697,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
ruler = { { '0,0-1 All', 9, 62 } }, ruler = { { '0,0-1 All', 9, 61 } },
}) })
command('hi clear MsgArea') command('hi clear MsgArea')
feed('i') feed('i')
@ -706,7 +706,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
showmode = { { '-- INSERT --', 5, 12 } }, showmode = { { '-- INSERT --', 5, 11 } },
ruler = { { '0,1 All' } }, ruler = { { '0,1 All' } },
} }
feed('abcde<cr>12345<esc>') feed('abcde<cr>12345<esc>')
@ -744,7 +744,7 @@ describe('ui/ext_messages', function()
{17:123}45 | {17:123}45 |
{1:~ }|*3 {1:~ }|*3
]], ]],
showmode = { { '-- VISUAL BLOCK --', 5, 12 } }, showmode = { { '-- VISUAL BLOCK --', 5, 11 } },
showcmd = { { '2x3' } }, showcmd = { { '2x3' } },
ruler = { { '1,3 All' } }, ruler = { { '1,3 All' } },
}) })
@ -825,7 +825,7 @@ describe('ui/ext_messages', function()
{1:~ }|*4 {1:~ }|*4
]], ]],
messages = { { messages = { {
content = { { 'bork', 9, 7 } }, content = { { 'bork', 9, 6 } },
kind = 'echoerr', kind = 'echoerr',
} }, } },
} }
@ -850,7 +850,7 @@ describe('ui/ext_messages', function()
]], ]],
messages = { messages = {
{ {
content = { { 'E117: Unknown function: nosuchfunction', 9, 7 } }, content = { { 'E117: Unknown function: nosuchfunction', 9, 6 } },
kind = 'emsg', kind = 'emsg',
}, },
}, },
@ -865,12 +865,12 @@ describe('ui/ext_messages', function()
msg_history = { msg_history = {
{ kind = 'echomsg', content = { { 'howdy' } } }, { kind = 'echomsg', content = { { 'howdy' } } },
{ kind = '', content = { { 'Type :qa and press <Enter> to exit Nvim' } } }, { kind = '', content = { { 'Type :qa and press <Enter> to exit Nvim' } } },
{ kind = 'echoerr', content = { { 'bork', 9, 7 } } }, { kind = 'echoerr', content = { { 'bork', 9, 6 } } },
{ kind = 'emsg', content = { { 'E117: Unknown function: nosuchfunction', 9, 7 } } }, { kind = 'emsg', content = { { 'E117: Unknown function: nosuchfunction', 9, 6 } } },
}, },
messages = { messages = {
{ {
content = { { 'Press ENTER or type command to continue', 6, 19 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@ -943,7 +943,7 @@ stack traceback:
[C]: in function 'error' [C]: in function 'error'
[string ":lua"]:1: in main chunk]], [string ":lua"]:1: in main chunk]],
9, 9,
7, 6,
}, },
}, },
kind = 'lua_error', kind = 'lua_error',
@ -963,7 +963,7 @@ stack traceback:
messages = { messages = {
{ {
content = { content = {
{ "Error invoking 'test_method' on channel 1:\ncomplete\nerror\n\nmessage", 9, 7 }, { "Error invoking 'test_method' on channel 1:\ncomplete\nerror\n\nmessage", 9, 6 },
}, },
kind = 'rpc_error', kind = 'rpc_error',
}, },
@ -1092,7 +1092,7 @@ stack traceback:
]], ]],
messages = { messages = {
{ {
content = { { 'wow, ', 10, 9 }, { 'such\n\nvery ', 9, 7 }, { 'color', 8, 13 } }, content = { { 'wow, ', 10, 8 }, { 'such\n\nvery ', 9, 6 }, { 'color', 8, 12 } },
kind = 'echomsg', kind = 'echomsg',
}, },
}, },
@ -1117,13 +1117,13 @@ stack traceback:
]], ]],
messages = { messages = {
{ {
content = { { 'Press ENTER or type command to continue', 6, 19 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
msg_history = { msg_history = {
{ {
content = { { 'wow, ', 10, 9 }, { 'such\n\nvery ', 9, 7 }, { 'color', 8, 13 } }, content = { { 'wow, ', 10, 8 }, { 'such\n\nvery ', 9, 6 }, { 'color', 8, 12 } },
kind = 'echomsg', kind = 'echomsg',
}, },
}, },
@ -1783,7 +1783,7 @@ describe('ui/ext_messages', function()
{1:~ }type :help iccf{18:<Enter>} for information {1: }| {1:~ }type :help iccf{18:<Enter>} for information {1: }|
{1:~ }|*5 {1:~ }|*5
]] ]]
local showmode = { { '-- INSERT --', 5, 12 } } local showmode = { { '-- INSERT --', 5, 11 } }
screen:expect(introscreen) screen:expect(introscreen)
-- <c-l> (same as :mode) does _not_ clear intro message -- <c-l> (same as :mode) does _not_ clear intro message
@ -1858,7 +1858,7 @@ describe('ui/ext_messages', function()
]], ]],
messages = { messages = {
{ {
content = { { 'Press ENTER or type command to continue', 6, 19 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },

View File

@ -94,6 +94,46 @@ describe('ui mode_change event', function()
} }
end) end)
-- oldtest: Test_mouse_shape_indent_norm_with_gq()
it('is restored to Normal mode after "gq" indents using :normal #12309', function()
screen:try_resize(60, 6)
n.exec([[
func Indent()
exe "normal! \<Ignore>"
return 0
endfunc
setlocal indentexpr=Indent()
call setline(1, [repeat('a', 80), repeat('b', 80)])
]])
feed('ggVG')
screen:expect {
grid = [[
{17:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
{17:aaaaaaaaaaaaaaaaaaaa} |
^b{17:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb}|
{17:bbbbbbbbbbbbbbbbbbbb} |
{1:~ }|
{5:-- VISUAL LINE --} |
]],
mode = 'visual',
}
feed('gq')
screen:expect {
grid = [[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaa |
^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
bbbbbbbbbbbbbbbbbbbb |
{1:~ }|
|
]],
mode = 'normal',
}
end)
it('works in insert mode', function() it('works in insert mode', function()
feed('i') feed('i')
screen:expect { screen:expect {

View File

@ -34,7 +34,7 @@ describe('shell command :!', function()
n.nvim_set .. ' notermguicolors', n.nvim_set .. ' notermguicolors',
}) })
screen:expect([[ screen:expect([[
{1: } | ^ |
{4:~ }|*4 {4:~ }|*4
| |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
@ -78,7 +78,7 @@ describe('shell command :!', function()
29999: foo | 29999: foo |
30000: foo | 30000: foo |
| |
{10:Press ENTER or type command to continue}{1: } | {10:Press ENTER or type command to continue}^ |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]], ]],
{ {

View File

@ -1162,6 +1162,8 @@ describe('builtin popupmenu', function()
[6] = { foreground = Screen.colors.White, background = Screen.colors.Red }, [6] = { foreground = Screen.colors.White, background = Screen.colors.Red },
[7] = { background = Screen.colors.Yellow }, -- Search [7] = { background = Screen.colors.Yellow }, -- Search
[8] = { foreground = Screen.colors.Red }, [8] = { foreground = Screen.colors.Red },
[9] = { foreground = Screen.colors.Yellow, background = Screen.colors.Green },
[10] = { foreground = Screen.colors.White, background = Screen.colors.Green },
ks = { foreground = Screen.colors.Red, background = Screen.colors.Grey }, ks = { foreground = Screen.colors.Red, background = Screen.colors.Grey },
kn = { foreground = Screen.colors.Red, background = Screen.colors.Plum1 }, kn = { foreground = Screen.colors.Red, background = Screen.colors.Plum1 },
xs = { foreground = Screen.colors.Black, background = Screen.colors.Grey }, xs = { foreground = Screen.colors.Black, background = Screen.colors.Grey },
@ -5561,6 +5563,179 @@ describe('builtin popupmenu', function()
]]) ]])
feed('<C-E><ESC>') feed('<C-E><ESC>')
end) end)
-- oldtest: Test_pum_matchins_highlight()
it('with ComplMatchIns highlight', function()
exec([[
func Omni_test(findstart, base)
if a:findstart
return col(".")
endif
return [#{word: "foo"}, #{word: "bar"}, #{word: "你好"}]
endfunc
set omnifunc=Omni_test
hi ComplMatchIns guifg=red
]])
feed('Sαβγ <C-X><C-O>')
screen:expect([[
αβγ {8:foo}^ |
{1:~ }{s: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{5:match 1 of 3} |
]])
feed('<C-E><Esc>')
feed('Sαβγ <C-X><C-O><C-N>')
screen:expect([[
αβγ {8:bar}^ |
{1:~ }{n: foo }{1: }|
{1:~ }{s: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{5:match 2 of 3} |
]])
feed('<C-E><Esc>')
feed('Sαβγ <C-X><C-O><C-N><C-N>')
screen:expect([[
αβγ {8:}^ |
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{s: }{1: }|
{1:~ }|*15
{2:-- }{5:match 3 of 3} |
]])
feed('<C-E><Esc>')
-- restore after accept
feed('Sαβγ <C-X><C-O><C-Y>')
screen:expect([[
αβγ foo^ |
{1:~ }|*18
{2:-- INSERT --} |
]])
feed('<Esc>')
-- restore after cancel completion
feed('Sαβγ <C-X><C-O><Space>')
screen:expect([[
αβγ foo ^ |
{1:~ }|*18
{2:-- INSERT --} |
]])
feed('<Esc>')
-- text after the inserted text shouldn't be highlighted
feed('0ea <C-X><C-O>')
screen:expect([[
αβγ {8:foo}^ foo |
{1:~ }{s: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{5:match 1 of 3} |
]])
feed('<C-P>')
screen:expect([[
αβγ ^ foo |
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{8:Back at original} |
]])
feed('<C-P>')
screen:expect([[
αβγ {8:}^ foo |
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{s: }{1: }|
{1:~ }|*15
{2:-- }{5:match 3 of 3} |
]])
feed('<C-Y>')
screen:expect([[
αβγ ^ foo |
{1:~ }|*18
{2:-- INSERT --} |
]])
feed('<Esc>')
end)
-- oldtest: Test_pum_matchins_highlight_combine()
it('with ComplMatchIns, Normal and CursorLine highlights', function()
exec([[
func Omni_test(findstart, base)
if a:findstart
return col(".")
endif
return [#{word: "foo"}, #{word: "bar"}, #{word: "你好"}]
endfunc
set omnifunc=Omni_test
hi Normal guibg=blue
hi CursorLine guibg=green guifg=white
set cursorline
call setline(1, 'aaa bbb')
]])
-- when ComplMatchIns is not set, CursorLine applies normally
feed('0ea <C-X><C-O>')
screen:expect([[
{10:aaa foo^ bbb }|
{1:~ }{s: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{5:match 1 of 3} |
]])
feed('<C-E>')
screen:expect([[
{10:aaa ^ bbb }|
{1:~ }|*18
{2:-- INSERT --} |
]])
feed('<BS><Esc>')
-- when ComplMatchIns is set, it is applied over CursorLine
command('hi ComplMatchIns guifg=Yellow')
feed('0ea <C-X><C-O>')
screen:expect([[
{10:aaa }{9:foo}{10:^ bbb }|
{1:~ }{s: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{5:match 1 of 3} |
]])
feed('<C-P>')
screen:expect([[
{10:aaa ^ bbb }|
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{8:Back at original} |
]])
feed('<C-P>')
screen:expect([[
{10:aaa }{9:}{10:^ bbb }|
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{s: }{1: }|
{1:~ }|*15
{2:-- }{5:match 3 of 3} |
]])
feed('<C-E>')
screen:expect([[
{10:aaa ^ bbb }|
{1:~ }|*18
{2:-- INSERT --} |
]])
feed('<Esc>')
end)
end end
end end

View File

@ -967,11 +967,11 @@ function Screen:_handle_mode_info_set(cursor_style_enabled, mode_info)
self._cursor_style_enabled = cursor_style_enabled self._cursor_style_enabled = cursor_style_enabled
for _, item in pairs(mode_info) do for _, item in pairs(mode_info) do
-- attr IDs are not stable, but their value should be -- attr IDs are not stable, but their value should be
if item.attr_id ~= nil then if item.attr_id ~= nil and self._attr_table[item.attr_id] ~= nil then
item.attr = self._attr_table[item.attr_id][1] item.attr = self._attr_table[item.attr_id][1]
item.attr_id = nil item.attr_id = nil
end end
if item.attr_id_lm ~= nil then if item.attr_id_lm ~= nil and self._attr_table[item.attr_id_lm] ~= nil then
item.attr_lm = self._attr_table[item.attr_id_lm][1] item.attr_lm = self._attr_table[item.attr_id_lm][1]
item.attr_id_lm = nil item.attr_id_lm = nil
end end

View File

@ -1,5 +1,8 @@
" Test for various indent options " Test for various indent options
source shared.vim
source check.vim
func Test_preserveindent() func Test_preserveindent()
new new
" Test for autoindent copying indent from the previous line " Test for autoindent copying indent from the previous line
@ -303,4 +306,50 @@ func Test_indent_overflow_count2()
close! close!
endfunc endfunc
" Test that mouse shape is restored to Normal mode after using "gq" when
" 'indentexpr' executes :normal.
func Test_mouse_shape_indent_norm_with_gq()
CheckFeature mouseshape
CheckCanRunGui
let lines =<< trim END
func Indent()
exe "normal! \<Ignore>"
return 0
endfunc
setlocal indentexpr=Indent()
END
call writefile(lines, 'Xindentexpr.vim', 'D')
let lines =<< trim END
vim9script
var mouse_shapes = []
setline(1, [repeat('a', 80), repeat('b', 80)])
feedkeys('ggVG')
timer_start(50, (_) => {
mouse_shapes += [getmouseshape()]
timer_start(50, (_) => {
feedkeys('gq')
timer_start(50, (_) => {
mouse_shapes += [getmouseshape()]
timer_start(50, (_) => {
writefile(mouse_shapes, 'Xmouseshapes')
quit!
})
})
})
})
END
call writefile(lines, 'Xmouseshape.vim', 'D')
call RunVim([], [], "-g -S Xindentexpr.vim -S Xmouseshape.vim")
call WaitForAssert({-> assert_equal(['rightup-arrow', 'arrow'],
\ readfile('Xmouseshapes'))}, 300)
call delete('Xmouseshapes')
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@ -1713,4 +1713,103 @@ func Test_pum_keep_select()
call StopVimInTerminal(buf) call StopVimInTerminal(buf)
endfunc endfunc
func Test_pum_matchins_highlight()
CheckScreendump
let lines =<< trim END
func Omni_test(findstart, base)
if a:findstart
return col(".")
endif
return [#{word: "foo"}, #{word: "bar"}, #{word: "你好"}]
endfunc
set omnifunc=Omni_test
hi ComplMatchIns ctermfg=red
END
call writefile(lines, 'Xscript', 'D')
let buf = RunVimInTerminal('-S Xscript', {})
call TermWait(buf)
call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>")
call VerifyScreenDump(buf, 'Test_pum_matchins_01', {})
call term_sendkeys(buf, "\<C-E>\<Esc>")
call TermWait(buf)
call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>\<C-N>")
call VerifyScreenDump(buf, 'Test_pum_matchins_02', {})
call term_sendkeys(buf, "\<C-E>\<Esc>")
call TermWait(buf)
call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>\<C-N>\<C-N>")
call VerifyScreenDump(buf, 'Test_pum_matchins_03', {})
call term_sendkeys(buf, "\<C-E>\<Esc>")
" restore after accept
call TermWait(buf)
call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>\<C-Y>")
call VerifyScreenDump(buf, 'Test_pum_matchins_04', {})
call term_sendkeys(buf, "\<Esc>")
" restore after cancel completion
call TermWait(buf)
call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>\<Space>")
call VerifyScreenDump(buf, 'Test_pum_matchins_05', {})
call term_sendkeys(buf, "\<Esc>")
" text after the inserted text shouldn't be highlighted
call TermWait(buf)
call term_sendkeys(buf, "0ea \<C-X>\<C-O>")
call VerifyScreenDump(buf, 'Test_pum_matchins_07', {})
call term_sendkeys(buf, "\<C-P>")
call VerifyScreenDump(buf, 'Test_pum_matchins_08', {})
call term_sendkeys(buf, "\<C-P>")
call VerifyScreenDump(buf, 'Test_pum_matchins_09', {})
call term_sendkeys(buf, "\<C-Y>")
call VerifyScreenDump(buf, 'Test_pum_matchins_10', {})
call term_sendkeys(buf, "\<Esc>")
call StopVimInTerminal(buf)
endfunc
func Test_pum_matchins_highlight_combine()
CheckScreendump
let lines =<< trim END
func Omni_test(findstart, base)
if a:findstart
return col(".")
endif
return [#{word: "foo"}, #{word: "bar"}, #{word: "你好"}]
endfunc
set omnifunc=Omni_test
hi Normal ctermbg=blue
hi CursorLine cterm=underline ctermbg=green
set cursorline
call setline(1, 'aaa bbb')
END
call writefile(lines, 'Xscript', 'D')
let buf = RunVimInTerminal('-S Xscript', {})
" when ComplMatchIns is not set, CursorLine applies normally
call term_sendkeys(buf, "0ea \<C-X>\<C-O>")
call VerifyScreenDump(buf, 'Test_pum_matchins_combine_01', {})
call term_sendkeys(buf, "\<C-E>")
call VerifyScreenDump(buf, 'Test_pum_matchins_combine_02', {})
call term_sendkeys(buf, "\<BS>\<Esc>")
" when ComplMatchIns is set, it is applied over CursorLine
call TermWait(buf)
call term_sendkeys(buf, ":hi ComplMatchIns ctermbg=red ctermfg=yellow\<CR>")
call TermWait(buf)
call term_sendkeys(buf, "0ea \<C-X>\<C-O>")
call VerifyScreenDump(buf, 'Test_pum_matchins_combine_03', {})
call term_sendkeys(buf, "\<C-P>")
call VerifyScreenDump(buf, 'Test_pum_matchins_combine_04', {})
call term_sendkeys(buf, "\<C-P>")
call VerifyScreenDump(buf, 'Test_pum_matchins_combine_05', {})
call term_sendkeys(buf, "\<C-E>")
call VerifyScreenDump(buf, 'Test_pum_matchins_combine_06', {})
call term_sendkeys(buf, "\<Esc>")
call StopVimInTerminal(buf)
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@ -59,7 +59,8 @@ func Test_window_preview_terminal()
CheckFeature quickfix CheckFeature quickfix
" CheckFeature terminal " CheckFeature terminal
term " ++curwin " term ++curwin
term
const buf_num = bufnr('$') const buf_num = bufnr('$')
call assert_equal(1, winnr('$')) call assert_equal(1, winnr('$'))
exe 'pbuffer' . buf_num exe 'pbuffer' . buf_num