Compare commits

...

21 Commits

Author SHA1 Message Date
dependabot[bot]
2290350177 ci: bump actions/github-script from 7 to 8
Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 8.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v7...v8)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-05 12:05:48 +00:00
zeertzjq
0bafbe872b vim-patch:9.1.1732: filetype: .inc file detection can be improved (#35635)
Problem:  filetype: .inc file detection can be improved
Solution: Update filetype detection for Pascal and BitBake code
          (Martin Schwan).

Fix the detection of .inc files containing Pascal and BitBake code:

- the concatenated string, merged from three lines, only contains one
  beginning and the pattern "^" would not match as expected. Use a range()
  loop to iterate each line string individually. This way, the pattern "^"
  works for beginning of lines.

- improve BitBake include file detection by also matching forward-slashes
  "/" in variable names and assignment operators with a dot ".=" and "=.".
  Valid examples, which should match, are:

    PREFERRED_PROVIDER_virtual/kernel = "linux-yocto"
    MACHINEOVERRIDES =. "qemuall:"
    BBPATH .= ":${LAYERDIR}"

- parse twenty instead of just three lines, to accommodate for potential
  comments at the beginning of files

closes: vim/vim#18202

9fd1a657d2

Co-authored-by: Martin Schwan <m.schwan@phytec.de>
2025-09-05 17:22:24 +08:00
Justin M. Keyes
9898327bd7 Merge #35621 from fredizzimo/refactor-mouse-spec
refactor(tests): don't compare the full screen in mouse_spec
2025-09-05 00:40:13 -04:00
zeertzjq
0bf4b7898c vim-patch:9.1.1731: Not using const qualifier for opchars (#35634)
Problem:  Not using const qualifier
Solution: Mark the opchars array const

closes: vim/vim#18196

63a02ca39a

Co-authored-by: Damien Lejay <damien@lejay.be>
2025-09-05 00:20:28 +00:00
Justin M. Keyes
7fcdb0541f Merge #35628 fix(progress): msg-id, memoryleak 2025-09-04 17:38:52 -04:00
Fred Sundvik
e6cdb76665 refactor(tests): don't compare the full screen in mouse_spec
Problem:
Adding multigrid tests to `mouse_spec` requires all tests to test both
the multigrid and non-multigrid screen state, which adds a lot of extra
code.

Solution:
Instead of testing the full screen state, only test substrings of it.
2025-09-05 00:12:55 +03:00
shadmansaleh
e5ba875a95 fix(progress): memory leak on progress-message with history=false 2025-09-04 21:53:49 +06:00
shadmansaleh
2415d8f424 fix(progress): message-id not sent to ui with history set to false 2025-09-04 20:37:05 +06:00
Justin M. Keyes
2b421d518f Merge #35462 from justinmk/doc2 2025-09-04 00:30:28 -04:00
Justin M. Keyes
2affb8373f docs: api events 2025-09-04 00:11:52 -04:00
Justin M. Keyes
9c3099f0cf docs: lsp, misc
- Problem: It's not clear for new plugin developers that `:help` uses
  a help-tags file for searching the docs, generated by `:helptags`.
  - Solution: Hint to the |:helptags| docs for regenerating the tags
    file for their freshly written documentation.

Co-authored-by: Yochem van Rosmalen <git@yochem.nl>
2025-09-03 23:03:51 -04:00
luukvbaal
de950f8272 fix(window): avoid referencing cmdline_win after it is closed #35617
Solution:  A window marked for ext_cmdline usage is still referenced
           after it is already closed and freed.
Solution:  Unset cmdline_win when the window is closed.
2025-09-03 16:28:23 -07:00
zeertzjq
17da1ad8f4 vim-patch:9.1.1730: filetype: vivado journal/log files are not recognized (#35613)
Problem:  filetype: vivado journal/log files are not recognized
Solution: Detect vivado*.{jou,log} as tcl filetype (Wu Zhenyu).

closes: vim/vim#18191

9a6cafdc1c

Also fix missing anchor in the pattern from the port of patch 9.1.1602.

Co-authored-by: Wu, Zhenyu <wuzhenyu@ustc.edu>
2025-09-04 07:16:47 +08:00
Fred Sundvik
f2536aa795 test: make it possible to test multiple screen string matches
Problem:
Currently it's only possible to test a single string match in the
screen, which makes it hard match multiple strings in the screen to
avoid having to compare the whole screen state.

It's also not possible to test if a string match is not found in the screen.

Solution:
Support an array of `any` matches and also support `none`, which does a
negative comparision.
2025-09-03 21:35:21 +03:00
Sean Dewar
bf5f7c1591 fix(window): don't add a hsep when out of room if global stl is off
Problem: a horizontal separator may be added to a window that doesn't need one
if there is no room when moving a different window.

Solution: only restore a hsep in winframe_restore when the global statusline is
enabled.
2025-09-03 18:34:37 +01:00
zeertzjq
1f7d6c3876 Merge pull request #35612 from zeertzjq/vim-e0704a3
vim-patch: runtime file updates
2025-09-03 22:40:10 +08:00
zeertzjq
967d226f96 vim-patch:f165798: runtime(m4): update syntax script
This change does the following to the M4 syntax script:

- In M4 there are no "strings" in the usual sense. Instead, M4 has
  quotes, but the text inside a quoted region is rescanned just like
  outside, and quotes can be nested.
- The old m4String region was misleading and removed. A new m4Quoted
  region reflects proper quoting semantics.
- Removed a duplicate highlight rule.
- Fixed a typo in a highlight group name (m4builtin → m4Builtin).
- Added a reference link to the POSIX M4 specification.
- Removed outdated maintainer URL.

closes: vim/vim#18192

f165798184

Co-authored-by: Damien Lejay <damien@lejay.be>
2025-09-03 21:28:11 +08:00
zeertzjq
c4c9daf7e2 vim-patch:e0704a3: runtime(keymap): Add transliteration (buckwalter) arabic keymap
References:
- https://en.wikipedia.org/wiki/Buckwalter_transliteration
- http://qamus.org/transliteration.htm

closes: vim/vim#18186

e0704a3593

Co-authored-by: Rafael Ketsetsides <rketsetsides@gmail.com>
2025-09-03 21:27:24 +08:00
Luna Razzaghipour
f9ce939bf5 perf: scheduler priority clamping on macOS #35488
Problem:
All of Nvim’s threads are clamped to the Default QoS class. This means
that Nvim is forced to compete for CPU time with compilers and other
batch work, and is even prioritized beneath user-initiated work in GUI
apps like e.g. file imports. This significantly harms responsiveness.

Solution:
Tell the kernel that the Nvim process takes part in rendering a UI.

Implementation:
Remove the process-wide QoS clamp. This doesn’t directly do anything to
the main thread, but rather has the side-effect of letting the main
thread run at its actual QoS (User Interactive QoS).
2025-09-02 18:34:46 -07:00
zeertzjq
1ae09bf545 vim-patch:4c39d0c: runtime(doc): quote partial urls with a backtick (#35606)
closes: vim/vim#18194

4c39d0cc9b

Co-authored-by: Yochem van Rosmalen <git@yochem.nl>
2025-09-03 09:07:01 +08:00
Evgeni Chasnovski
431004dda2 fix: screenchar()/screenstring() with hidden floating windows #35560 2025-09-02 11:21:19 -07:00
53 changed files with 1755 additions and 1308 deletions

View File

@@ -29,7 +29,7 @@ jobs:
- name: Create failed backport label
if: ${{ steps.backport.outputs.was_successful == 'false' }}
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
github.rest.issues.addLabels({

View File

@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: check issue title
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const title = context.payload.issue.title;

View File

@@ -40,7 +40,7 @@ jobs:
pull-requests: write
steps:
- if: startsWith(github.base_ref, 'release')
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
github.rest.issues.addLabels({

View File

@@ -14,7 +14,7 @@ jobs:
pull-requests: write
steps:
- uses: actions/checkout@v5
- uses: actions/github-script@v7
- uses: actions/github-script@v8
with:
script: |
const script = require('./.github/scripts/close_unresponsive.js')
@@ -28,7 +28,7 @@ jobs:
pull-requests: write
steps:
- uses: actions/checkout@v5
- uses: actions/github-script@v7
- uses: actions/github-script@v8
with:
script: |
const script = require('./.github/scripts/remove_response_label.js')

View File

@@ -12,7 +12,7 @@ jobs:
steps:
- uses: actions/checkout@v5
- name: 'Request reviewers'
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const script = require('./.github/scripts/reviewers_add.js')

View File

@@ -10,7 +10,7 @@ jobs:
steps:
- uses: actions/checkout@v5
- name: 'Remove reviewers'
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const script = require('./.github/scripts/reviewers_remove.js')

View File

@@ -826,7 +826,8 @@ message window. Cmdline state is emitted as |ui-cmdline| events, which the UI
must handle.
["msg_show", kind, content, replace_last, history, append, msg_id] ~
Display a message to the user.
Display a message to the user. Update (replace) any existing message
matching `msg_id`.
kind
Name indicating the message kind:

View File

@@ -254,19 +254,6 @@ The idea is "versionless evolution", in the words of Rich Hickey:
- Relaxing a requirement should be a compatible change.
- Strengthening a promise should be a compatible change.
==============================================================================
Global events *api-global-events*
When a client invokes an API request as an async notification, it is not
possible for Nvim to send an error response. Instead, in case of error, the
following notification will be sent to the client:
*nvim_error_event*
nvim_error_event[{type}, {message}]
{type} is a numeric id as defined by `api_info().error_types`, and {message} is
a string with the error message.
==============================================================================
Buffer update events *api-buffer-updates*
@@ -553,6 +540,38 @@ Extmark positions changed by an edit will be restored on undo/redo. Creating
and deleting extmarks is not a buffer change, thus new undo states are not
created for extmark changes.
==============================================================================
Global Events *api-events*
nvim_error_event({type}, {msg}) *nvim_error_event*
Emitted on the client channel if an async API request responds with an
error.
Attributes: ~
|RPC| only
Parameters: ~
• {type} (`integer`) Error type id as defined by
`api_info().error_types`.
• {msg} (`string`) Error message.
nvim_ui_term_event({event}, {value}) *nvim_ui_term_event*
Emitted by the TUI client to signal when a host-terminal event occurred.
Supports these events:
• "termresponse": The host-terminal sent a DA1, OSC, DCS, or APC response
sequence to Nvim. The payload is the received response. Sets
|v:termresponse| and fires |TermResponse|.
Attributes: ~
|RPC| only
Since: 0.10.0
Parameters: ~
• {event} (`string`) Event name
• {value} (`any`) Event payload
==============================================================================
Global Functions *api-global*
@@ -1385,9 +1404,9 @@ nvim_set_client_info({name}, {version}, {type}, {methods}, {attributes})
debugging and orchestration. (Note: Something is better than nothing!
Fields are optional, but at least set `name`.)
Can be called more than once; the caller should merge old info if
appropriate. Example: library first identifies the channel, then a plugin
using that library later identifies itself.
Can be called more than once; caller should merge old info if appropriate.
Example: a library first identifies the channel, then a plugin using that
library later identifies itself.
Attributes: ~
|RPC| only
@@ -3324,8 +3343,7 @@ nvim_set_decoration_provider({ns_id}, {opts})
• on_win: called when starting to redraw a specific window. >
["win", winid, bufnr, toprow, botrow]
<
• on_line: called for each buffer line being redrawn. (The
interaction with fold lines is subject to change) >
• on_line: (deprecated, use on_range instead) >
["line", winid, bufnr, row]
<
• on_range: called for each buffer range being redrawn. Range
@@ -3661,22 +3679,6 @@ nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()*
• {name} (`string`)
• {value} (`any`)
nvim_ui_term_event({event}, {value}) *nvim_ui_term_event()*
Tells Nvim when a host-terminal event occurred.
Supports these events:
• "termresponse": The host-terminal sent a DA1, OSC, DCS, or APC response
sequence to Nvim. The payload is the received response. Sets
|v:termresponse| and fires |TermResponse|.
Attributes: ~
|RPC| only
Since: 0.10.0
Parameters: ~
• {event} (`string`) Event name
• {value} (`any`) Event payload
nvim_ui_try_resize({width}, {height}) *nvim_ui_try_resize()*
Attributes: ~

View File

@@ -1153,23 +1153,23 @@ first word). You can use the |']| or |`]| command after the put command to
move the cursor to the end of the inserted text, or use |'[| or |`[| to move
the cursor to the start.
*put-Visual-mode* *v_p* *v_P*
*put-Visual-mode*
When using a put command like |p| or |P| in Visual mode, Vim will try to
replace the selected text with the contents of the register. Whether this
works well depends on the type of selection and the type of the text in the
register. With blockwise selection it also depends on the size of the block
and whether the corners are on an existing character. (Implementation detail:
it actually works by first putting the register after the selection and then
deleting the selection.)
With |p| the previously selected text is put in the unnamed register (and
possibly the selection and/or clipboard). This is useful if you want to put
that text somewhere else. But you cannot repeat the same change.
With |P| the unnamed register is not changed (and neither the selection or
clipboard), you can repeat the same change. But the deleted text cannot be
used. If you do need it you can use |p| with another register. E.g., yank
the text to copy, Visually select the text to replace and use "0p . You can
repeat this as many times as you like, and the unnamed register will be
changed each time.
replace the selected text with the contents of the register. How this
works depends on the type of selection and the text. With blockwise selection
it also depends on the size of the block and whether the corners are on an
existing character. (Implementation detail: it actually works by first
putting the register after the selection and then deleting the selection.)
*v_p*
|p| in Visual mode puts text and sets the default register (unnamed,
selection, or clipboard) to the previously-selected text. Useful if you want
to put that text somewhere else. But you cannot repeat the same change.
*v_P*
|P| in Visual mode puts text without setting the default register. You can
repeat the change, but the deleted text cannot be used. If you do need it you
can use |p| with another register. E.g., yank the text to copy, Visually
select the text to replace and use "0p . You can repeat this as many times as
you like, and the unnamed register will be changed each time.
*blockwise-put*
When a register contains text from one line (characterwise), using a
blockwise Visual selection, putting that register will paste that text

View File

@@ -451,6 +451,8 @@ Use existing common {verb} names (actions) if possible:
a handler. |dev-name-events|
- open: Opens something (a buffer, window, …)
- parse: Parses something into a structured form
- request: Calls a remote (network, RPC) operation.
- send: Writes data or a message to a channel.
- set: Sets a thing (or group of things)
- start: Spin up a long-lived process. Prefer "enable" except when
"start" is obviously more appropriate.
@@ -461,7 +463,7 @@ Do NOT use these deprecated verbs:
- contains: Prefer "has".
- disable: Prefer `enable(enable: boolean)`.
- exit: Prefer "cancel" (or "stop" if appropriate).
- is_disabled: Prefer `is_enabled()`.
- is_disabled: Prefer `!is_enabled()`.
- list: Redundant with "get"
- notify: Redundant with "print", "echo"
- show: Redundant with "print", "echo"

View File

@@ -104,14 +104,13 @@ CTRL-R {register} *i_CTRL-R*
Insert the contents of a register. Between typing CTRL-R and
the second character, '"' will be displayed to indicate that
you are expected to enter the name of a register. When used
with When used with named or clipboard registers
(A-Z,a-z,0-9,+) text is inserted literally like pasting with
"p". For other registers, the text is inserted as if you typed
it, but mappings and abbreviations are not used. If you have
options like 'textwidth', 'formatoptions', or 'autoindent'
set, this will influence what will be inserted. This is
different from what happens with the "p" command and pasting
with the mouse.
with named or clipboard registers (A-Z,a-z,0-9,+) text is
inserted literally like pasting with "p". For other registers,
the text is inserted as if you typed it, but mappings and
abbreviations are not used. If you have options like
'textwidth', 'formatoptions', or 'autoindent' set, this will
influence what will be inserted. This is different from what
happens with the "p" command and pasting with the mouse.
Special registers:
'"' the unnamed register, containing the text of
the last delete or yank

View File

@@ -2229,6 +2229,37 @@ is_enabled({filter}) *vim.lsp.inlay_hint.is_enabled()*
==============================================================================
Lua module: vim.lsp.inline_completion *lsp-inline_completion*
This module provides the LSP "inline completion" feature, for completing
multiline text (e.g., whole methods) instead of just a word or line, which may
result in "syntactically or semantically incorrect" code. Unlike regular
completion, this is typically presented as overlay text instead of a menu of
completion candidates.
LSP spec:
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#textDocument_inlineCompletion
To try it out, here is a quickstart example using Copilot: *lsp-copilot*
1. Install Copilot: >sh
npm install --global @github/copilot-language-server
<
2. Define a config, (or copy `lsp/copilot.lua` from
https://github.com/neovim/nvim-lspconfig): >lua
vim.lsp.config('copilot', {
cmd = { 'copilot-language-server', '--stdio', },
root_markers = { '.git' },
})
<
3. Activate the config: >lua
vim.lsp.enable('copilot')
<
4. Sign in to Copilot, or use the `:LspCopilotSignIn` command from
https://github.com/neovim/nvim-lspconfig
5. Enable inline completion: >lua
vim.lsp.inline_completion.enable()
<
6. Set a keymap for `vim.lsp.inline_completion.get()` and invoke the keymap.
*vim.lsp.inline_completion.Item*
Fields: ~

View File

@@ -10,9 +10,9 @@
==============================================================================
Introduction *lua-guide*
This guide introduces the basics of everyday usage of Lua to configure and
operate Nvim. It assumes some familiarity with the (non-Lua) basics of Nvim
(commands, options, mappings, autocommands), which are covered in the
This guide introduces the basics of everyday Lua usage for configuring and
controlling Nvim. It assumes some familiarity with the (non-Lua) basics of
Nvim (commands, options, mappings, autocommands), which are covered in the
|user-manual|.
This is not a comprehensive encyclopedia of all available features. Think of

View File

@@ -10,7 +10,7 @@
==============================================================================
Introduction *lua-plugin*
This document provides guidance for developing Nvim (Lua) plugins:
This document provides guidance for developing Nvim Lua plugins.
See |lua-guide| for guidance on using Lua to configure and operate Nvim.
See |luaref| and |lua-concepts| for details on the Lua programming language.
@@ -19,7 +19,7 @@ See |luaref| and |lua-concepts| for details on the Lua programming language.
Creating your first plugin *lua-plugin-new*
Any Vimscript or Lua code file that lives in the right directory,
automatically is a "plugin". There's no maniest or "registration" required.
automatically is a "plugin". There's no manifest or "registration" step.
You can try it right now:
@@ -35,7 +35,7 @@ You can try it right now:
Besides `plugin/foo.lua`, which is always run at startup, you can define Lua
modules in the `lua/` directory. Those modules aren't loaded until your
`plugin/foo.lua`, the user, calls `require(…)`.
`plugin/foo.lua`, or the user, calls `require(…)`.
==============================================================================
Type safety *lua-plugin-type-safety*
@@ -108,11 +108,11 @@ In your plugin:
>lua
vim.keymap.set('n', '<Plug>(SayHello)', function()
print('Hello from normal mode')
end, { noremap = true })
end)
vim.keymap.set('v', '<Plug>(SayHello)', function()
print('Hello from visual mode')
end, { noremap = true })
end)
<
In the user's config:
>lua
@@ -176,7 +176,9 @@ For example, instead of:
local foo = require('foo')
vim.api.nvim_create_user_command('MyCommand', function()
foo.do_something()
end, { -- ... })
end, {
-- ...
})
<
which calls `require('foo')` as soon as the module is loaded, you can
lazy-load it by moving the `require` into the command's implementation:
@@ -227,7 +229,7 @@ A plugin tailored to Rust development might have initialization in
-- e.g. add a |<Plug>| mapping or create a command
vim.keymap.set('n', '<Plug>(MyPluginBufferAction)', function()
print('Hello')
end, { noremap = true, buffer = bufnr, })
end, { buffer = bufnr, })
<
==============================================================================
Configuration *lua-plugin-config*
@@ -274,7 +276,7 @@ Versioning and releases *lua-plugin-versioning*
Consider:
- Use |vim.deprecate()| or a `---@deprecate` annotation when you need to
communicate a (future) breaking change or discourged practice.
communicate a (future) breaking change or discouraged practice.
- Using SemVer https://semver.org/ tags and releases to properly communicate
bug fixes, new features, and breaking changes.
- Automating versioning and releases in CI.
@@ -299,7 +301,9 @@ VERSIONING TOOLS
Documentation *lua-plugin-doc*
Provide vimdoc (see |help-writing|), so that users can read your plugin's
documentation in Nvim, by entering `:h {plugin}` in |command-mode|.
documentation in Nvim, by entering `:h {plugin}` in |command-mode|. The
help-tags (the right-aligned "search keywords" in the help documents) are
regenerated using the |:helptags| command.
DOCUMENTATION TOOLS

View File

@@ -848,25 +848,32 @@ prompt.
==============================================================================
4. PROGRESS MESSAGE *progress-message*
Nvim can emit progress-message, which are a special kind of |ui-messages|
used to report the state of long-running tasks.
Plugins and core Nvim features can emit "progress" |ui-messages| to report the
state of long-running tasks.
Progress messages are created or updated using |nvim_echo()| with `kind='progress'`
and the related options. Each message has a unique `msg_id`. A subsequent
message with the same `msg_id` replaces the older one.
Create or update a progress-message by calling |nvim_echo()| with
`kind='progress'`. Each message has a unique message-id, returned by
`nvim_echo`. You can specify the id when calling `nvim_echo` to update an
existing progress-message.
Events: ~
• msg_show |ui-messages| event is fired for ext-ui upon creation/update of a
progress-message
• Updating or creating a progress message also triggers the |Progress| autocommand.
Example: >
local id = vim.api.nvim_echo({{'searching...'}}, true,
{kind='progress', status='running', percent=10, title="term"})
vim.api.nvim_echo({{'searching'}}, true,
{id=id, kind='progress', status='running', percent=50, title="term"})
vim.api.nvim_echo({{'done'}}, true,
{id=id, kind='progress', status='success', percent=100, title="term"})
Example: >lua
local progress = {
kind = 'progress',
status = 'running',
percent = 10,
title = 'term',
}
progress.id = vim.api.nvim_echo({ { 'searching...' } }, true, progress)
progress.percent = 50
vim.api.nvim_echo({ { 'searching' } }, true, progress)
progress.status = 'success'
progress.percent = 100
vim.api.nvim_echo({ { 'done' } }, true, progress)
<
See also: |nvim_echo()| |ui-messages| |Progress|

View File

@@ -68,8 +68,9 @@ DIAGNOSTICS
EDITOR
|i_CTRL-R| inserts named registers (A-Z,a-z,0-9) literally like pasting instead of
as typed. To get the old behavior you can use `<C-R>=@x`.
- |i_CTRL-R| inserts named/clipboard registers (A-Z,a-z,0-9+) literally, like
pasting instead of like user input. Improves performance, avoids broken
formatting. To get the old behavior you can use `<C-R>=@x`.
EVENTS
@@ -203,9 +204,8 @@ EVENTS
HIGHLIGHTS
• |hl-DiffTextAdd| highlights added text within a changed line.
• |hl-StderrMsg| |hl-StdoutMsg|
|hl-OkMsg| |hl-StderrMsg| |hl-StdoutMsg|
• |hl-SnippetTabstopActive| highlights the currently active tabstop.
• |hl-OkMsg| highlights success messages.
LSP
@@ -244,6 +244,7 @@ LSP
• |vim.lsp.buf.signature_help()| supports "noActiveParameterSupport".
• Support for `textDocument/inlineCompletion` |lsp-inline_completion|
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#textDocument_inlineCompletion
See |lsp-inline_completion| for quickstart instructions.
• Support for `textDocument/onTypeFormatting`: |lsp-on_type_formatting|
https://microsoft.github.io/language-server-protocol/specification/#textDocument_onTypeFormatting
@@ -291,6 +292,7 @@ PERFORMANCE
support for nested braces and follows LSP 3.17 specification with
additional constraints for improved correctness and resistance to
backtracking edge cases.
- |i_CTRL-R| inserts named/clipboard registers literally, 10x speedup.
PLUGINS

View File

@@ -649,11 +649,11 @@ ask you where to write the file (there must be a writable directory in
'runtimepath' for this).
The plugin has a default place where to look for spell files, on the Vim ftp
server. The protocol used is SSL (https://) for security. If you want to use
another location or another protocol, set the g:spellfile_URL variable to the
directory that holds the spell files. You can use http:// or ftp://, but you
are taking a security risk then. The |netrw| plugin is used for getting the
file, look there for the specific syntax of the URL. Example: >
server. The protocol used is TLS (`https://`) for security. If you want to
use another location or another protocol, set the g:spellfile_URL variable to
the directory that holds the spell files. You can use `http://` or `ftp://`,
but you are taking a security risk then. The |netrw| plugin is used for
getting the file, look there for the specific syntax of the URL. Example: >
let g:spellfile_URL = 'https://ftp.nluug.nl/vim/runtime/spell'
You may need to escape special characters.

View File

@@ -5264,9 +5264,11 @@ EndOfBuffer Filler lines (~) after the last line in the buffer.
*hl-TermCursor*
TermCursor Cursor in a focused terminal.
*hl-OkMsg*
OkMsg Success messages on the command line.
OkMsg Success messages.
*hl-WarningMsg*
WarningMsg Warning messages.
*hl-ErrorMsg*
ErrorMsg Error messages on the command line.
ErrorMsg Error messages.
*hl-StderrMsg*
StderrMsg Messages in stderr from shell commands.
*hl-StdoutMsg*
@@ -5407,8 +5409,6 @@ Title Titles for output from ":set all", ":autocmd" etc.
Visual Visual mode selection.
*hl-VisualNOS*
VisualNOS Visual mode selection when vim is "Not Owning the Selection".
*hl-WarningMsg*
WarningMsg Warning messages.
*hl-Whitespace*
Whitespace "nbsp", "space", "tab", "multispace", "lead" and "trail"
in 'listchars'.

View File

@@ -136,10 +136,10 @@ might want to try the manual way of downloading the file.
Accessing files over the internet works with the netrw plugin. Currently URLs
with these formats are recognized:
ftp:// uses ftp
rcp:// uses rcp
scp:// uses scp
http:// uses wget (reading only)
`ftp://` uses ftp
`rcp://` uses rcp
`scp://` uses scp
`http://` uses wget (reading only)
Vim doesn't do the communication itself, it relies on the mentioned programs
to be available on your computer. On most Unix systems "ftp" and "rcp" will
@@ -147,7 +147,7 @@ be present. "scp" and "wget" might need to be installed.
Vim detects these URLs for each command that starts editing a new file, also
with ":edit" and ":split", for example. Write commands also work, except for
http://.
`http://`.
For more information, also about passwords, see |netrw|.

View File

@@ -316,8 +316,9 @@ Commands:
Editor:
- |prompt-buffer| supports multiline input/paste, undo/redo, and o/O normal
commands.
- |i_CTRL-R| inserts named registers (A-Z,a-z,0-9) literally like pasting instead of
as typed. To get the old behavior you can use `<C-R>=@x`.
- |i_CTRL-R| inserts named/clipboard registers (A-Z,a-z,0-9+) literally, like
pasting instead of like user input. Improves performance, avoids broken
formatting. To get the old behavior you can use `<C-R>=@x`.
Events (autocommands):
- Fixed inconsistent behavior in execution of nested autocommands #23368

View File

@@ -0,0 +1,75 @@
" Vim Keymap file for Arabic using Buckwalter Transliteration
" see
" http://qamus.org/transliteration.htm
" https://en.wikipedia.org/wiki/Buckwalter_transliteration
"
" Created By: Rafael Ketsetsides <rketsetsides@gmail.com>
" Last Update: 2025 Sep 02
let b:keymap_name = "arabic_buckwalter"
loadkeymap
A <char-0x0627> " ALEF
b <char-0x0628> " BEH
p <char-0x0629> " TEH MARBUTA
t <char-0x062a> " TEH
v <char-0x062b> " THEH
j <char-0x062c> " JEEM
H <char-0x062d> " HAH
x <char-0x062e> " KHAH
d <char-0x062f> " DAL
* <char-0x0630> " THAL
r <char-0x0631> " REH
z <char-0x0632> " ZAIN
s <char-0x0633> " SEEN
$ <char-0x0634> " SHEEN
S <char-0x0635> " SAD
D <char-0x0636> " DAD
T <char-0x0637> " TAH
Z <char-0x0638> " ZAH
E <char-0x0639> " AIN
g <char-0x063a> " GHAIN
_ <char-0x0640> " TATWEEL
f <char-0x0641> " FEH
q <char-0x0642> " QAF
k <char-0x0643> " KAF
l <char-0x0644> " LAM
m <char-0x0645> " MEEM
n <char-0x0646> " NOON
h <char-0x0647> " HEH
w <char-0x0648> " WAW
Y <char-0x0649> " ALEF MAKSURA
y <char-0x064a> " YEH
' <char-0x0621> " HAMZA
| <char-0x0622> " ALEF WITH MADDA ABOVE
> <char-0x0623> " ALEF WITH HAMZA ABOVE
& <char-0x0624> " WAW WITH HAMZA ABOVE
< <char-0x0625> " ALEF WITH HAMZA BELOW
} <char-0x0626> " YEH WITH HAMZA ABOVE
F <char-0x064b> " Tanween -- FATHATAN
N <char-0x064c> " Tanween -- DAMMATAN
K <char-0x064d> " Tanween -- KASRATAN
a <char-0x064e> " Tanween -- FATHA
u <char-0x064f> " Tanween -- DAMMA
i <char-0x0650> " Tanween -- KASRA
~ <char-0x0651> " Tanween -- SHADDA
o <char-0x0652> " Tanween -- SUKUN
; <char-0x061b> " Arabic Semicolon
, <char-0x060c> " Arabic Comma
? <char-0x061f> " Arabic Question Mark
{ <char-0x0671> " ALEF WASLA
P <char-0x067E> " PEH
J <char-0x0686> " TCHEH
V <char-0x06A4> " VEH
G <char-0x06AF> " GAF
0 <char-0x06F0> " Arabic-Indic 0
1 <char-0x06F1> " Arabic-Indic 1
2 <char-0x06F2> " Arabic-Indic 2
3 <char-0x06F3> " Arabic-Indic 3
4 <char-0x06F4> " Arabic-Indic 4
5 <char-0x06F5> " Arabic-Indic 5
6 <char-0x06F6> " Arabic-Indic 6
7 <char-0x06F7> " Arabic-Indic 7
8 <char-0x06F8> " Arabic-Indic 8
9 <char-0x06F9> " Arabic-Indic 9

View File

@@ -2157,8 +2157,7 @@ function vim.api.nvim_set_current_win(window) end
--- ```
--- ["win", winid, bufnr, toprow, botrow]
--- ```
--- - on_line: called for each buffer line being redrawn.
--- (The interaction with fold lines is subject to change)
--- - on_line: (deprecated, use on_range instead)
--- ```
--- ["line", winid, bufnr, row]
--- ```

View File

@@ -2348,7 +2348,7 @@ local pattern = {
},
['require'] = {
['%-requirements%.txt$'] = 'requirements',
['requirements%-.*%.txt$'] = 'requirements',
['^requirements%-.*%.txt$'] = 'requirements',
['^requirements/.*%.txt$'] = 'requirements',
['^requires/.*%.txt$'] = 'requirements',
},
@@ -2530,6 +2530,8 @@ local pattern = {
[',v$'] = 'rcs',
['^svn%-commit.*%.tmp$'] = 'svn',
['%.swift%.gyb$'] = 'swiftgyb',
['^vivado.*%.jou$'] = 'tcl',
['^vivado.*%.log$'] = 'tcl',
['termcap'] = starsetf(function(_path, _bufnr)
return require('vim.filetype.detect').printcap('term')
end),

View File

@@ -844,28 +844,30 @@ function M.inc(path, bufnr)
if vim.g.filetype_inc then
return vim.g.filetype_inc
end
local lines = table.concat(getlines(bufnr, 1, 3))
if lines:lower():find('perlscript') then
return 'aspperl'
elseif lines:find('<%%') then
return 'aspvbs'
elseif lines:find('<%?') then
return 'php'
for _, line in ipairs(getlines(bufnr, 1, 20)) do
if line:lower():find('perlscript') then
return 'aspperl'
elseif line:find('<%%') then
return 'aspvbs'
elseif line:find('<%?') then
return 'php'
-- Pascal supports // comments but they're vary rarely used for file
-- headers so assume POV-Ray
elseif findany(lines, { '^%s{', '^%s%(%*' }) or matchregex(lines, pascal_keywords) then
return 'pascal'
elseif findany(lines, { '^%s*inherit ', '^%s*require ', '^%s*%u[%w_:${}]*%s+%??[?:+]?= ' }) then
return 'bitbake'
else
local syntax = M.asm_syntax(path, bufnr)
if not syntax or syntax == '' then
return 'pov'
end
return syntax, function(b)
vim.b[b].asmsyntax = syntax
elseif findany(line, { '^%s{', '^%s%(%*' }) or matchregex(line, pascal_keywords) then
return 'pascal'
elseif
findany(line, { '^%s*inherit ', '^%s*require ', '^%s*%u[%w_:${}/]*%s+%??[?:+.]?=.? ' })
then
return 'bitbake'
end
end
local syntax = M.asm_syntax(path, bufnr)
if not syntax or syntax == '' then
return 'pov'
end
return syntax, function(b)
vim.b[b].asmsyntax = syntax
end
end
--- @type vim.filetype.mapfn

View File

@@ -1,3 +1,35 @@
--- @brief
--- This module provides the LSP "inline completion" feature, for completing multiline text (e.g.,
--- whole methods) instead of just a word or line, which may result in "syntactically or
--- semantically incorrect" code. Unlike regular completion, this is typically presented as overlay
--- text instead of a menu of completion candidates.
---
--- LSP spec: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#textDocument_inlineCompletion
---
--- To try it out, here is a quickstart example using Copilot: [lsp-copilot]()
---
--- 1. Install Copilot:
--- ```sh
--- npm install --global @github/copilot-language-server
--- ```
--- 2. Define a config, (or copy `lsp/copilot.lua` from https://github.com/neovim/nvim-lspconfig):
--- ```lua
--- vim.lsp.config('copilot', {
--- cmd = { 'copilot-language-server', '--stdio', },
--- root_markers = { '.git' },
--- })
--- ```
--- 3. Activate the config:
--- ```lua
--- vim.lsp.enable('copilot')
--- ```
--- 4. Sign in to Copilot, or use the `:LspCopilotSignIn` command from https://github.com/neovim/nvim-lspconfig
--- 5. Enable inline completion:
--- ```lua
--- vim.lsp.inline_completion.enable()
--- ```
--- 6. Set a keymap for `vim.lsp.inline_completion.get()` and invoke the keymap.
local util = require('vim.lsp.util')
local log = require('vim.lsp.log')
local protocol = require('vim.lsp.protocol')

View File

@@ -1,9 +1,8 @@
" Vim syntax file
" Language: M4
" Language: M4
" Maintainer: Claudio Fleiner (claudio@fleiner.com)
" URL: http://www.fleiner.com/vim/syntax/m4.vim
" (outdated)
" Last Change: 2022 Jun 12
" 2025 Sep 2 by Vim project: fix a few syntax issues #18192
" This file will highlight user function calls if they use only
" capital letters and have at least one argument (i.e. the '('
@@ -18,6 +17,23 @@ if !exists("main_syntax")
let main_syntax='m4'
endif
" Reference: The Open Group Base Specifications, M4
" https://pubs.opengroup.org/onlinepubs/9799919799/
" Quoting in M4:
" Quotes are nestable;
" The delimiters can be redefined with changequote(); here we only handle
" the default pair: ` ... ';
" Quoted text in M4 is rescanned, not treated as a literal string;
" Therefore the region is marked transparent so contained items retain
" their normal highlighting.
syn region m4Quoted
\ matchgroup=m4QuoteDelim
\ start=+`+
\ end=+'+
\ contains=@m4Top
\ transparent
" define the m4 syntax
syn match m4Variable contained "\$\d\+"
syn match m4Special contained "$[@*#]"
@@ -30,28 +46,26 @@ syn region m4Paren matchgroup=m4Delimiter start="(" end=")" contained contain
syn region m4Command matchgroup=m4Function start="\<\(m4_\)\=\(define\|defn\|pushdef\)(" end=")" contains=@m4Top
syn region m4Command matchgroup=m4Preproc start="\<\(m4_\)\=\(include\|sinclude\)("he=e-1 end=")" contains=@m4Top
syn region m4Command matchgroup=m4Statement start="\<\(m4_\)\=\(syscmd\|esyscmd\|ifdef\|ifelse\|indir\|builtin\|shift\|errprint\|m4exit\|changecom\|changequote\|changeword\|m4wrap\|debugfile\|divert\|undivert\)("he=e-1 end=")" contains=@m4Top
syn region m4Command matchgroup=m4builtin start="\<\(m4_\)\=\(len\|index\|regexp\|substr\|translit\|patsubst\|format\|incr\|decr\|eval\|maketemp\)("he=e-1 end=")" contains=@m4Top
syn region m4Command matchgroup=m4Builtin start="\<\(m4_\)\=\(len\|index\|regexp\|substr\|translit\|patsubst\|format\|incr\|decr\|eval\|maketemp\)("he=e-1 end=")" contains=@m4Top
syn keyword m4Statement divert undivert
syn region m4Command matchgroup=m4Type start="\<\(m4_\)\=\(undefine\|popdef\)("he=e-1 end=")" contains=@m4Top
syn region m4Function matchgroup=m4Type start="\<[_A-Z][_A-Z0-9]*("he=e-1 end=")" contains=@m4Top
syn region m4String start="`" end="'" contains=SpellErrors
syn cluster m4Top contains=m4Comment,m4Constants,m4Special,m4Variable,m4String,m4Paren,m4Command,m4Statement,m4Function
syn cluster m4Top contains=m4Comment,m4Constants,m4Special,m4Variable,m4Paren,m4Command,m4Statement,m4Function,m4Quoted
" Define the default highlighting.
" Only when an item doesn't have highlighting yet
hi def link m4Delimiter Delimiter
hi def link m4Comment Comment
hi def link m4Function Function
hi def link m4Keyword Keyword
hi def link m4Special Special
hi def link m4String String
hi def link m4Statement Statement
hi def link m4Preproc PreProc
hi def link m4Type Type
hi def link m4Special Special
hi def link m4Variable Special
hi def link m4Constants Constant
hi def link m4Builtin Statement
hi def link m4QuoteDelim Delimiter
hi def link m4Delimiter Delimiter
hi def link m4Comment Comment
hi def link m4Function Function
hi def link m4Keyword Keyword
hi def link m4Special Special
hi def link m4Statement Statement
hi def link m4Preproc PreProc
hi def link m4Type Type
hi def link m4Variable Special
hi def link m4Constants Constant
hi def link m4Builtin Statement
let b:current_syntax = "m4"

View File

@@ -4,8 +4,8 @@
# changelog header
header = """
# Changelog\n
For notable changes, see runtime/doc/news.txt (or `:help news` in Nvim).\n
Following is a list of fixes/features commits.\n
Following is a list of commits (fixes/features only) in this release.\n
See `:help news` in Nvim for release notes.\n
"""
# template for the changelog body
# https://github.com/Keats/tera

View File

@@ -97,5 +97,5 @@ echo "
Next steps:
- Run tests/CI (version_spec.lua)!
- Push the tag:
git push --follow-tags
git push v${__VERSION}
- Update website: index.html"

View File

@@ -395,6 +395,7 @@ output:write([[
#include "nvim/api/buffer.h"
#include "nvim/api/command.h"
#include "nvim/api/deprecated.h"
#include "nvim/api/events.h"
#include "nvim/api/extmark.h"
#include "nvim/api/options.h"
#include "nvim/api/tabpage.h"

View File

@@ -73,6 +73,7 @@ local new_layout = {
['intro.txt'] = true,
['lua.txt'] = true,
['lua-guide.txt'] = true,
['lua-plugin.txt'] = true,
['luaref.txt'] = true,
['news.txt'] = true,
['news-0.9.txt'] = true,

View File

@@ -1,5 +1,8 @@
#!/usr/bin/env -S nvim -l
--- Generates Nvim :help docs from Lua/C docstrings
--- Generates Nvim :help docs from Lua/C docstrings.
---
--- Usage:
--- make doc
---
--- The generated :help text for each function is formatted as follows:
--- - Max width of 78 columns (`TEXT_WIDTH`).
@@ -106,6 +109,7 @@ local config = {
filename = 'api.txt',
section_order = {
-- Sections at the top, in a specific order:
'events.c',
'vim.c',
'vimscript.c',
@@ -126,11 +130,22 @@ local config = {
['vim.c'] = 'Global',
},
section_fmt = function(name)
if name == 'Events' then
return 'Global Events'
end
return name .. ' Functions'
end,
helptag_fmt = function(name)
return fmt('api-%s', name:lower())
end,
fn_helptag_fmt = function(fun)
local name = fun.name
if vim.endswith(name, '_event') then
return name
end
return fn_helptag_fmt_common(fun)
end,
},
lua = {
filename = 'lua.txt',

View File

@@ -409,13 +409,18 @@ name, etc.
All the global variables are declared in `globals.h`.
### The main loop
### The main event-loop
The main loop is implemented in state_enter. The basic idea is that Vim waits
for the user to type a character and processes it until another character is
needed. Thus there are several places where Vim waits for a character to be
typed. The `vgetc()` function is used for this. It also handles mapping.
What we consider the "Nvim event loop" is actually a wrapper around `uv_run` to
handle both the `fast_events` queue and possibly (a suitable subset of) deferred
events. Therefore "raw" `vim.uv.run()` is often not enough to "yield" from Lua
plugins; instead they can call `vim.wait(0)`.
Updating the screen is mostly postponed until a command or a sequence of
commands has finished. The work is done by `update_screen()`, which calls
`win_update()` for every window, which calls `win_line()` for every line.

76
src/nvim/api/events.c Normal file
View File

@@ -0,0 +1,76 @@
#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "klib/kvec.h"
#include "nvim/api/events.h"
#include "nvim/api/private/converter.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/validate.h"
#include "nvim/api/ui.h"
#include "nvim/assert_defs.h"
#include "nvim/autocmd.h"
#include "nvim/autocmd_defs.h"
#include "nvim/channel.h"
#include "nvim/channel_defs.h"
#include "nvim/eval.h"
#include "nvim/globals.h"
#include "nvim/main.h"
#include "nvim/map_defs.h"
#include "nvim/memory.h"
#include "nvim/memory_defs.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/msgpack_rpc/packer.h"
#include "nvim/msgpack_rpc/packer_defs.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
/// Emitted on the client channel if an async API request responds with an error.
///
/// @param channel_id
/// @param type Error type id as defined by `api_info().error_types`.
/// @param msg Error message.
void nvim_error_event(uint64_t channel_id, Integer type, String msg)
FUNC_API_REMOTE_ONLY
{
// TODO(bfredl): consider printing message to user, as will be relevant
// if we fork nvim processes as async workers
ELOG("async error on channel %" PRId64 ": %s", channel_id, msg.size ? msg.data : "");
}
/// Emitted by the TUI client to signal when a host-terminal event occurred.
///
/// Supports these events:
///
/// - "termresponse": The host-terminal sent a DA1, OSC, DCS, or APC response sequence to Nvim.
/// The payload is the received response. Sets |v:termresponse| and fires
/// |TermResponse|.
///
/// @param channel_id
/// @param event Event name
/// @param value Event payload
/// @param[out] err Error details, if any.
void nvim_ui_term_event(uint64_t channel_id, String event, Object value, Error *err)
FUNC_API_SINCE(12) FUNC_API_REMOTE_ONLY
{
if (strequal("termresponse", event.data)) {
if (value.type != kObjectTypeString) {
api_set_error(err, kErrorTypeValidation, "termresponse must be a string");
return;
}
const String termresponse = value.data.string;
set_vim_var_string(VV_TERMRESPONSE, termresponse.data, (ptrdiff_t)termresponse.size);
MAXSIZE_TEMP_DICT(data, 1);
PUT_C(data, "sequence", value);
apply_autocmds_group(EVENT_TERMRESPONSE, NULL, NULL, true, AUGROUP_ALL, NULL, NULL,
&DICT_OBJ(data));
}
}

8
src/nvim/api/events.h Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
#include <stdint.h> // IWYU pragma: keep
#include "nvim/api/keysets_defs.h" // IWYU pragma: keep
#include "nvim/api/private/defs.h" // IWYU pragma: keep
#include "api/events.h.generated.h"

View File

@@ -1033,8 +1033,7 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start,
/// ```
/// ["win", winid, bufnr, toprow, botrow]
/// ```
/// - on_line: called for each buffer line being redrawn.
/// (The interaction with fold lines is subject to change)
/// - on_line: (deprecated, use on_range instead)
/// ```
/// ["line", winid, bufnr, row]
/// ```

View File

@@ -567,37 +567,6 @@ void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, Floa
ui->pum_pos = true;
}
/// Tells Nvim when a host-terminal event occurred.
///
/// Supports these events:
///
/// - "termresponse": The host-terminal sent a DA1, OSC, DCS, or APC response sequence to Nvim.
/// The payload is the received response. Sets |v:termresponse| and fires
/// |TermResponse|.
///
/// @param channel_id
/// @param event Event name
/// @param value Event payload
/// @param[out] err Error details, if any.
void nvim_ui_term_event(uint64_t channel_id, String event, Object value, Error *err)
FUNC_API_SINCE(12) FUNC_API_REMOTE_ONLY
{
if (strequal("termresponse", event.data)) {
if (value.type != kObjectTypeString) {
api_set_error(err, kErrorTypeValidation, "termresponse must be a string");
return;
}
const String termresponse = value.data.string;
set_vim_var_string(VV_TERMRESPONSE, termresponse.data, (ptrdiff_t)termresponse.size);
MAXSIZE_TEMP_DICT(data, 1);
PUT_C(data, "sequence", value);
apply_autocmds_group(EVENT_TERMRESPONSE, NULL, NULL, true, AUGROUP_ALL, NULL, NULL,
&DICT_OBJ(data));
}
}
static void flush_event(RemoteUI *ui)
{
if (ui->cur_event) {

View File

@@ -1558,7 +1558,7 @@ ArrayOf(Object, 2) nvim_get_api_info(uint64_t channel_id, Arena *arena)
/// orchestration. (Note: Something is better than nothing! Fields are optional, but at least set
/// `name`.)
///
/// Can be called more than once; the caller should merge old info if appropriate. Example: library
/// Can be called more than once; caller should merge old info if appropriate. Example: a library
/// first identifies the channel, then a plugin using that library later identifies itself.
///
/// @param channel_id
@@ -2222,15 +2222,6 @@ DictAs(eval_statusline_ret) nvim_eval_statusline(String str, Dict(eval_statuslin
return result;
}
/// @nodoc
void nvim_error_event(uint64_t channel_id, Integer lvl, String data)
FUNC_API_REMOTE_ONLY
{
// TODO(bfredl): consider printing message to user, as will be relevant
// if we fork nvim processes as async workers
ELOG("async error on channel %" PRId64 ": %s", channel_id, data.size ? data.data : "");
}
/// EXPERIMENTAL: this API may change in the future.
///
/// Sets info for the completion item at the given index. If the info text was shown in a window,

View File

@@ -17,6 +17,8 @@ EXTERN const char *hlf_names[] INIT( = {
[HLF_TERM] = "TermCursor",
[HLF_AT] = "NonText",
[HLF_D] = "Directory",
[HLF_OK] = "OkMsg",
[HLF_W] = "WarningMsg",
[HLF_E] = "ErrorMsg",
[HLF_SE] = "StderrMsg",
[HLF_SO] = "StdoutMsg",
@@ -39,7 +41,6 @@ EXTERN const char *hlf_names[] INIT( = {
[HLF_V] = "Visual",
[HLF_VNC] = "VisualNC",
[HLF_VSP] = "VertSplit",
[HLF_W] = "WarningMsg",
[HLF_WM] = "WildMenu",
[HLF_FL] = "Folded",
[HLF_FC] = "FoldColumn",
@@ -84,7 +85,6 @@ EXTERN const char *hlf_names[] INIT( = {
[HLF_BFOOTER] = "FloatFooter",
[HLF_TS] = "StatusLineTerm",
[HLF_TSNC] = "StatusLineTermNC",
[HLF_OK] = "OkMsg",
});
EXTERN int highlight_attr[HLF_COUNT]; // Highl. attr for each context.

View File

@@ -188,6 +188,7 @@ static bool event_teardown(void)
/// Needed for unit tests.
void early_init(mparm_T *paramp)
{
os_hint_priority();
estack_init();
cmdline_init();
eval_init(); // init global variables

View File

@@ -344,7 +344,7 @@ static HlMessage format_progress_message(HlMessage hl_msg, MessageData *msg_data
/// @param kind Message kind (can be NULL to avoid setting kind)
/// @param history Whether to add message to history
/// @param err Whether to print message as an error
/// @param msg_data Additional data for progress messages
/// @param msg_data Progress-message data
MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bool err,
MessageData *msg_data, bool *needs_msg_clear)
{
@@ -352,6 +352,7 @@ MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bo
msg_start();
msg_clr_eos();
bool need_clear = false;
bool hl_msg_updated = false;
msg_ext_history = history;
if (kind != NULL) {
msg_ext_set_kind(kind);
@@ -368,12 +369,14 @@ MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bo
msg_id_next = id.data.integer + 1;
}
}
msg_ext_id = id;
// progress message are special displayed as "title: percent% msg"
if (strequal(kind, "progress") && msg_data) {
HlMessage formated_message = format_progress_message(hl_msg, msg_data);
if (formated_message.items != hl_msg.items) {
*needs_msg_clear = true;
hl_msg_updated = true;
hl_msg = formated_message;
}
}
@@ -396,6 +399,10 @@ MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bo
is_multihl = false;
no_wait_return--;
msg_end();
if (hl_msg_updated && !(history && kv_size(hl_msg))) {
hl_msg_free(hl_msg);
}
return id;
}
@@ -1161,7 +1168,6 @@ static void msg_hist_add_multihl(MsgID msg_id, HlMessage msg, bool temp, Message
msg_hist_last = entry;
msg_ext_history = true;
msg_ext_id = msg_id;
msg_hist_clear(msg_hist_max);
}

View File

@@ -99,7 +99,7 @@ static const char e_search_pattern_and_expression_register_may_not_contain_two_o
/// The names of operators.
/// IMPORTANT: Index must correspond with defines in ops.h!!!
/// The third field indicates whether the operator always works on lines.
static char opchars[][3] = {
static const char opchars[][3] = {
{ NUL, NUL, 0 }, // OP_NOP
{ 'd', NUL, OPF_CHANGE }, // OP_DELETE
{ 'y', NUL, 0 }, // OP_YANK

View File

@@ -39,6 +39,10 @@
# include "nvim/fileio.h"
#endif
#ifdef __APPLE__
# include <mach/task.h>
#endif
#ifdef HAVE__NSGETENVIRON
# include <crt_externs.h>
#endif
@@ -367,6 +371,18 @@ int64_t os_get_pid(void)
#endif
}
/// Signals to the OS that Nvim is an application for "interactive work"
/// which should be prioritized similar to a GUI app.
void os_hint_priority(void)
{
#ifdef __APPLE__
// By default, processes have the TASK_UNSPECIFIED "role", which means all of its threads are
// clamped to Default QoS. Setting the role to TASK_DEFAULT_APPLICATION removes this clamp.
integer_t policy = TASK_DEFAULT_APPLICATION;
task_policy_set(mach_task_self(), TASK_CATEGORY_POLICY, &policy, 1);
#endif
}
/// Gets the hostname of the current machine.
///
/// @param hostname Buffer to store the hostname.

View File

@@ -335,7 +335,8 @@ ScreenGrid *ui_comp_get_grid_at_coord(int row, int col)
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
ScreenGrid *grid = &wp->w_grid_alloc;
if (row >= grid->comp_row && row < grid->comp_row + grid->rows
&& col >= grid->comp_col && col < grid->comp_col + grid->cols) {
&& col >= grid->comp_col && col < grid->comp_col + grid->cols
&& !wp->w_config.hide) {
return grid;
}
}

View File

@@ -3138,6 +3138,10 @@ static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp)
if (win == win_tp->tp_curwin) {
win_tp->tp_curwin = wp;
}
// Avoid executing cmdline_win logic after it is closed.
if (win == cmdline_win) {
cmdline_win = NULL;
}
return wp;
}
@@ -3412,7 +3416,7 @@ void winframe_restore(win_T *wp, int dir, frame_T *unflat_altfr)
if (frp->fr_parent->fr_layout == FR_COL && frp->fr_prev != NULL) {
if (global_stl_height() == 0 && wp->w_status_height == 0) {
frame_add_statusline(frp->fr_prev);
} else if (wp->w_hsep_height == 0) {
} else if (global_stl_height() > 0 && wp->w_hsep_height == 0) {
frame_add_hsep(frp->fr_prev);
}
}

View File

@@ -84,7 +84,7 @@ describe('insert-mode', function()
]])
end)
it('inserts named registers literally', function()
it('inserts named/clipboard registers literally', function()
local screen = Screen.new(50, 6)
-- regular text without special charecter command
command('let @a = "test"')

View File

@@ -93,7 +93,7 @@ describe('luaeval()', function()
-- Not checked: funcrefs converted to NIL. To be altered to something more
-- meaningful later.
it('correctly evaluates scalars', function()
it('scalars', function()
-- Also test method call (->) syntax
eq(1, fn.luaeval('1'))
eq(0, eval('"1"->luaeval()->type()'))
@@ -114,7 +114,7 @@ describe('luaeval()', function()
eq(NIL, fn.luaeval('nil'))
end)
it('correctly evaluates containers', function()
it('containers', function()
eq({}, fn.luaeval('{}'))
eq(3, eval('type(luaeval("{}"))'))
@@ -145,7 +145,7 @@ describe('luaeval()', function()
)
end)
it('correctly passes scalars as argument', function()
it('passes scalars as argument', function()
eq(1, fn.luaeval('_A', 1))
eq(1.5, fn.luaeval('_A', 1.5))
eq('', fn.luaeval('_A', ''))
@@ -155,7 +155,7 @@ describe('luaeval()', function()
eq(false, fn.luaeval('_A', false))
end)
it('correctly passes containers as argument', function()
it('passes containers as argument', function()
eq({}, fn.luaeval('_A', {}))
eq({ test = 1 }, fn.luaeval('_A', { test = 1 }))
eq({ 4, 2 }, fn.luaeval('_A', { 4, 2 }))
@@ -187,7 +187,7 @@ describe('luaeval()', function()
]=]):format(expr or '"_A"', argexpr):gsub('\n', '')))
end
it('correctly passes special dictionaries', function()
it('passes special dictionaries', function()
eq({ 0, '\000\n\000' }, luaevalarg(sp('string', '["\\n", "\\n"]')))
eq({ 0, true }, luaevalarg(sp('boolean', 1)))
eq({ 0, false }, luaevalarg(sp('boolean', 0)))
@@ -195,7 +195,7 @@ describe('luaeval()', function()
eq({ 0, { [''] = '' } }, luaevalarg(mapsp(sp('string', '[""]'), '""')))
end)
it('issues an error in some cases', function()
it('failure modes', function()
eq(
'Vim(call):E5100: Cannot convert given Lua table: table should contain either only integer keys or only string keys',
exc_exec('call luaeval("{1, foo=2}")')
@@ -205,7 +205,7 @@ describe('luaeval()', function()
startswith('Vim(call):E5108: Lua: [string "luaeval()"]:', exc_exec('call luaeval("(nil)()")'))
end)
it('should handle sending lua functions to viml', function()
it('handles sending lua functions to viml', function()
eq(
true,
exec_lua [[
@@ -294,7 +294,7 @@ describe('luaeval()', function()
matches(': dead function\n', api.nvim_get_vvar('errmsg'))
end)
it('should handle passing functions around', function()
it('can pass functions around', function()
command [[
function VimCanCallLuaCallbacks(Concat, Cb)
let message = a:Concat("Hello Vim", "I'm Lua")
@@ -317,7 +317,7 @@ describe('luaeval()', function()
)
end)
it('should handle funcrefs', function()
it('handles funcrefs', function()
command [[
function VimCanCallLuaCallbacks(Concat, Cb)
let message = a:Concat("Hello Vim", "I'm Lua")
@@ -340,7 +340,7 @@ describe('luaeval()', function()
)
end)
it('should work with metatables using __call', function()
it('works with metatables using __call', function()
eq(
1,
exec_lua [[
@@ -362,7 +362,7 @@ describe('luaeval()', function()
)
end)
it('should handle being called from a timer once.', function()
it('handles being called from a timer once.', function()
eq(
3,
exec_lua [[
@@ -381,7 +381,7 @@ describe('luaeval()', function()
)
end)
it('should call functions once with __call metamethod', function()
it('calls functions once with __call metamethod', function()
eq(
true,
exec_lua [[
@@ -398,7 +398,7 @@ describe('luaeval()', function()
)
end)
it('should work with lists using __call', function()
it('works with lists using __call', function()
eq(
3,
exec_lua [[
@@ -429,7 +429,7 @@ describe('luaeval()', function()
)
end)
it('should not work with tables not using __call', function()
it('fails with tables not using __call', function()
eq(
{ false, 'Vim:E921: Invalid callback argument' },
exec_lua [[
@@ -441,7 +441,7 @@ describe('luaeval()', function()
)
end)
it('correctly converts containers with type_idx', function()
it('converts containers with type_idx', function()
eq(5, eval('type(luaeval("{[vim.type_idx]=vim.types.float, [vim.val_idx]=0}"))'))
eq(4, eval([[type(luaeval('{[vim.type_idx]=vim.types.dictionary}'))]]))
eq(3, eval([[type(luaeval('{[vim.type_idx]=vim.types.array}'))]]))
@@ -463,7 +463,7 @@ describe('luaeval()', function()
eq({}, fn.luaeval('{[vim.type_idx]=vim.types.dictionary}'))
end)
it('correctly converts self-containing containers', function()
it('converts self-containing containers', function()
api.nvim_set_var('l', {})
eval('add(l, l)')
eq(true, eval('luaeval("_A == _A[1]", l)'))
@@ -479,7 +479,7 @@ describe('luaeval()', function()
eq(true, eval('luaeval("_A ~= _A.d", {"d": d})'))
end)
it('errors out correctly when doing incorrect things in lua', function()
it('fails when doing incorrect things in lua', function()
-- Conversion errors
eq(
'Vim(call):E5108: Lua: [string "luaeval()"]:1: attempt to call field \'xxx_nonexistent_key_xxx\' (a nil value)',
@@ -531,7 +531,7 @@ describe('v:lua', function()
]])
end)
it('works in expressions', function()
it('in expressions', function()
eq(7, eval('v:lua.foo(3,4,v:null)'))
eq(true, exec_lua([[return _G.val == vim.NIL]]))
eq(NIL, eval('v:lua.mymod.noisy("eval")'))
@@ -545,7 +545,7 @@ describe('v:lua', function()
)
end)
it('works when called as a method', function()
it('when called as a method', function()
eq(123, eval('110->v:lua.foo(13)'))
eq(true, exec_lua([[return _G.val == nil]]))
@@ -562,7 +562,7 @@ describe('v:lua', function()
)
end)
it('works in :call', function()
it('in :call', function()
command(":call v:lua.mymod.noisy('command')")
eq('hey command', api.nvim_get_current_line())
eq(
@@ -571,7 +571,7 @@ describe('v:lua', function()
)
end)
it('works in func options', function()
it('in func options', function()
local screen = Screen.new(60, 8)
api.nvim_set_option_value('omnifunc', 'v:lua.mymod.omni', {})
feed('isome st<c-x><c-o>')
@@ -599,7 +599,7 @@ describe('v:lua', function()
eq(9004, eval("0 ? v:lua.require'bar'.doit() : v:lua.require'baz-quux'.doit()"))
end)
it('throw errors for invalid use', function()
it('fails for invalid usage', function()
eq(
[[Vim(let):E15: Invalid expression: "v:lua.func"]],
pcall_err(command, 'let g:Func = v:lua.func')
@@ -639,7 +639,7 @@ describe('v:lua', function()
eq([[Vim:E15: Invalid expression: "v:lua.()"]], pcall_err(eval, 'v:lua.()'))
end)
describe('invalid use in fold text', function()
describe('invalid usage in fold text', function()
before_each(function()
feed('ifoo<CR>bar<Esc>')
command('1,2fold')

View File

@@ -390,6 +390,13 @@ describe('vim.ui_attach', function()
9 bufname( {12: } |
Excommand:call bufadd^( |
]])
-- No crash after _cmdline_offset window is closed #35584.
exec_lua(function()
vim.ui_detach(_G.ns)
vim.api.nvim_win_close(_G.win, true)
end)
feed('<Esc>:<Tab>')
n.assert_alive()
end)
end)

View File

@@ -3185,7 +3185,7 @@ describe('progress-message', function()
setup_autocmd()
end)
it('can be sent by nvim_echo', function()
it('emitted by nvim_echo', function()
local id = api.nvim_echo(
{ { 'test-message' } },
true,
@@ -3194,9 +3194,9 @@ describe('progress-message', function()
screen:expect({
grid = [[
^ |
{1:~ }|*4
]],
^ |
{1:~ }|*4
]],
messages = {
{
content = {
@@ -3283,7 +3283,7 @@ describe('progress-message', function()
-- failed status
api.nvim_echo(
{ { 'test-message (success)' } },
{ { 'test-message (fail)' } },
true,
{ kind = 'progress', title = 'TestSuit', percent = 35, status = 'failed' }
)
@@ -3298,7 +3298,7 @@ describe('progress-message', function()
{ 'TestSuit', 9, 'ErrorMsg' },
{ ': ' },
{ ' 35% ', 19, 'WarningMsg' },
{ 'test-message (success)' },
{ 'test-message (fail)' },
},
history = true,
id = 3,
@@ -3309,22 +3309,22 @@ describe('progress-message', function()
-- cancel status
api.nvim_echo(
{ { 'test-message (success)' } },
{ { 'test-message (cancel)' } },
true,
{ kind = 'progress', title = 'TestSuit', percent = 30, status = 'cancel' }
)
screen:expect({
grid = [[
^ |
{1:~ }|*4
]],
^ |
{1:~ }|*4
]],
messages = {
{
content = {
{ 'TestSuit', 19, 'WarningMsg' },
{ ': ' },
{ ' 30% ', 19, 'WarningMsg' },
{ 'test-message (success)' },
{ 'test-message (cancel)' },
},
history = true,
id = 4,
@@ -3640,4 +3640,41 @@ describe('progress-message', function()
{6:TestSuit}: {19: 10% }test-message |
]])
end)
it('works with history off', function()
api.nvim_echo({ { 'test-message' } }, false, {
kind = 'progress',
title = 'TestSuit',
percent = 10,
status = 'running',
})
screen:expect({
grid = [[
^ |
{1:~ }|*4
]],
messages = {
{
content = {
{ 'TestSuit', 6, 'MoreMsg' },
{ ': ' },
{ ' 10% ', 19, 'WarningMsg' },
{ 'test-message' },
},
id = 1,
kind = 'progress',
},
},
})
assert_progress_autocmd({
text = { 'test-message' },
percent = 10,
status = 'running',
title = 'TestSuit',
id = 1,
data = {},
}, 'progress autocmd receives progress messages')
end)
end)

File diff suppressed because it is too large Load Diff

View File

@@ -362,6 +362,7 @@ local expect_keys = {
condition = true,
mouse_enabled = true,
any = true,
none = true,
mode = true,
unchanged = true,
intermediate = true,
@@ -408,7 +409,13 @@ end
--- following chars are magic characters
--- ( ) . % + - * ? [ ^ $
--- and must be escaped with a preceding % for a literal match.
--- @field any? string
--- @field any? string|table<string>
---
--- Lua pattern string expected to not match a screen line. NB: the
--- following chars are magic characters
--- ( ) . % + - * ? [ ^ $
--- and must be escaped with a preceding % for a literal match.
--- @field none? string|table<string>
---
--- Expected mode as signaled by "mode_change" event
--- @field mode? string
@@ -492,7 +499,7 @@ function Screen:expect(expected, attr_ids, ...)
grid = expected.grid
attr_ids = expected.attr_ids
condition = expected.condition
assert(expected.any == nil or grid == nil)
assert((expected.any == nil and expected.none == nil) or grid == nil)
elseif type(expected) == 'string' then
grid = expected
expected = {}
@@ -541,22 +548,55 @@ function Screen:expect(expected, attr_ids, ...)
local actual_rows
if expected.any or grid then
actual_rows = self:render(not expected.any, attr_state)
actual_rows = self:render(not (expected.any or expected.none), attr_state)
end
if expected.any then
-- Search for `any` anywhere in the screen lines.
local any_or_none = function(screen_str, value, is_any)
if value then
local v = value
if type(v) == 'string' then
v = { v }
end
local msg
if is_any then
msg = 'Expected (anywhere): "'
else
msg = 'Expected (nowhere): "'
end
for _, v2 in ipairs(v) do
local test = screen_str:find(v2)
if is_any then
test = not test
end
-- Search for `any` anywhere in the screen lines.
if test then
return (
'Failed to match any screen lines.\n'
.. msg
.. v2
.. '"\n'
.. 'Actual:\n |'
.. table.concat(actual_rows, '\n |')
.. '\n\n'
)
end
end
end
return nil
end
if expected.any or expected.none then
local actual_screen_str = table.concat(actual_rows, '\n')
if not actual_screen_str:find(expected.any) then
return (
'Failed to match any screen lines.\n'
.. 'Expected (anywhere): "'
.. expected.any
.. '"\n'
.. 'Actual:\n |'
.. table.concat(actual_rows, '\n |')
.. '\n\n'
)
if expected.any then
local res = any_or_none(actual_screen_str, expected.any, true)
if res then
return res
end
end
if expected.none then
local res = any_or_none(actual_screen_str, expected.none, false)
if res then
return res
end
end
end

View File

@@ -504,6 +504,20 @@ describe('global statusline', function()
{3:[No Name] 0,0-1 All}|
|
]])
-- Shouldn't gain a hsep if the global statusline is turned off.
command('set laststatus=2')
eq('Vim(wincmd):E36: Not enough room', pcall_err(command, 'wincmd L'))
command('mode')
screen:expect([[
|
{1:~ }|*5
{2:[No Name] 0,0-1 All}|
^ |
{1:~ }|*6
{3:[No Name] 0,0-1 All}|
|
]])
end)
end)

View File

@@ -76,7 +76,39 @@ describe('screenchar() and family respect floating windows', function()
describe('with ext_multigrid', function()
with_ext_multigrid(true)
end)
describe('without ext_multigrid', function()
with_ext_multigrid(false)
end)
describe('hidden windows', function()
before_each(function()
clear()
Screen.new(40, 7, {})
api.nvim_buf_set_lines(0, 0, -1, true, { 'aaa', 'aaa' })
end)
local assert_screen_funcs = function()
eq('a', fn.screenstring(1, 1))
eq(97, fn.screenchar(1, 1))
eq({ 97 }, fn.screenchars(1, 1))
eq(fn.screenattr(2, 1), fn.screenattr(1, 1))
end
it('manual', function()
local bufnr = api.nvim_create_buf(false, true)
api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'bb' })
local win_opts = { relative = 'editor', row = 0, col = 0, height = 1, width = 2, hide = true }
api.nvim_open_win(bufnr, false, win_opts)
assert_screen_funcs()
end)
it('from ui2', function()
n.exec_lua('require("vim._extui").enable({ enable = true })')
command('echo "foo"')
assert_screen_funcs()
end)
end)
end)

View File

@@ -820,7 +820,8 @@ func s:GetFilenameChecks() abort
\ 'tal': ['file.tal'],
\ 'taskdata': ['pending.data', 'completed.data', 'undo.data'],
\ 'taskedit': ['file.task'],
\ 'tcl': ['file.tcl', 'file.tm', 'file.tk', 'file.itcl', 'file.itk', 'file.jacl', '.tclshrc', 'tclsh.rc', '.wishrc', '.tclsh-history', '.xsctcmdhistory', '.xsdbcmdhistory'],
\ 'tcl': ['file.tcl', 'file.tm', 'file.tk', 'file.itcl', 'file.itk', 'file.jacl', '.tclshrc', 'tclsh.rc', '.wishrc', '.tclsh-history',
\ '.xsctcmdhistory', '.xsdbcmdhistory', 'vivado.jou', 'vivado.log'],
\ 'teal': ['file.tl'],
\ 'templ': ['file.templ'],
\ 'template': ['file.tmpl'],
@@ -2659,6 +2660,21 @@ func Test_inc_file()
call assert_equal('bitbake', &filetype)
bwipe!
call writefile(['PREFERRED_PROVIDER_virtual/kernel = "linux-yocto"'], 'Xfile.inc')
split Xfile.inc
call assert_equal('bitbake', &filetype)
bwipe!
call writefile(['MACHINEOVERRIDES =. "qemuall:"'], 'Xfile.inc')
split Xfile.inc
call assert_equal('bitbake', &filetype)
bwipe!
call writefile(['BBPATH .= ":${LAYERDIR}"'], 'Xfile.inc')
split Xfile.inc
call assert_equal('bitbake', &filetype)
bwipe!
" asm
call writefile(['asmsyntax=foo'], 'Xfile.inc')
split Xfile.inc