Compare commits

...

49 Commits

Author SHA1 Message Date
zeertzjq
506eaf2aac vim-patch:9.1.0733: keyword completion does not work with fuzzy
Problem:  keyword completion does not work with fuzzy
          (egesip)
Solution: handle ctrl_x_mode_normal() specifically
          (glepnir)

fixes: vim/vim#15412
closes: vim/vim#15424

7cfe693f9b

Co-authored-by: glepnir <glephunter@gmail.com>
2024-09-16 09:15:27 +08:00
zeertzjq
5f27960302 vim-patch:26e4b00: runtime(doc): Revert outdated comment in completeopt's fuzzy documentation
Originally, `:set completeopt+=fuzzy` did not affect how the candidate
list is collected in default keyword completion. A comment was added to
documentation as part of vim/vim#14912 to clarify it. vim/vim#15193 later changed the
fuzzy behavior to now change the candidate collection behavior as well
so the clarification in docs is now wrong. Remove them here.

closes: vim/vim#15656

26e4b00002

Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
2024-09-16 09:09:56 +08:00
zeertzjq
72fa480df8 vim-patch:9.1.0705: Sorting of fuzzy filename completion is not stable
Problem:  Sorting of fuzzy filename completion is not stable
Solution: Compare indexes when scores are equal.  Fix some typos.
          (zeertzjq)

closes: vim/vim#15593

58d705238c
2024-09-16 09:09:56 +08:00
zeertzjq
760e62345d vim-patch:9.1.0654: completion does not respect completeslash with fuzzy
Problem:  completion does not respect completeslash with fuzzy
          (egesip)
Solution: Change path separator on Windows, depending on 'completeslash'
          option value (glepnir)

fixes: vim/vim#15392
closes: vim/vim#15418

b9de1a057f

Co-authored-by: glepnir <glephunter@gmail.com>
2024-09-16 09:09:56 +08:00
zeertzjq
0b1751f7f8 vim-patch:9.1.0634: Ctrl-P not working by default
Problem:  Ctrl-P not working by default
          (Jesse Pavel, after v9.1.0598)
Solution: Revert part of v9.1.0598 and set cur_match_pos
          correctly according to compl_dir_forward()

fixes: vim/vim#15370
closes: vim/vim#15379

13032a49b7

Co-authored-by: Christian Brabandt <cb@256bit.org>
2024-09-16 09:09:56 +08:00
zeertzjq
85328ac139 vim-patch:9.1.0631: wrong completion list displayed with non-existing dir + fuzzy completion
Problem:  wrong completion list displayed with non-existing dir + fuzzy
          completion (kawarimidoll)
Solution: clear list of matches, if leader did not use fuzzy match
          (glepnir)

fixes: vim/vim#15357
closes: vim/vim#15365

6b6280c4a2

Co-authored-by: glepnir <glephunter@gmail.com>
2024-09-16 09:09:56 +08:00
zeertzjq
b42ecb6753 vim-patch:9.1.0605: internal error with fuzzy completion
Problem:  internal error with fuzzy completion
          (techntools)
Solution: only fuzzy complete the pattern after directory separator
          (glepnir)

fixes: vim/vim#15287
closes: vim/vim#15291

0be03e14b9

Co-authored-by: glepnir <glephunter@gmail.com>
2024-09-16 09:09:56 +08:00
zeertzjq
e6c9862dcd vim-patch:9.1.0598: fuzzy completion does not work with default completion
Problem:  fuzzy completion does not work with default completion
Solution: Make it work (glepnir)

closes: vim/vim#15193

8159fb18a9

Cherry-pick insexpand.c changes from patch 9.1.0608.

N/A patch:
vim-patch:9.1.0632: MS-Windows: Compiler Warnings

Co-authored-by: glepnir <glephunter@gmail.com>
2024-09-16 09:09:56 +08:00
zeertzjq
78b8510933
vim-patch:4d427d4: runtime(vim): Update base-syntax, match Vim9 bool/null literal args to :if/:while/:return (#30391)
Match Vim9 boolean and null literals in expression arguments of :if,
:elseif, :while and :return.

closes: vim/vim#15684

4d427d4cab

Co-authored-by: Doug Kearns <dougkearns@gmail.com>
2024-09-15 22:57:16 +00:00
Justin M. Keyes
057d27a9d6
refactor: rename "process" => "proc" #30387
Problem:
- "process" is often used as a verb (`multiqueue_process_events`), which
  is ambiguous for cases where it's used as a topic.
- The documented naming convention for processes is "proc".
  - `:help dev-name-common`
- Shorter is better, when it doesn't harm readability or
  discoverability.

Solution:
Rename "process" => "proc" in all C symbols and module names.
2024-09-15 12:20:58 -07:00
Justin M. Keyes
5792546777
refactor(tests): rename terminal/testutil.lua => testterm.lua #30372
This module is generally used by any tests that need the full Nvim TUI
instead of `screen.lua`. Thus it should live in `functional/` instead of
in `functional/terminal/`.
2024-09-15 03:28:14 -07:00
zeertzjq
3b54adc6c6
Merge pull request #30378 from zeertzjq/vim-9.1.0729
vim-patch:9.1.{0729,0730}
2024-09-14 19:51:11 +08:00
zeertzjq
325d349f9d
vim-patch:9.1.0728: [security]: heap-use-after-free in garbage collection with location list user data (#30377)
Problem:  heap-use-after-free in garbage collection with location list
          user data.
Solution: Mark user data as in use when no other window is referencing
          the location list (zeertzjq)

fixes: neovim/neovim#30371
closes: vim/vim#15683

be4bd189d2
2024-09-14 19:38:33 +08:00
zeertzjq
5191a11d66 vim-patch:9.1.0730: Crash with cursor-screenline and narrow window
Problem:  Crash with cursor-screenline and narrow window
          (elig0n)
Solution: Don't set right_col when width2 is 0 (zeertzjq).

fixes: vim/vim#15677
closes: vim/vim#15678

59149f0269
2024-09-14 19:29:40 +08:00
zeertzjq
90585e47fe vim-patch:9.1.0729: Wrong cursor-screenline when resizing window
Problem:  Wrong cursor-screenline when resizing window
Solution: Invalidate saved left_col and right_col when width1 or width2
          change.

closes: vim/vim#15679

86dc4f8b43
2024-09-14 19:29:37 +08:00
Jaehwang Jung
f2173b1aa2
fix(defaults): cannot remove "How-to disable mouse" menu item #30375 2024-09-14 02:18:38 -07:00
dundargoc
67d6b6f27e ci: skip automerge step if backport failed 2024-09-14 01:55:36 +02:00
Mathias Fussenegger
8512f669f0 fix(lsp): handle nil bytes in strings
Problem:

The LSP omnifunc can insert nil bytes, which when read in other places
(like semantic token) could cause an error:

    semantic_tokens.lua:304: Vim:E976: Using a Blob as a String

Solution:

Use `#line` instead of `vim.fn.strlen(line)`. Both return UTF-8 bytes
but the latter can't handle nil bytes.

Completion candidates can currently insert nil bytes, if other parts of
Alternative fix to https://github.com/neovim/neovim/pull/30359

Note that https://github.com/neovim/neovim/pull/30315 will avoid the
insertion of nil bytes from the LSP omnifunc, but the change of this PR
can more easily be backported.
2024-09-13 22:34:49 +02:00
dundargoc
755512ed60 ci: don't add reviewers for PRs created by a bot
This will ensure automatic backports created by the backport action does
not request reviewers (since the commit in question has already been
vetted and merged), but manual backports created by users does request
reviewers as these commits has not been vetted previously.
2024-09-13 16:58:15 +02:00
dundargoc
4c23b83456 ci: add needs:backport label on backport PRs with conflict
This makes it easy to keep track of which backport PRs have failed and
need manual intervention to fix.
2024-09-13 16:49:35 +02:00
dundargoc
5284a2a793 build: bump unibilium to v2.1.2
There is no real practical difference from previous commit except that
this is a tagged release.
2024-09-13 15:56:37 +02:00
Riley Bruins
b9b408a56c
feat(treesitter): start moving get_parser to return nil #30313
**Problem:** `vim.treesitter.get_parser` will throw an error if no parser
can be found.

- This means the caller is responsible for wrapping it in a `pcall`,
  which is easy to forget
- It also makes it slightly harder to potentially memoize `get_parser`
  in the future
- It's a bit unintuitive since many other `get_*` style functions
  conventionally return `nil` if no object is found (e.g. `get_node`,
  `get_lang`, `query.get`, etc.)

**Solution:** Return `nil` if no parser can be found or created

- This requires a function signature change, and some new assertions in
  places where the parser will always (or should always) be found.
- This commit starts by making this change internally, since it is
  breaking. Eventually it will be rolled out to the public API.
2024-09-13 05:09:11 -07:00
James Trew
8654a97006
fix(lsp): handle empty call hierarchy items #30349
Ensure that the function `pick_call_hierarchy_item` correctly handles
the case where `call_hierarchy_items` is nil or an empty table. This
prevents potential errors when the function is called with no items.
2024-09-13 04:59:49 -07:00
dundargoc
057314345a ci: enable automerge by default when backporting
This will automatically merge backported PRs without human intervention
if the tests pass.
2024-09-13 12:31:33 +02:00
Justin M. Keyes
deac7df80a
refactor(stream.c): unused params in stream_close #30356 2024-09-12 09:16:57 -07:00
Christian Clason
ae917dbd06 fix(treesitter): sync queries from upstream 2024-09-12 13:41:15 +02:00
Christian Clason
c65153893a build(deps): bump tree-sitter-c to v0.23.0 2024-09-12 13:41:15 +02:00
Christian Clason
f6cc0394ae build(deps): bump tree-sitter-markdown to v0.3.2 2024-09-12 13:41:15 +02:00
Christian Clason
f347c292d1 build(deps): bump tree-sitter-lua to v0.2.0 2024-09-12 13:41:15 +02:00
zeertzjq
48c14d3544
vim-patch:9.1.0725: filetype: swiftinterface files are not recognized (#30350)
Problem:  filetype: swiftinterface files are not recognized
Solution: Detect '*.swiftinterface' files as swift filetype
          (LosFarmosCTL)

closes: vim/vim#15658

03cac4b70d

Co-authored-by: LosFarmosCTL <80157503+LosFarmosCTL@users.noreply.github.com>
2024-09-12 15:16:58 +08:00
Justin M. Keyes
5931f780e0
feat(log): use "ui" as default name for TUI client #30345
The default "session name" for the builtin TUI is "ui".

before:

    INF 2024-09-10T14:57:35.385 hello.sock os_exit:692: Nvim exit: 1
    INF 2024-09-10T14:57:35.388 ?.4543     os_exit:692: Nvim exit: 1

after:

    INF 2024-09-10T14:59:19.919 hello.sock os_exit:692: Nvim exit: 1
    INF 2024-09-10T14:59:19.922 ui.5684    os_exit:692: Nvim exit: 1
2024-09-11 17:25:00 -07:00
Gregory Anders
98ba65b8be
fix: replace NVIM with Nvim in default titlestring (#30348) 2024-09-11 20:32:08 +00:00
glepnir
f9bf64d746
fix(lsp): check buffer is loaded and valid #30330
Problem: buffer mabye not valid when callback handler invoke.

Soliton: check buffer is valid and loaded in handler.
2024-09-11 08:11:09 -07:00
Justin M. Keyes
a30afeeb85
Merge #30342 :checkhealth completion 2024-09-11 03:01:48 -07:00
Justin M. Keyes
7b680e0ca9 test(health): "test_plug/health/init.lua" completes as "test_plug" 2024-09-11 11:40:56 +02:00
Christian Clason
8501fe621a build(deps): bump unibilium to HEAD - ab28a2ddb 2024-09-11 11:10:40 +02:00
Christian Clason
a5bd6665b0 fix(scripts): update bundled dependencies in bump_deps 2024-09-11 11:10:40 +02:00
Christian Clason
4ac733f6ef vim-patch:fc72a2f: runtime(idlang): update syntax script
closes: vim/vim#15419

fc72a2fa48

Co-authored-by: Joe Sapp <992873+sappjw@users.noreply.github.com>
2024-09-11 09:47:30 +02:00
Christian Clason
c1a4b8680b vim-patch:e401576: runtime(spec): Recognize epoch when making spec changelog in ftplugin
closes: vim/vim#15537

e40157641c

Co-authored-by: fundawang <fundawang@yeah.net>
2024-09-11 09:47:30 +02:00
Christian Clason
f6579a4db1 vim-patch:2241f08: runtime(spec): add file triggers to syntax script
closes: vim/vim#15569

2241f0845f

Co-authored-by: fundawang <fundawang@yeah.net>
2024-09-11 09:47:30 +02:00
Christian Clason
608ef83fc6 vim-patch:077d1d2: runtime(make): add compiler/make.vim to reset compiler plugin settings
closes: vim/vim#15645

077d1d2cff

Co-authored-by: Konfekt <Konfekt@users.noreply.github.com>
Co-authored-by: K.Takata <kentkt@csc.jp>
2024-09-11 09:47:30 +02:00
Christian Clason
57db94235c vim-patch:a9ae38d: runtime(java): Recognise all available standard doclet tags
* Complement the tag set with @spec, {@systemProperty},
  {@summary}, @provides, @uses, @hidden, and {@index}.
* Do not hoard all tags under a single highlighting group.
* Skip over nested balanced braces in inline tags.
* Observe that tag names are case sensitive: both {@docRoot}
  and {@inheritDoc} are valid, whereas {@inheritdoc} and
  {@docroot} are not.
* In the @see tag arguments, allow for:
  - module name prefixes (e.g. java.base/java.lang.String);
  - references to arbitrary URI fragments (e.g. ##foo);
  - matching any tag variation arguments on the next line.
* Test directives and tags for Java module declarations.
* Enforce the word end for "module-info" candidates.

References:
https://bugs.openjdk.org/browse/JDK-8226279 (@spec)
https://bugs.openjdk.org/browse/JDK-8214559 ({@systemProperty})
https://bugs.openjdk.org/browse/JDK-8173425 ({@summary})
https://bugs.openjdk.org/browse/JDK-8160196 (@provides & @uses)
https://bugs.openjdk.org/browse/JDK-8073100 (@hidden)
https://bugs.openjdk.org/browse/JDK-8044243 ({@index})
https://docs.oracle.com/en/java/javase/21/docs/specs/javadoc/doc-comment-spec.html
https://github.com/openjdk/jdk/blob/jdk-21-ga/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java

closes: vim/vim#15652

a9ae38dc3f

Co-authored-by: Aliaksei Budavei <0x000c70@gmail.com>
2024-09-11 09:47:30 +02:00
Christian Clason
cdab8c8ebb vim-patch:c0982f9: runtime(dosini): Update syntax script, spellcheck comments only
By default spell checking is enabled for all text, but adding
`contains=@Spell` to syntax rules restricts spell checking to those
syntax rules.  See `:help spell-syntax` for full details.

Variable names and headers are far more likely than comments to contain
spelling errors, so only enable spell checking in comments.

Introduced in https://github.com/xuhdev/syntax-dosini.vim/pull/8

cc @tobinjt

closes: vim/vim#15655

c0982f9f79

Co-authored-by: John Tobin <johntobin@johntobin.ie>
2024-09-11 09:47:30 +02:00
Christian Clason
830cf054bc vim-patch:d30ffdc: runtime(pandoc): Update compiler plugin to use actual 'spelllang'
Previously these would be cached in buffer-local variables and
would not change on :compiler pandoc

closes: vim/vim#15642

d30ffdca49

Co-authored-by: Christian Brabandt <cb@256bit.org>
2024-09-11 09:47:30 +02:00
Christian Clason
def6111118 vim-patch:7cc0e91: runtime(groff): Add compiler plugin for groff
Groff MOM (Macros for Manuscripts) is a macro package for the GNU
troff (groff) typesetting system, a light-weight alternative
to LaTeX for professional-quality documents.

closes: vim/vim#15646

7cc0e9145d

Co-authored-by: Konfekt <Konfekt@users.noreply.github.com>
2024-09-11 09:47:30 +02:00
monkoose
237d2aef4d
fix(health): return correct name from 'path2name()'
`path2name()` function doesn't process `'pluginname/health/init.lua'` correctly. Instead of retruning `'pluginname'` it returns `'pluginname.health'`
2024-09-11 07:55:37 +03:00
zeertzjq
15bfdf73ea
vim-patch:9.1.0727: too many strlen() calls in option.c (#30338)
Problem:  too many strlen() calls in option.c
Solution: refactor the code to reduce the number of strlen() calls
          (John Marriott)

closes: vim/vim#15604

95dacbb5fd

Co-authored-by: John Marriott <basilisk@internode.on.net>
2024-09-10 23:31:07 +00:00
dundargoc
f289161c3c test: add termkey unit tests
Skipped importing the following unit tests from libtermkey as they'd
require introducing a lot of unused code or require more effort to port
than is probably worth:

- 05read
- 12strpkey
- 20canon
- 40ti-override
2024-09-11 00:36:14 +02:00
zeertzjq
4b98d38870
vim-patch:d657d3d: runtime(doc): clarify the effect of the timeout for search()-functions (#30337)
related: vim/vim#15657
related: vim/vim#15404

d657d3d8fd

Co-authored-by: Christian Brabandt <cb@256bit.org>
2024-09-11 06:09:58 +08:00
109 changed files with 2418 additions and 606 deletions

View File

@ -26,3 +26,21 @@ jobs:
pull_title: "${pull_title}"
label_pattern: "^ci:backport ([^ ]+)$"
github_token: ${{ steps.app-token.outputs.token }}
- name: Create failed backport label
if: ${{ steps.backport.outputs.was_successful == 'false' }}
uses: actions/github-script@v7
with:
script: |
github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['needs:backport']
})
- name: Enable automerge
if: ${{ steps.backport.outputs.was_successful == 'true' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh pr merge --rebase --auto ${{ steps.backport.outputs.created_pull_numbers }}

View File

@ -5,7 +5,7 @@ on:
workflow_call:
jobs:
request-reviewer:
if: github.event.pull_request.state == 'open' && github.event.pull_request.draft == false
if: github.event.pull_request.state == 'open' && github.event.pull_request.draft == false && !endsWith(github.actor, '[bot]')
runs-on: ubuntu-latest
permissions:
pull-requests: write

View File

@ -7,8 +7,8 @@ LUAJIT_SHA256 2b5514bd6a6573cb6111b43d013e952cbaf46762d14ebe26c872ddb80b5a84e0
LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz
LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333
UNIBILIUM_URL https://github.com/neovim/unibilium/archive/d72c3598e7ac5d1ebf86ee268b8b4ed95c0fa628.tar.gz
UNIBILIUM_SHA256 9c4747c862ab5e3076dcf8fa8f0ea7a6b50f20ec5905618b9536655596797487
UNIBILIUM_URL https://github.com/neovim/unibilium/archive/v2.1.2.tar.gz
UNIBILIUM_SHA256 370ecb07fbbc20d91d1b350c55f1c806b06bf86797e164081ccc977fc9b3af7a
LUV_URL https://github.com/luvit/luv/releases/download/1.48.0-2/luv-1.48.0-2.tar.gz
LUV_SHA256 2c3a1ddfebb4f6550293a40ee789f7122e97647eede51511f57203de48c03b7a
@ -38,18 +38,18 @@ LIBICONV_SHA256 8f74213b56238c85a50a5329f77e06198771e70dd9a739779f4c02f65d971313
UTF8PROC_URL https://github.com/JuliaStrings/utf8proc/archive/3de4596fbe28956855df2ecb3c11c0bbc3535838.tar.gz
UTF8PROC_SHA256 fb4a16bb659b58afb7f921fcc8928d0b3c1fcab135366c8a4f9ca7de1b1cfada
TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.21.3.tar.gz
TREESITTER_C_SHA256 75a3780df6114cd37496761c4a7c9fd900c78bee3a2707f590d78c0ca3a24368
TREESITTER_LUA_URL https://github.com/tree-sitter-grammars/tree-sitter-lua/archive/v0.1.0.tar.gz
TREESITTER_LUA_SHA256 230cfcbfa74ed1f7b8149e9a1f34c2efc4c589a71fe0f5dc8560622f8020d722
TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.23.0.tar.gz
TREESITTER_C_SHA256 ee58c925e2e507c23d735aad46bf7fb0af31ca06d6f4f41bc008216d9232b0cb
TREESITTER_LUA_URL https://github.com/tree-sitter-grammars/tree-sitter-lua/archive/v0.2.0.tar.gz
TREESITTER_LUA_SHA256 6c41227cd0a59047b19d31f0031d4d901f08bfd78d6fc7f55c89e5b8374c794e
TREESITTER_VIM_URL https://github.com/neovim/tree-sitter-vim/archive/v0.4.0.tar.gz
TREESITTER_VIM_SHA256 9f856f8b4a10ab43348550fa2d3cb2846ae3d8e60f45887200549c051c66f9d5
TREESITTER_VIMDOC_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v3.0.0.tar.gz
TREESITTER_VIMDOC_SHA256 a639bf92bf57bfa1cdc90ca16af27bfaf26a9779064776dd4be34c1ef1453f6c
TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/archive/v0.4.0.tar.gz
TREESITTER_QUERY_SHA256 d3a423ab66dc62b2969625e280116678a8a22582b5ff087795222108db2f6a6e
TREESITTER_MARKDOWN_URL https://github.com/MDeiml/tree-sitter-markdown/archive/v0.2.3.tar.gz
TREESITTER_MARKDOWN_SHA256 4909d6023643f1afc3ab219585d4035b7403f3a17849782ab803c5f73c8a31d5
TREESITTER_MARKDOWN_URL https://github.com/tree-sitter-grammars/tree-sitter-markdown/archive/v0.3.2.tar.gz
TREESITTER_MARKDOWN_SHA256 5dac48a6d971eb545aab665d59a18180d21963afc781bbf40f9077c06cb82ae5
TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.23.0.tar.gz
TREESITTER_SHA256 6403b361b0014999e96f61b9c84d6950d42f0c7d6e806be79382e0232e48a11b

View File

@ -4,6 +4,8 @@ They are used with the ":compiler" command.
These scripts usually set options, for example 'errorformat'.
See ":help write-compiler-plugin".
To undo the effect of a compiler plugin, use the make compiler plugin.
If you want to write your own compiler plugin, have a look at the other files
for how to do it, the format is simple.

View File

@ -0,0 +1,45 @@
" Vim compiler file
" Compiler: Groff
" Maintainer: Konfekt
" Last Change: 2024 Sep 8
"
" Expects output file extension, say `:make html` or `:make pdf`.
" Supported devices as of Sept 2024 are: (x)html, pdf, ps, dvi, lj4, lbp ...
" Adjust command-line flags, language, encoding by buffer-local/global variables
" groff_compiler_args, groff_compiler_lang, and groff_compiler_encoding,
" which default to '', &spelllang and 'utf8'.
if exists("current_compiler")
finish
endif
let s:keepcpo = &cpo
set cpo&vim
let current_compiler = 'groff'
silent! function s:groff_compiler_lang()
let lang = get(b:, 'groff_compiler_lang',
\ &spell ? matchstr(&spelllang, '^\a\a') : '')
if lang ==# 'en' | let lang = '' | endif
return empty(lang) ? '' : '-m'..lang
endfunction
" Requires output format (= device) to be set by user after :make.
execute 'CompilerSet makeprg=groff'..escape(
\ ' '..s:groff_compiler_lang()..
\ ' -K'..get(b:, 'groff_compiler_encoding', get(g:, 'groff_compiler_encoding', 'utf8'))..
\ ' '..get(b:, 'groff_compiler_args', get(g:, 'groff_compiler_args', ''))..
\ ' -mom -T$* -- %:S > %:r:S.$*', ' ')
" From Gavin Freeborn's https://github.com/Gavinok/vim-troff under Vim License
" https://github.com/Gavinok/vim-troff/blob/91017b1423caa80aba541c997909a4f810edd275/compiler/troff.vim#L39
CompilerSet errorformat=%o:<standard\ input>\ (%f):%l:%m,
\%o:\ <standard\ input>\ (%f):%l:%m,
\%o:%f:%l:%m,
\%o:\ %f:%l:%m,
\%f:%l:\ macro\ %trror:%m,
\%f:%l:%m,
\%W%tarning:\ file\ '%f'\\,\ around\ line\ %l:,%Z%m
let &cpo = s:keepcpo
unlet s:keepcpo

13
runtime/compiler/make.vim Normal file
View File

@ -0,0 +1,13 @@
" Vim compiler plugin
"
" Maintainer: The Vim Project <https://github.com/vim/vim>
" Last Change: 2024 Sep 10
" Original Author: Konfekt
"
" This compiler plugin is used to reset previously set compiler options.
if exists("g:current_compiler") | unlet g:current_compiler | endif
if exists("b:current_compiler") | unlet b:current_compiler | endif
CompilerSet makeprg&
CompilerSet errorformat&

View File

@ -1,10 +1,12 @@
" Vim compiler file
" Compiler: Pandoc
" Maintainer: Konfekt
" Last Change: 2024 Aug 20
" Last Change: 2024 Sep 8
"
" Expects output file extension, say `:make html` or `:make pdf`.
" Passes additional arguments to pandoc, say `:make html --self-contained`.
" Adjust command-line flags by buffer-local/global variable
" b/g:pandoc_compiler_args which defaults to empty.
if exists("current_compiler")
finish
@ -40,17 +42,20 @@ silent! function s:PandocFiletype(filetype) abort
endif
endfunction
let b:pandoc_compiler_from = get(b:, 'pandoc_compiler_from', s:PandocFiletype(&filetype))
let b:pandoc_compiler_lang = get(b:, 'pandoc_compiler_lang', &spell ? matchstr(&spelllang, '^\a\a') : '')
silent! function s:PandocLang()
let lang = get(b:, 'pandoc_compiler_lang',
\ &spell ? matchstr(&spelllang, '^\a\a') : '')
if lang ==# 'en' | let lang = '' | endif
return empty(lang) ? '' : '--metadata lang='..lang
endfunction
execute 'CompilerSet makeprg=pandoc'..escape(
\ ' --standalone' .
\ (b:pandoc_compiler_from ==# 'markdown' && (getline(1) =~# '^%\s\+\S\+' || (search('^title:\s+\S+', 'cnw') > 0)) ?
\ '' : ' --metadata title=%:t:r:S') .
\ (empty(b:pandoc_compiler_lang) ?
\ '' : ' --metadata lang='..b:pandoc_compiler_lang) .
\ ' --from='..b:pandoc_compiler_from .
\ ' '..get(b:, 'pandoc_compiler_args', get(g:, 'pandoc_compiler_args', '')) .
\ ' --standalone'..
\ (s:PandocFiletype(&filetype) ==# 'markdown' && (getline(1) =~# '^%\s\+\S\+' || (search('^title:\s+\S+', 'cnw') > 0)) ?
\ '' : ' --metadata title=%:t:r:S')..
\ ' '..s:PandocLang()..
\ ' --from='..s:PandocFiletype(&filetype)..
\ ' '..get(b:, 'pandoc_compiler_args', get(g:, 'pandoc_compiler_args', ''))..
\ ' --output %:r:S.$* -- %:S', ' ')
CompilerSet errorformat=\"%f\",\ line\ %l:\ %m

View File

@ -6201,6 +6201,9 @@ search({pattern} [, {flags} [, {stopline} [, {timeout} [, {skip}]]]]) *search()*
The value must not be negative. A zero value is like not
giving the argument.
Note: the timeout is only considered when searching, not
while evaluating the {skip} expression.
If the {skip} expression is given it is evaluated with the
cursor positioned on the start of a match. If it evaluates to
non-zero this match is skipped. This can be used, for

View File

@ -189,7 +189,8 @@ TREESITTER
TUI
• TODO
• |log| messages written by the builtin UI client (TUI, |--remote-ui|) are
now prefixed with "ui" instead of "?".
UI

View File

@ -1566,10 +1566,7 @@ A jump table for the options with a short description can be found at |Q_op|.
fuzzy Enable |fuzzy-matching| for completion candidates. This
allows for more flexible and intuitive matching, where
characters can be skipped and matches can be found even
if the exact sequence is not typed. Only makes a
difference how completion candidates are reduced from the
list of alternatives, but not how the candidates are
collected (using different completion types).
if the exact sequence is not typed.
*'completeslash'* *'csl'*
'completeslash' 'csl' string (default "")
@ -6713,7 +6710,7 @@ A jump table for the options with a short description can be found at |Q_op|.
global
When on, the title of the window will be set to the value of
'titlestring' (if it is not empty), or to:
filename [+=-] (path) - NVIM
filename [+=-] (path) - Nvim
Where:
filename the name of the file being edited
- indicates the file cannot be modified, 'ma' off
@ -6721,7 +6718,7 @@ A jump table for the options with a short description can be found at |Q_op|.
= indicates the file is read-only
=+ indicates the file is read-only and modified
(path) is the path of the file being edited
- NVIM the server name |v:servername| or "NVIM"
- Nvim the server name |v:servername| or "Nvim"
*'titlelen'*
'titlelen' number (default 85)

View File

@ -1262,6 +1262,7 @@ not "b:current_compiler". What the command actually does is the following:
For writing a compiler plugin, see |write-compiler-plugin|.
Use the |compiler-make| plugin to undo the effect of a compiler plugin.
DOTNET *compiler-dotnet*
@ -1277,7 +1278,6 @@ Example: limit output to only display errors, and suppress the project name: >
let dotnet_show_project_file = v:false
compiler dotnet
<
GCC *quickfix-gcc* *compiler-gcc*
There's one variable you can set for the GCC compiler:
@ -1294,6 +1294,24 @@ Commonly used compiler options can be added to 'makeprg' by setting the
g:javac_makeprg_params variable. For example: >
let g:javac_makeprg_params = "-Xlint:all -encoding utf-8"
<
GNU MAKE *compiler-make*
Since the default make program is "make", the compiler plugin for make,
:compiler make, will reset the 'makeprg' and 'errorformat' option to
the default values and unlet any variables that may have been set by a
previous compiler plugin.
GROFF *quickfix-groff* *compiler-groff*
The GROFF compiler plugin uses the mom macro set (documented in the groff_mom
manpage) as input and expects that the output file type extension is passed to
make, say :make html or :make pdf.
Additional arguments can be passed to groff by setting them in
`b:groff_compiler_args` or `g:groff_compiler_args`. The `language` argument
passed to groff is set using 'spelllang'; it can be overridden by setting
`b:groff_compiler_lang`. The default enconding is `UTF-8` and can be changed
by setting `b:groff_compiler_encoding` or `g:groff_compiler_encoding`.
PANDOC *quickfix-pandoc* *compiler-pandoc*
@ -1307,8 +1325,7 @@ Additional arguments can be passed to pandoc:
The `--from` argument is an educated guess using the buffer file type;
it can be overridden by setting `b:pandoc_compiler_from`.
Likewise the `--metadata lang` argument is set using `&spelllang`;
it can be overridden by setting `b:pandoc_compiler_lang`.
The `--metadata lang` argument is set using 'spelllang';
If `--from=markdown` is assumed and no title set in a title header or
YAML block, then the filename (without extension) is used as the title.

View File

@ -2,8 +2,9 @@
" Filename: spec.vim
" Maintainer: Igor Gnatenko i.gnatenko.brain@gmail.com
" Former Maintainer: Gustavo Niemeyer <niemeyer@conectiva.com> (until March 2014)
" Last Change: Mon Jun 01 21:15 MSK 2015 Igor Gnatenko
" Last Change: 2015 Jun 01
" Update by Zdenek Dohnal, 2022 May 17
" 2024 Sep 10 by Vim Project: add epoch support for spec changelog, #15537
if exists("b:did_ftplugin")
finish
@ -66,9 +67,11 @@ if !exists("*s:SpecChangelog")
endif
let line = 0
let name = ""
let epoch = ""
let ver = ""
let rel = ""
let nameline = -1
let epochline = -1
let verline = -1
let relline = -1
let chgline = -1
@ -77,6 +80,9 @@ if !exists("*s:SpecChangelog")
if name == "" && linestr =~? '^Name:'
let nameline = line
let name = substitute(strpart(linestr,5), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
elseif epoch == "" && linestr =~? '^Epoch:'
let epochline = line
let epoch = substitute(strpart(linestr,6), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
elseif ver == "" && linestr =~? '^Version:'
let verline = line
let ver = substitute(strpart(linestr,8), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
@ -93,6 +99,7 @@ if !exists("*s:SpecChangelog")
if nameline != -1 && verline != -1 && relline != -1
let include_release_info = exists("g:spec_chglog_release_info")
let name = s:ParseRpmVars(name, nameline)
let epoch = s:ParseRpmVars(epoch, epochline)
let ver = s:ParseRpmVars(ver, verline)
let rel = s:ParseRpmVars(rel, relline)
else
@ -117,6 +124,9 @@ if !exists("*s:SpecChangelog")
if chgline != -1
let tmptime = v:lc_time
language time C
if strlen(epoch)
let ver = epoch.":".ver
endif
let parsed_format = "* ".strftime(format)." - ".ver."-".rel
execute "language time" tmptime
let release_info = "+ ".name."-".ver."-".rel

View File

@ -9,8 +9,8 @@
local function get_commentstring(ref_position)
local buf_cs = vim.bo.commentstring
local has_ts_parser, ts_parser = pcall(vim.treesitter.get_parser)
if not has_ts_parser then
local ts_parser = vim.treesitter._get_parser()
if not ts_parser then
return buf_cs
end

View File

@ -213,7 +213,6 @@ end
--- Default menus
do
--- Right click popup menu
local function def_menu(ctx)
vim.cmd([[
anoremenu PopUp.Go\ to\ definition <Cmd>lua vim.lsp.buf.definition()<CR>
amenu PopUp.Open\ in\ web\ browser gx
@ -229,7 +228,10 @@ do
inoremenu PopUp.Select\ All <C-Home><C-O>VG
anoremenu PopUp.-2- <Nop>
anoremenu PopUp.How-to\ disable\ mouse <Cmd>help disable-mouse<CR>
]])
local function enable_ctx_menu(ctx)
vim.cmd([[
amenu disable PopUp.Go\ to\ definition
amenu disable PopUp.Open\ in\ web\ browser
]])
@ -240,7 +242,6 @@ do
vim.cmd([[anoremenu enable PopUp.Go\ to\ definition]])
end
end
def_menu()
local nvim_popupmenu_augroup = vim.api.nvim_create_augroup('nvim_popupmenu', {})
vim.api.nvim_create_autocmd('MenuPopup', {
@ -252,7 +253,7 @@ do
local urls = require('vim.ui')._get_urls()
local url = vim.startswith(urls[1], 'http')
local ctx = url and 'url' or (vim.lsp.get_clients({ bufnr = 0 })[1] and 'lsp' or nil)
def_menu(ctx)
enable_ctx_menu(ctx)
end,
})
end

View File

@ -1090,10 +1090,7 @@ vim.bo.cfu = vim.bo.completefunc
--- fuzzy Enable `fuzzy-matching` for completion candidates. This
--- allows for more flexible and intuitive matching, where
--- characters can be skipped and matches can be found even
--- if the exact sequence is not typed. Only makes a
--- difference how completion candidates are reduced from the
--- list of alternatives, but not how the candidates are
--- collected (using different completion types).
--- if the exact sequence is not typed.
---
--- @type string
vim.o.completeopt = "menu,preview"
@ -7255,7 +7252,7 @@ vim.go.tm = vim.go.timeoutlen
--- When on, the title of the window will be set to the value of
--- 'titlestring' (if it is not empty), or to:
--- filename [+=-] (path) - NVIM
--- filename [+=-] (path) - Nvim
--- Where:
--- filename the name of the file being edited
--- - indicates the file cannot be modified, 'ma' off
@ -7263,7 +7260,7 @@ vim.go.tm = vim.go.timeoutlen
--- = indicates the file is read-only
--- =+ indicates the file is read-only and modified
--- (path) is the path of the file being edited
--- - NVIM the server name `v:servername` or "NVIM"
--- - Nvim the server name `v:servername` or "Nvim"
---
--- @type boolean
vim.o.title = false

View File

@ -7421,6 +7421,9 @@ function vim.fn.screenstring(row, col) end
--- The value must not be negative. A zero value is like not
--- giving the argument.
---
--- Note: the timeout is only considered when searching, not
--- while evaluating the {skip} expression.
---
--- If the {skip} expression is given it is evaluated with the
--- cursor positioned on the start of a match. If it evaluates to
--- non-zero this match is skipped. This can be used, for

View File

@ -1164,6 +1164,7 @@ local extension = {
svelte = 'svelte',
svg = 'svg',
swift = 'swift',
swiftinterface = 'swift',
swig = 'swig',
swg = 'swig',
sys = detect.sys,

View File

@ -285,8 +285,8 @@ local path2name = function(path)
-- Remove everything up to the last /lua/ folder
path = path:gsub('^.*/lua/', '')
-- Remove the filename (health.lua)
path = vim.fs.dirname(path)
-- Remove the filename (health.lua) or (health/init.lua)
path = vim.fs.dirname(path:gsub('/init%.lua$', ''))
-- Change slashes to dots
path = path:gsub('/', '.')

View File

@ -447,11 +447,9 @@ function M.document_symbol(opts)
request_with_opts(ms.textDocument_documentSymbol, params, opts)
end
--- @param call_hierarchy_items lsp.CallHierarchyItem[]?
--- @param call_hierarchy_items lsp.CallHierarchyItem[]
--- @return lsp.CallHierarchyItem?
local function pick_call_hierarchy_item(call_hierarchy_items)
if not call_hierarchy_items then
return
end
if #call_hierarchy_items == 1 then
return call_hierarchy_items[1]
end
@ -476,7 +474,7 @@ local function call_hierarchy(method)
vim.notify(err.message, vim.log.levels.WARN)
return
end
if not result then
if not result or vim.tbl_isempty(result) then
vim.notify('No item resolved', vim.log.levels.WARN)
return
end

View File

@ -43,17 +43,16 @@ function M.on_inlayhint(err, result, ctx, _)
return
end
local bufnr = assert(ctx.bufnr)
if util.buf_versions[bufnr] ~= ctx.version then
if
util.buf_versions[bufnr] ~= ctx.version
or not result
or not api.nvim_buf_is_loaded(bufnr)
or not bufstates[bufnr].enabled
then
return
end
local client_id = ctx.client_id
if not result then
return
end
local bufstate = bufstates[bufnr]
if not bufstate.enabled then
return
end
if not (bufstate.client_hints and bufstate.version) then
bufstate.client_hints = vim.defaulttable()
bufstate.version = ctx.version

View File

@ -154,7 +154,7 @@ end
---@param encoding string utf-8|utf-16|utf-32| defaults to utf-16
---@return integer byte (utf-8) index of `encoding` index `index` in `line`
function M._str_byteindex_enc(line, index, encoding)
local len = vim.fn.strlen(line)
local len = #line
if index > len then
-- LSP spec: if character > line length, default to the line length.
-- https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position
@ -167,7 +167,7 @@ function M._str_byteindex_enc(line, index, encoding)
if index then
return index
else
return #line
return len
end
elseif encoding == 'utf-16' then
return vim.str_byteindex(line, index, true)

View File

@ -74,14 +74,14 @@ end
--- Returns the parser for a specific buffer and attaches it to the buffer
---
--- If needed, this will create the parser.
--- If needed, this will create the parser. If no parser can be found or created, returns `nil`.
---
---@param bufnr (integer|nil) Buffer the parser should be tied to (default: current buffer)
---@param lang (string|nil) Language of this parser (default: from buffer filetype)
---@param opts (table|nil) Options to pass to the created language tree
---
---@return vim.treesitter.LanguageTree object to use for parsing
function M.get_parser(bufnr, lang, opts)
---@return vim.treesitter.LanguageTree? object to use for parsing, or `nil` if not found
function M._get_parser(bufnr, lang, opts)
opts = opts or {}
if bufnr == nil or bufnr == 0 then
@ -94,18 +94,14 @@ function M.get_parser(bufnr, lang, opts)
if not valid_lang(lang) then
if not parsers[bufnr] then
error(
string.format(
'There is no parser available for buffer %d and one could not be'
.. ' created because lang could not be determined. Either pass lang'
.. ' or set the buffer filetype',
bufnr
)
)
return nil
end
elseif parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then
assert(lang, 'lang should be valid')
parsers[bufnr] = M._create_parser(bufnr, lang, opts)
local parser = vim.F.npcall(M._create_parser, bufnr, lang, opts)
if not parser then
return nil
end
parsers[bufnr] = parser
end
parsers[bufnr]:register_cbs(opts.buf_attach_cbs)
@ -113,6 +109,29 @@ function M.get_parser(bufnr, lang, opts)
return parsers[bufnr]
end
--- Returns the parser for a specific buffer and attaches it to the buffer
---
--- If needed, this will create the parser.
---
---@param bufnr (integer|nil) Buffer the parser should be tied to (default: current buffer)
---@param lang (string|nil) Language of this parser (default: from buffer filetype)
---@param opts (table|nil) Options to pass to the created language tree
---
---@return vim.treesitter.LanguageTree object to use for parsing
function M.get_parser(bufnr, lang, opts)
-- TODO(ribru17): Remove _get_parser and move that logic back here once the breaking function
-- signature change is acceptable.
local parser = M._get_parser(bufnr, lang, opts)
if not parser then
vim.notify_once(
'WARNING: vim.treesitter.get_parser will return nil instead of raising an error in Neovim 0.12',
vim.log.levels.WARN
)
error('Parser not found.')
end
return parser
end
--- Returns a string parser
---
---@param str string Text to parse
@ -386,7 +405,7 @@ function M.get_node(opts)
local ts_range = { row, col, row, col }
local root_lang_tree = M.get_parser(bufnr, opts.lang)
local root_lang_tree = M._get_parser(bufnr, opts.lang)
if not root_lang_tree then
return
end
@ -419,7 +438,11 @@ end
---@param lang (string|nil) Language of the parser (default: from buffer filetype)
function M.start(bufnr, lang)
bufnr = bufnr or api.nvim_get_current_buf()
local parser = M.get_parser(bufnr, lang)
local parser = M._get_parser(bufnr, lang)
if not parser then
vim.notify('No parser for the given buffer.', vim.log.levels.WARN)
return
end
M.highlighter.new(parser)
end

View File

@ -114,7 +114,7 @@ local function compute_folds_levels(bufnr, info, srow, erow, parse_injections)
srow = srow or 0
erow = erow or api.nvim_buf_line_count(bufnr)
local parser = ts.get_parser(bufnr)
local parser = assert(ts._get_parser(bufnr))
parser:parse(parse_injections and { srow, erow } or nil)
@ -392,7 +392,7 @@ function M.foldexpr(lnum)
lnum = lnum or vim.v.lnum
local bufnr = api.nvim_get_current_buf()
local parser = vim.F.npcall(ts.get_parser, bufnr)
local parser = ts._get_parser(bufnr)
if not parser then
return '0'
end

View File

@ -172,7 +172,7 @@ function M.lint(buf, opts)
--- @type (table|nil)
local parser_info = vim.F.npcall(vim.treesitter.language.inspect, lang)
local parser = vim.treesitter.get_parser(buf)
local parser = assert(vim.treesitter._get_parser(buf), 'query parser not found.')
parser:parse()
parser:for_each_tree(function(tree, ltree)
if ltree:lang() == 'query' then

View File

@ -76,10 +76,9 @@ end
---
---@package
function TSTreeView:new(bufnr, lang)
local ok, parser = pcall(vim.treesitter.get_parser, bufnr or 0, lang)
if not ok then
local err = parser --[[ @as string ]]
return nil, 'No parser available for the given buffer:\n' .. err
local parser = vim.treesitter._get_parser(bufnr or 0, lang)
if not parser then
return nil, 'No parser available for the given buffer.'
end
-- For each child tree (injected language), find the root of the tree and locate the node within
@ -539,7 +538,7 @@ local edit_ns = api.nvim_create_namespace('treesitter/dev-edit')
local function update_editor_highlights(query_win, base_win, lang)
local base_buf = api.nvim_win_get_buf(base_win)
local query_buf = api.nvim_win_get_buf(query_win)
local parser = vim.treesitter.get_parser(base_buf, lang)
local parser = assert(vim.treesitter._get_parser(base_buf, lang))
api.nvim_buf_clear_namespace(base_buf, edit_ns, 0, -1)
local query_content = table.concat(api.nvim_buf_get_lines(query_buf, 0, -1, false), '\n')
@ -596,8 +595,8 @@ function M.edit_query(lang)
end
vim.cmd(cmd)
local ok, parser = pcall(vim.treesitter.get_parser, buf, lang)
if not ok then
local parser = vim.treesitter._get_parser(buf, lang)
if not parser then
return nil, 'No parser available for the given buffer'
end
lang = parser:lang()

View File

@ -33,7 +33,7 @@ end
--- Show a table of contents for the help buffer in a loclist
function M.show_toc()
local bufnr = vim.api.nvim_get_current_buf()
local parser = vim.treesitter.get_parser(bufnr, 'vimdoc')
local parser = assert(vim.treesitter._get_parser(bufnr, 'vimdoc'), 'vimdoc parser not found.')
local query = vim.treesitter.query.parse(
parser:lang(),
[[

View File

@ -45,6 +45,11 @@
(link_destination) @_url
(#set! @_label url @_url))
(image
(image_description) @_label
(link_destination) @_url
(#set! @_label url @_url))
; Conceal image links
(image
[

View File

@ -33,7 +33,10 @@
")"
] @punctuation.bracket
":" @punctuation.delimiter
[
":"
"/"
] @punctuation.delimiter
[
"@"

View File

@ -1,12 +1,12 @@
" Vim syntax file
" Language: Configuration File (ini file) for MSDOS/MS Windows
" Version: 2.3
" Version: 2.4
" Original Author: Sean M. McKee <mckee@misslink.net>
" Previous Maintainer: Nima Talebi <nima@it.net.au>
" Current Maintainer: Hong Xu <hong@topbug.net>
" Homepage: http://www.vim.org/scripts/script.php?script_id=3747
" Repository: https://github.com/xuhdev/syntax-dosini.vim
" Last Change: 2023 Aug 20
" Last Change: 2024 Sept 08
" quit when a syntax file was already loaded
@ -27,7 +27,7 @@ syn match dosiniNumber "=\zs\s*\d\+\s*$"
syn match dosiniNumber "=\zs\s*\d*\.\d\+\s*$"
syn match dosiniNumber "=\zs\s*\d\+e[+-]\=\d\+\s*$"
syn region dosiniHeader start="^\s*\[" end="\]"
syn match dosiniComment "^[#;].*$"
syn match dosiniComment "^[#;].*$" contains=@Spell
syn region dosiniSection start="\s*\[.*\]" end="\ze\s*\[.*\]" fold
\ contains=dosiniLabel,dosiniValue,dosiniNumber,dosiniHeader,dosiniComment

View File

@ -1,7 +1,8 @@
" Interactive Data Language syntax file (IDL, too [:-)]
" Maintainer: Aleksandar Jelenak <ajelenak AT yahoo.com>
" Last change: 2011 Apr 11
" Created by: Hermann Rochholz <Hermann.Rochholz AT gmx.de>
" Created By: Hermann Rochholz <Hermann.Rochholz AT gmx.de>
" Last Change: 2011 Apr 11
" 2024 Sep 10 by Vim Project: update syntax script, #15419
" Remove any old syntax stuff hanging around
" quit when a syntax file was already loaded
@ -16,7 +17,7 @@ syn match idlangStatement "^\s*function\s"
syn keyword idlangStatement return continue mod do break
syn keyword idlangStatement compile_opt forward_function goto
syn keyword idlangStatement begin common end of
syn keyword idlangStatement inherits on_ioerror begin
syn keyword idlangStatement inherits on_error on_ioerror begin
syn keyword idlangConditional if else then for while case switch
syn keyword idlangConditional endcase endelse endfor endswitch
@ -82,7 +83,7 @@ syn keyword idlangRoutine CALL_EXTERNAL CALL_FUNCTION CALL_METHOD
syn keyword idlangRoutine CALL_PROCEDURE CATCH CD CEIL CHEBYSHEV CHECK_MATH
syn keyword idlangRoutine CHISQR_CVF CHISQR_PDF CHOLDC CHOLSOL CINDGEN
syn keyword idlangRoutine CIR_3PNT CLOSE CLUST_WTS CLUSTER COLOR_CONVERT
syn keyword idlangRoutine COLOR_QUAN COLORMAP_APPLICABLE COMFIT COMMON
syn keyword idlangRoutine COLOR_QUAN COLORMAP_APPLICABLE COMFIT
syn keyword idlangRoutine COMPLEX COMPLEXARR COMPLEXROUND
syn keyword idlangRoutine COMPUTE_MESH_NORMALS COND CONGRID CONJ
syn keyword idlangRoutine CONSTRAINED_MIN CONTOUR CONVERT_COORD CONVOL
@ -98,7 +99,7 @@ syn keyword idlangRoutine CW_PALETTE_EDITOR_GET CW_PALETTE_EDITOR_SET
syn keyword idlangRoutine CW_PDMENU CW_RGBSLIDER CW_TMPL CW_ZOOM DBLARR
syn keyword idlangRoutine DCINDGEN DCOMPLEX DCOMPLEXARR DEFINE_KEY DEFROI
syn keyword idlangRoutine DEFSYSV DELETE_SYMBOL DELLOG DELVAR DERIV DERIVSIG
syn keyword idlangRoutine DETERM DEVICE DFPMIN DIALOG_MESSAGE
syn keyword idlangRoutine DETERM DEVICE DFPMIN DIAG_MATRIX DIALOG_MESSAGE
syn keyword idlangRoutine DIALOG_PICKFILE DIALOG_PRINTERSETUP
syn keyword idlangRoutine DIALOG_PRINTJOB DIALOG_READ_IMAGE
syn keyword idlangRoutine DIALOG_WRITE_IMAGE DIGITAL_FILTER DILATE DINDGEN
@ -155,7 +156,7 @@ syn keyword idlangRoutine MPEG_PUT MPEG_SAVE MSG_CAT_CLOSE MSG_CAT_COMPILE
syn keyword idlangRoutine MSG_CAT_OPEN MULTI N_ELEMENTS N_PARAMS N_TAGS
syn keyword idlangRoutine NEWTON NORM OBJ_CLASS OBJ_DESTROY OBJ_ISA OBJ_NEW
syn keyword idlangRoutine OBJ_VALID OBJARR ON_ERROR ON_IOERROR ONLINE_HELP
syn keyword idlangRoutine OPEN OPENR OPENW OPLOT OPLOTERR P_CORRELATE
syn keyword idlangRoutine OPEN OPENR OPENW OPENU OPLOT OPLOTERR P_CORRELATE
syn keyword idlangRoutine PARTICLE_TRACE PCOMP PLOT PLOT_3DBOX PLOT_FIELD
syn keyword idlangRoutine PLOTERR PLOTS PNT_LINE POINT_LUN POLAR_CONTOUR
syn keyword idlangRoutine POLAR_SURFACE POLY POLY_2D POLY_AREA POLY_FIT

View File

@ -3,7 +3,7 @@
" Maintainer: Aliaksei Budavei <0x000c70 AT gmail DOT com>
" Former Maintainer: Claudio Fleiner <claudio@fleiner.com>
" Repository: https://github.com/zzzyxwvut/java-vim.git
" Last Change: 2024 Aug 26
" Last Change: 2024 Sep 10
" Please check :help java.vim for comments on some of the options available.
@ -157,13 +157,20 @@ endif
" testing in a project without attendant confusion for IDEs, with the
" ".java\=" extension used for a production version and an arbitrary
" extension used for a testing version.
if fnamemodify(bufname("%"), ":t") =~ '^module-info\%(\.class\>\)\@!'
if fnamemodify(bufname("%"), ":t") =~ '^module-info\>\%(\.class\>\)\@!'
syn keyword javaModuleStorageClass module transitive
syn keyword javaModuleStmt open requires exports opens uses provides
syn keyword javaModuleExternal to with
hi def link javaModuleStorageClass StorageClass
hi def link javaModuleStmt Statement
hi def link javaModuleExternal Include
if !exists("g:java_ignore_javadoc") && g:main_syntax != 'jsp'
syn match javaDocProvidesTag contained "@provides\_s\+\S\+" contains=javaDocParam
syn match javaDocUsesTag contained "@uses\_s\+\S\+" contains=javaDocParam
hi def link javaDocProvidesTag Special
hi def link javaDocUsesTag Special
endif
endif
" Fancy parameterised types (JLS-17, §4.5).
@ -335,29 +342,99 @@ if !exists("g:java_ignore_javadoc") && g:main_syntax != 'jsp'
call s:ReportOnce(v:exception)
endtry
syn region javaDocComment start="/\*\*" end="\*/" keepend contains=javaCommentTitle,@javaHtml,javaDocTags,javaDocSeeTag,javaDocCodeTag,javaDocSnippetTag,javaTodo,javaCommentError,javaSpaceError,@Spell fold
exec 'syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*" matchgroup=javaCommentTitle end="\.$" end="\.[ \t\r]\@=" end="\%(^\s*\**\s*\)\@' . s:ff.Peek('80', '') . '<=@"me=s-2,he=s-1 end="\*/"me=s-1,he=s-1 contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,javaDocTags,javaDocSeeTag,javaDocCodeTag,javaDocSnippetTag'
syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*\s*\r\=\n\=\s*\**\s*\%({@return\>\)\@=" matchgroup=javaCommentTitle end="}\%(\s*\.*\)*" contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,javaDocTags,javaDocSeeTag,javaDocCodeTag,javaDocSnippetTag
syn region javaDocTags contained start="{@\%(li\%(teral\|nk\%(plain\)\=\)\|inherit[Dd]oc\|doc[rR]oot\|value\)\>" end="}"
syn match javaDocTags contained "@\%(param\|exception\|throws\|since\)\s\+\S\+" contains=javaDocParam
syn match javaDocParam contained "\s\S\+"
syn match javaDocTags contained "@\%(version\|author\|return\|deprecated\|serial\%(Field\|Data\)\=\)\>"
syn region javaDocSeeTag contained matchgroup=javaDocTags start="@see\s\+" matchgroup=NONE end="\_."re=e-1 contains=javaDocSeeTagParam
syn match javaDocSeeTagParam contained @"\_[^"]\+"\|<a\s\+\_.\{-}</a>\|\%(\k\|\.\)*\%(#\k\+\%((\_[^)]*)\)\=\)\=@ contains=@javaHtml extend
syn region javaDocComment start="/\*\*" end="\*/" keepend contains=javaCommentTitle,@javaHtml,@javaDocTags,javaTodo,javaCommentError,javaSpaceError,@Spell fold
exec 'syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*" matchgroup=javaCommentTitle end="\.$" end="\.[ \t\r]\@=" end="\%(^\s*\**\s*\)\@' . s:ff.Peek('80', '') . '<=@"me=s-2,he=s-1 end="\*/"me=s-1,he=s-1 contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,@javaDocTags'
syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*\s*\r\=\n\=\s*\**\s*\%({@return\>\)\@=" matchgroup=javaCommentTitle end="}\%(\s*\.*\)*" contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,@javaDocTags,javaTitleSkipBlock
syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*\s*\r\=\n\=\s*\**\s*\%({@summary\>\)\@=" matchgroup=javaCommentTitle end="}" contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,@javaDocTags,javaTitleSkipBlock
" The members of javaDocTags are sub-grouped according to the Java
" version of their introduction, and sub-group members in turn are
" arranged in alphabetical order, so that future newer members can
" be pre-sorted and appended without disturbing the current member
" placement.
" Since they only have significance in javaCommentTitle, neither
" javaDocSummaryTag nor javaDocReturnTitleTag are defined.
syn cluster javaDocTags contains=javaDocAuthorTag,javaDocDeprecatedTag,javaDocExceptionTag,javaDocParamTag,javaDocReturnTag,javaDocSeeTag,javaDocVersionTag,javaDocSinceTag,javaDocLinkTag,javaDocSerialTag,javaDocSerialDataTag,javaDocSerialFieldTag,javaDocThrowsTag,javaDocDocRootTag,javaDocInheritDocTag,javaDocLinkplainTag,javaDocValueTag,javaDocCodeTag,javaDocLiteralTag,javaDocHiddenTag,javaDocIndexTag,javaDocProvidesTag,javaDocUsesTag,javaDocSystemPropertyTag,javaDocSnippetTag,javaDocSpecTag
" Anticipate non-standard inline tags in {@return} and {@summary}.
syn region javaTitleSkipBlock contained transparent start="{\%(@\%(return\|summary\)\>\)\@!" end="}"
syn match javaDocDocRootTag contained "{@docRoot}"
syn match javaDocInheritDocTag contained "{@inheritDoc}"
syn region javaIndexSkipBlock contained transparent start="{\%(@index\>\)\@!" end="}" contains=javaIndexSkipBlock,javaDocIndexTag
syn region javaDocIndexTag contained start="{@index\>" end="}" contains=javaDocIndexTag,javaIndexSkipBlock
syn region javaLinkSkipBlock contained transparent start="{\%(@link\>\)\@!" end="}" contains=javaLinkSkipBlock,javaDocLinkTag
syn region javaDocLinkTag contained start="{@link\>" end="}" contains=javaDocLinkTag,javaLinkSkipBlock
syn region javaLinkplainSkipBlock contained transparent start="{\%(@linkplain\>\)\@!" end="}" contains=javaLinkplainSkipBlock,javaDocLinkplainTag
syn region javaDocLinkplainTag contained start="{@linkplain\>" end="}" contains=javaDocLinkplainTag,javaLinkplainSkipBlock
syn region javaLiteralSkipBlock contained transparent start="{\%(@literal\>\)\@!" end="}" contains=javaLiteralSkipBlock,javaDocLiteralTag
syn region javaDocLiteralTag contained start="{@literal\>" end="}" contains=javaDocLiteralTag,javaLiteralSkipBlock
syn region javaSystemPropertySkipBlock contained transparent start="{\%(@systemProperty\>\)\@!" end="}" contains=javaSystemPropertySkipBlock,javaDocSystemPropertyTag
syn region javaDocSystemPropertyTag contained start="{@systemProperty\>" end="}" contains=javaDocSystemPropertyTag,javaSystemPropertySkipBlock
syn region javaValueSkipBlock contained transparent start="{\%(@value\>\)\@!" end="}" contains=javaValueSkipBlock,javaDocValueTag
syn region javaDocValueTag contained start="{@value\>" end="}" contains=javaDocValueTag,javaValueSkipBlock
syn match javaDocParam contained "\s\zs\S\+"
syn match javaDocExceptionTag contained "@exception\s\+\S\+" contains=javaDocParam
syn match javaDocParamTag contained "@param\s\+\S\+" contains=javaDocParam
syn match javaDocSinceTag contained "@since\s\+\S\+" contains=javaDocParam
syn match javaDocThrowsTag contained "@throws\s\+\S\+" contains=javaDocParam
syn match javaDocSpecTag contained "@spec\_s\+\S\+\ze\_s\+\S\+" contains=javaDocParam
syn match javaDocAuthorTag contained "@author\>"
syn match javaDocDeprecatedTag contained "@deprecated\>"
syn match javaDocHiddenTag contained "@hidden\>"
syn match javaDocReturnTag contained "@return\>"
syn match javaDocSerialTag contained "@serial\>"
syn match javaDocSerialDataTag contained "@serialData\>"
syn match javaDocSerialFieldTag contained "@serialField\>"
syn match javaDocVersionTag contained "@version\>"
syn match javaDocSeeTag contained "@see\>" nextgroup=javaDocSeeTag1,javaDocSeeTag2,javaDocSeeTag3,javaDocSeeTagStar skipwhite skipempty
syn match javaDocSeeTagStar contained "^\s*\*\+\%(\s*{\=@\|/\|$\)\@!" nextgroup=javaDocSeeTag1,javaDocSeeTag2,javaDocSeeTag3 skipwhite skipempty
syn match javaDocSeeTag1 contained @"\_[^"]\+"@
syn match javaDocSeeTag2 contained @<a\s\+\_.\{-}</a>@ contains=@javaHtml extend
syn match javaDocSeeTag3 contained @["< \t]\@!\%(\k\|[/.]\)*\%(##\=\k\+\%((\_[^)]*)\)\=\)\=@ nextgroup=javaDocSeeTag3Label skipwhite skipempty
syn match javaDocSeeTag3Label contained @\k\%(\k\+\s*\)*$@
syn region javaCodeSkipBlock contained transparent start="{\%(@code\>\)\@!" end="}" contains=javaCodeSkipBlock,javaDocCodeTag
syn region javaDocCodeTag contained start="{@code\>" end="}" contains=javaDocCodeTag,javaCodeSkipBlock
exec 'syn region javaDocSnippetTagAttr contained transparent matchgroup=javaHtmlArg start=/\<\%(class\|file\|id\|lang\|region\)\%(\s*=\)\@=/ matchgroup=javaHtmlString end=/:$/ end=/\%(=\s*\)\@' . s:ff.Peek('80', '') . '<=\%("[^"]\+"\|' . "\x27[^\x27]\\+\x27" . '\|\%([.\\/-]\|\k\)\+\)/ nextgroup=javaDocSnippetTagAttr skipwhite skipnl'
syn region javaSnippetSkipBlock contained transparent start="{\%(@snippet\>\)\@!" end="}" contains=javaSnippetSkipBlock,javaDocSnippetTag,javaCommentMarkupTag
syn region javaDocSnippetTag contained start="{@snippet\>" end="}" contains=javaDocSnippetTag,javaSnippetSkipBlock,javaDocSnippetTagAttr,javaCommentMarkupTag
syntax case match
hi def link javaDocComment Comment
hi def link javaDocSeeTagStar javaDocComment
hi def link javaCommentTitle SpecialComment
hi def link javaDocTags Special
hi def link javaDocCodeTag Special
hi def link javaDocSnippetTag Special
hi def link javaDocSeeTagParam Function
hi def link javaDocParam Function
hi def link javaDocAuthorTag Special
hi def link javaDocCodeTag Special
hi def link javaDocDeprecatedTag Special
hi def link javaDocDocRootTag Special
hi def link javaDocExceptionTag Special
hi def link javaDocHiddenTag Special
hi def link javaDocIndexTag Special
hi def link javaDocInheritDocTag Special
hi def link javaDocLinkTag Special
hi def link javaDocLinkplainTag Special
hi def link javaDocLiteralTag Special
hi def link javaDocParamTag Special
hi def link javaDocReturnTag Special
hi def link javaDocSeeTag Special
hi def link javaDocSeeTag1 String
hi def link javaDocSeeTag2 Special
hi def link javaDocSeeTag3 Function
hi def link javaDocSerialTag Special
hi def link javaDocSerialDataTag Special
hi def link javaDocSerialFieldTag Special
hi def link javaDocSinceTag Special
hi def link javaDocSnippetTag Special
hi def link javaDocSpecTag Special
hi def link javaDocSystemPropertyTag Special
hi def link javaDocThrowsTag Special
hi def link javaDocValueTag Special
hi def link javaDocVersionTag Special
endif
" match the special comment /**/

View File

@ -4,6 +4,7 @@
" Maintainer: Igor Gnatenko i.gnatenko.brain@gmail.com
" Former Maintainer: Donovan Rebbechi elflord@panix.com (until March 2014)
" Last Change: 2020 May 25
" 2024 Sep 10 by Vim Project: add file triggers support, #15569
" quit when a syntax file was already loaded
if exists("b:current_syntax")
@ -111,7 +112,7 @@ syn region specDescriptionArea matchgroup=specSection start='^%description' end=
syn region specPackageArea matchgroup=specSection start='^%package' end='^%'me=e-1 contains=specPackageOpts,specPreAmble,specComment
"%% Scripts Section %%
syn region specScriptArea matchgroup=specSection start='^%\(prep\|generate_buildrequires\|conf\|build\|install\|clean\|check\|pre\|postun\|preun\|post\|posttrans\)\>' skip='^%{\|^%\(define\|patch\d*\|configure\|GNUconfigure\|setup\|autosetup\|autopatch\|find_lang\|make_build\|makeinstall\|make_install\)\>' end='^%'me=e-1 contains=specSpecialVariables,specVariables,@specCommands,specVariables,shDo,shFor,shCaseEsac,specNoNumberHilite,specCommandOpts,shComment,shIf,specSpecialChar,specMacroIdentifier,specSectionMacroArea,specSectionMacroBracketArea,shOperator,shQuote1,shQuote2
syn region specScriptArea matchgroup=specSection start='^%\(prep\|generate_buildrequires\|conf\|build\|install\|clean\|check\|pre\|postun\|preun\|post\|posttrans\|filetriggerin\|filetriggerun\|filetriggerpostun\|transfiletriggerin\|transfiletriggerun\|transfiletriggerpostun\)\>' skip='^%{\|^%\(define\|patch\d*\|configure\|GNUconfigure\|setup\|autosetup\|autopatch\|find_lang\|make_build\|makeinstall\|make_install\)\>' end='^%'me=e-1 contains=specSpecialVariables,specVariables,@specCommands,specVariables,shDo,shFor,shCaseEsac,specNoNumberHilite,specCommandOpts,shComment,shIf,specSpecialChar,specMacroIdentifier,specSectionMacroArea,specSectionMacroBracketArea,shOperator,shQuote1,shQuote2
"%% Changelog Section %%
syn region specChangelogArea matchgroup=specSection start='^%changelog' end='^%'me=e-1 contains=specEmail,specURL,specWeekday,specMonth,specNumber,specComment,specLicense

View File

@ -685,7 +685,7 @@ if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_novimfunctionerror")
syn match vimBufnrWarn /\<bufnr\s*(\s*["']\.['"]\s*)/
endif
syn match vimNotFunc "\<if\>\|\<el\%[seif]\>\|\<retu\%[rn]\>\|\<while\>" skipwhite nextgroup=vimOper,vimOperParen,vimVar,vimFunc,vimNotation
syn match vimNotFunc "\<if\>\|\<el\%[seif]\>\|\<retu\%[rn]\>\|\<while\>" skipwhite nextgroup=@vimExprList,vimNotation
" Match: {{{2
" =====

View File

@ -81,6 +81,14 @@ local function get_dependency(dependency_name)
repo = 'luvit/luv',
symbol = 'LUV',
},
['unibilium'] = {
repo = 'neovim/unibilium',
symbol = 'UNIBILIUM',
},
['utf8proc'] = {
repo = 'JuliaStrings/utf8proc',
symbol = 'UTF8PROC',
},
['tree-sitter'] = {
repo = 'tree-sitter/tree-sitter',
symbol = 'TREESITTER',
@ -90,11 +98,11 @@ local function get_dependency(dependency_name)
symbol = 'TREESITTER_C',
},
['tree-sitter-lua'] = {
repo = 'MunifTanjim/tree-sitter-lua',
repo = 'tree-sitter-grammars/tree-sitter-lua',
symbol = 'TREESITTER_LUA',
},
['tree-sitter-vim'] = {
repo = 'neovim/tree-sitter-vim',
repo = 'tree-sitter-grammars/tree-sitter-vim',
symbol = 'TREESITTER_VIM',
},
['tree-sitter-vimdoc'] = {
@ -102,9 +110,21 @@ local function get_dependency(dependency_name)
symbol = 'TREESITTER_VIMDOC',
},
['tree-sitter-query'] = {
repo = 'nvim-treesitter/tree-sitter-query',
repo = 'tree-sitter-grammars/tree-sitter-query',
symbol = 'TREESITTER_QUERY',
},
['tree-sitter-markdown'] = {
repo = 'tree-sitter-grammars/tree-sitter-markdown',
symbol = 'TREESITTER_MARKDOWN',
},
['wasmtime'] = {
repo = 'bytecodealliance/wasmtime',
symbol = 'WASMTIME',
},
['uncrustify'] = {
repo = 'uncrustify/uncrustify',
symbol = 'UNCRUSTIFY',
},
}
local dependency = dependency_table[dependency_name]
if dependency == nil then

View File

@ -786,7 +786,7 @@ local function parse_buf(fname, parser_path)
if parser_path then
vim.treesitter.language.add('vimdoc', { path = parser_path })
end
local lang_tree = vim.treesitter.get_parser(buf)
local lang_tree = assert(vim.treesitter._get_parser(buf), 'vimdoc parser not found.')
return lang_tree, buf
end

View File

@ -10,7 +10,7 @@
Memcheck:Leak
fun:malloc
fun:uv_spawn
fun:libuv_process_spawn
fun:process_spawn
fun:libuv_proc_spawn
fun:proc_spawn
fun:job_start
}

View File

@ -848,7 +848,7 @@ def CheckIncludes(filename, lines, error):
or filename.endswith('.in.h')
or FileInfo(filename).RelativePath() in {
'func_attr.h',
'os/pty_process.h',
'os/pty_proc.h',
}):
return
@ -869,7 +869,7 @@ def CheckIncludes(filename, lines, error):
"src/nvim/msgpack_rpc/unpacker.h",
"src/nvim/option.h",
"src/nvim/os/pty_conpty_win.h",
"src/nvim/os/pty_process_win.h",
"src/nvim/os/pty_proc_win.h",
]
skip_headers = [

View File

@ -417,10 +417,10 @@ list(SORT NVIM_HEADERS)
foreach(sfile ${NVIM_SOURCES})
get_filename_component(f ${sfile} NAME)
if(WIN32 AND ${f} MATCHES "^(pty_process_unix.c)$")
if(WIN32 AND ${f} MATCHES "^(pty_proc_unix.c)$")
list(REMOVE_ITEM NVIM_SOURCES ${sfile})
endif()
if(NOT WIN32 AND ${f} MATCHES "^(pty_process_win.c)$")
if(NOT WIN32 AND ${f} MATCHES "^(pty_proc_win.c)$")
list(REMOVE_ITEM NVIM_SOURCES ${sfile})
endif()
if(NOT WIN32 AND ${f} MATCHES "^(pty_conpty_win.c)$")
@ -436,7 +436,7 @@ foreach(hfile ${NVIM_HEADERS})
if(WIN32 AND ${f} MATCHES "^(unix_defs.h)$")
list(REMOVE_ITEM NVIM_HEADERS ${hfile})
endif()
if(WIN32 AND ${f} MATCHES "^(pty_process_unix.h)$")
if(WIN32 AND ${f} MATCHES "^(pty_proc_unix.h)$")
list(REMOVE_ITEM NVIM_HEADERS ${hfile})
endif()
if(NOT WIN32 AND ${f} MATCHES "^(win_defs.h)$")
@ -832,12 +832,12 @@ find_program(CLANG_TIDY_PRG clang-tidy)
set(EXCLUDE_CLANG_TIDY typval_encode.c.h ui_events.in.h)
if(WIN32)
list(APPEND EXCLUDE_CLANG_TIDY
os/pty_process_unix.h
os/pty_proc_unix.h
os/unix_defs.h)
else()
list(APPEND EXCLUDE_CLANG_TIDY
os/win_defs.h
os/pty_process_win.h
os/pty_proc_win.h
os/pty_conpty_win.h
os/os_win_console.h)
endif()

View File

@ -70,7 +70,7 @@
#include "nvim/optionstr.h"
#include "nvim/os/input.h"
#include "nvim/os/os_defs.h"
#include "nvim/os/process.h"
#include "nvim/os/proc.h"
#include "nvim/popupmenu.h"
#include "nvim/pos_defs.h"
#include "nvim/runtime.h"

View File

@ -3338,7 +3338,7 @@ void maketitle(void)
#define SPACE_FOR_FNAME (sizeof(buf) - 100)
#define SPACE_FOR_DIR (sizeof(buf) - 20)
#define SPACE_FOR_ARGNR (sizeof(buf) - 10) // At least room for " - NVIM".
#define SPACE_FOR_ARGNR (sizeof(buf) - 10) // At least room for " - Nvim".
char *buf_p = buf;
if (curbuf->b_fname == NULL) {
const size_t size = xstrlcpy(buf_p, _("[No Name]"),
@ -3412,7 +3412,7 @@ void maketitle(void)
append_arg_number(curwin, buf_p, (int)(SPACE_FOR_ARGNR - (size_t)(buf_p - buf)));
xstrlcat(buf_p, " - NVIM", (sizeof(buf) - (size_t)(buf_p - buf)));
xstrlcat(buf_p, " - Nvim", (sizeof(buf) - (size_t)(buf_p - buf)));
if (maxlen > 0) {
// Make it shorter by removing a bit in the middle.

View File

@ -19,7 +19,7 @@
#include "nvim/eval/typval.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/process.h"
#include "nvim/event/proc.h"
#include "nvim/event/rstream.h"
#include "nvim/event/socket.h"
#include "nvim/event/stream.h"
@ -88,7 +88,7 @@ void channel_free_all_mem(void)
bool channel_close(uint64_t id, ChannelPart part, const char **error)
{
Channel *chan;
Process *proc;
Proc *proc;
const char *dummy;
if (!error) {
@ -139,8 +139,8 @@ bool channel_close(uint64_t id, ChannelPart part, const char **error)
if (part == kChannelPartStderr || part == kChannelPartAll) {
rstream_may_close(&proc->err);
}
if (proc->type == kProcessTypePty && part == kChannelPartAll) {
pty_process_close_master(&chan->stream.pty);
if (proc->type == kProcTypePty && part == kChannelPartAll) {
pty_proc_close_master(&chan->stream.pty);
}
break;
@ -289,7 +289,7 @@ static void channel_destroy(Channel *chan)
}
if (chan->streamtype == kChannelStreamProc) {
process_free(&chan->stream.proc);
proc_free(&chan->stream.proc);
}
callback_reader_free(&chan->on_data);
@ -376,7 +376,7 @@ Channel *channel_job_start(char **argv, const char *exepath, CallbackReader on_s
*status_out = 0;
return NULL;
}
chan->stream.pty = pty_process_init(&main_loop, chan);
chan->stream.pty = pty_proc_init(&main_loop, chan);
if (pty_width > 0) {
chan->stream.pty.width = pty_width;
}
@ -384,22 +384,22 @@ Channel *channel_job_start(char **argv, const char *exepath, CallbackReader on_s
chan->stream.pty.height = pty_height;
}
} else {
chan->stream.uv = libuv_process_init(&main_loop, chan);
chan->stream.uv = libuv_proc_init(&main_loop, chan);
}
Process *proc = &chan->stream.proc;
Proc *proc = &chan->stream.proc;
proc->argv = argv;
proc->exepath = exepath;
proc->cb = channel_process_exit_cb;
proc->cb = channel_proc_exit_cb;
proc->events = chan->events;
proc->detach = detach;
proc->cwd = cwd;
proc->env = env;
proc->overlapped = overlapped;
char *cmd = xstrdup(process_get_exepath(proc));
char *cmd = xstrdup(proc_get_exepath(proc));
bool has_out, has_err;
if (proc->type == kProcessTypePty) {
if (proc->type == kProcTypePty) {
has_out = true;
has_err = false;
} else {
@ -410,7 +410,7 @@ Channel *channel_job_start(char **argv, const char *exepath, CallbackReader on_s
bool has_in = stdin_mode == kChannelStdinPipe;
int status = process_spawn(proc, has_in, has_out, has_err);
int status = proc_spawn(proc, has_in, has_out, has_err);
if (status) {
semsg(_(e_jobspawn), os_strerror(status), cmd);
xfree(cmd);
@ -760,7 +760,7 @@ void channel_reader_callbacks(Channel *chan, CallbackReader *reader)
}
}
static void channel_process_exit_cb(Process *proc, int status, void *data)
static void channel_proc_exit_cb(Proc *proc, int status, void *data)
{
Channel *chan = data;
if (chan->term) {
@ -847,7 +847,7 @@ static void term_write(const char *buf, size_t size, void *data)
static void term_resize(uint16_t width, uint16_t height, void *data)
{
Channel *chan = data;
pty_process_resize(&chan->stream.pty, width, height);
pty_proc_resize(&chan->stream.pty, width, height);
}
static inline void term_delayed_free(void **argv)
@ -867,7 +867,7 @@ static inline void term_delayed_free(void **argv)
static void term_close(void *data)
{
Channel *chan = data;
process_stop(&chan->stream.proc);
proc_stop(&chan->stream.proc);
multiqueue_put(chan->events, term_delayed_free, data);
}
@ -907,7 +907,7 @@ bool channel_job_running(uint64_t id)
Channel *chan = find_channel(id);
return (chan
&& chan->streamtype == kChannelStreamProc
&& !process_is_stopped(&chan->stream.proc));
&& !proc_is_stopped(&chan->stream.proc));
}
Dictionary channel_info(uint64_t id, Arena *arena)
@ -924,8 +924,8 @@ Dictionary channel_info(uint64_t id, Arena *arena)
switch (chan->streamtype) {
case kChannelStreamProc: {
stream_desc = "job";
if (chan->stream.proc.type == kProcessTypePty) {
const char *name = pty_process_tty_name(&chan->stream.pty);
if (chan->stream.proc.type == kProcTypePty) {
const char *name = pty_proc_tty_name(&chan->stream.pty);
PUT_C(info, "pty", CSTR_TO_ARENA_OBJ(arena, name));
}

View File

@ -7,11 +7,11 @@
#include "nvim/channel_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h"
#include "nvim/event/defs.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/libuv_proc.h"
#include "nvim/macros_defs.h"
#include "nvim/map_defs.h"
#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/os/pty_process.h"
#include "nvim/os/pty_proc.h"
#include "nvim/types_defs.h"
struct Channel {
@ -21,9 +21,9 @@ struct Channel {
ChannelStreamType streamtype;
union {
Process proc;
LibuvProcess uv;
PtyProcess pty;
Proc proc;
LibuvProc uv;
PtyProc pty;
RStream socket;
StdioPair stdio;
StderrState err;

View File

@ -170,28 +170,26 @@ static void margin_columns_win(win_T *wp, int *left_col, int *right_col)
// cache previous calculations depending on w_virtcol
static int saved_w_virtcol;
static win_T *prev_wp;
static int prev_width1;
static int prev_width2;
static int prev_left_col;
static int prev_right_col;
static int prev_col_off;
int cur_col_off = win_col_off(wp);
int width1;
int width2;
int width1 = wp->w_width_inner - cur_col_off;
int width2 = width1 + win_col_off2(wp);
if (saved_w_virtcol == wp->w_virtcol && prev_wp == wp
&& prev_col_off == cur_col_off) {
&& prev_width1 == width1 && prev_width2 == width2) {
*right_col = prev_right_col;
*left_col = prev_left_col;
return;
}
width1 = wp->w_width_inner - cur_col_off;
width2 = width1 + win_col_off2(wp);
*left_col = 0;
*right_col = width1;
if (wp->w_virtcol >= (colnr_T)width1) {
if (wp->w_virtcol >= (colnr_T)width1 && width2 > 0) {
*right_col = width1 + ((wp->w_virtcol - width1) / width2 + 1) * width2;
}
if (wp->w_virtcol >= (colnr_T)width1 && width2 > 0) {
@ -202,8 +200,9 @@ static void margin_columns_win(win_T *wp, int *left_col, int *right_col)
prev_left_col = *left_col;
prev_right_col = *right_col;
prev_wp = wp;
prev_width1 = width1;
prev_width2 = width2;
saved_w_virtcol = wp->w_virtcol;
prev_col_off = cur_col_off;
}
/// Put a single char from an UTF-8 buffer into a line buffer.

View File

@ -32,7 +32,7 @@
#include "nvim/eval/vars.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/process.h"
#include "nvim/event/proc.h"
#include "nvim/event/time.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_docmd.h"
@ -8506,7 +8506,7 @@ Channel *find_job(uint64_t id, bool show_error)
{
Channel *data = find_channel(id);
if (!data || data->streamtype != kChannelStreamProc
|| process_is_stopped(&data->stream.proc)) {
|| proc_is_stopped(&data->stream.proc)) {
if (show_error) {
if (data && data->streamtype != kChannelStreamProc) {
emsg(_(e_invchanjob));

View File

@ -8927,6 +8927,9 @@ M.funcs = {
The value must not be negative. A zero value is like not
giving the argument.
Note: the timeout is only considered when searching, not
while evaluating the {skip} expression.
If the {skip} expression is given it is evaluated with the
cursor positioned on the start of a match. If it evaluates to
non-zero this match is skipped. This can be used, for

View File

@ -49,7 +49,7 @@
#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/process.h"
#include "nvim/event/proc.h"
#include "nvim/event/time.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds_defs.h"
@ -101,7 +101,7 @@
#include "nvim/os/fs.h"
#include "nvim/os/os.h"
#include "nvim/os/os_defs.h"
#include "nvim/os/pty_process.h"
#include "nvim/os/pty_proc.h"
#include "nvim/os/shell.h"
#include "nvim/os/stdpaths_defs.h"
#include "nvim/os/time.h"
@ -3770,7 +3770,7 @@ static void f_jobpid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
Process *proc = &data->stream.proc;
Proc *proc = &data->stream.proc;
rettv->vval.v_number = proc->pid;
}
@ -3796,12 +3796,12 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
if (data->stream.proc.type != kProcessTypePty) {
if (data->stream.proc.type != kProcTypePty) {
emsg(_(e_channotpty));
return;
}
pty_process_resize(&data->stream.pty, (uint16_t)argvars[1].vval.v_number,
pty_proc_resize(&data->stream.pty, (uint16_t)argvars[1].vval.v_number,
(uint16_t)argvars[2].vval.v_number);
rettv->vval.v_number = 1;
}
@ -4077,7 +4077,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
// Ignore return code, but show error later.
channel_close(data->id, kChannelPartRpc, &error);
}
process_stop(&data->stream.proc);
proc_stop(&data->stream.proc);
rettv->vval.v_number = 1;
if (error) {
emsg(error);
@ -4113,10 +4113,10 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|| !(chan = find_channel((uint64_t)TV_LIST_ITEM_TV(arg)->vval.v_number))
|| chan->streamtype != kChannelStreamProc) {
jobs[i] = NULL; // Invalid job.
} else if (process_is_stopped(&chan->stream.proc)) {
} else if (proc_is_stopped(&chan->stream.proc)) {
// Job is stopped but not fully destroyed.
// Ensure all callbacks on its event queue are executed. #15402
process_wait(&chan->stream.proc, -1, NULL);
proc_wait(&chan->stream.proc, -1, NULL);
jobs[i] = NULL; // Invalid job.
} else {
jobs[i] = chan;
@ -4144,7 +4144,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (jobs[i] == NULL) {
continue; // Invalid job, will assign status=-3 below.
}
int status = process_wait(&jobs[i]->stream.proc, remaining,
int status = proc_wait(&jobs[i]->stream.proc, remaining,
waiting_jobs);
if (status < 0) {
break; // Interrupted (CTRL-C) or timeout, skip remaining jobs.
@ -8207,7 +8207,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
int pid = chan->stream.pty.process.pid;
int pid = chan->stream.pty.proc.pid;
// "./…" => "/home/foo/…"
vim_FullName(cwd, NameBuff, sizeof(NameBuff), false);

View File

@ -142,30 +142,31 @@ struct socket_watcher {
};
typedef enum {
kProcessTypeUv,
kProcessTypePty,
} ProcessType;
kProcTypeUv,
kProcTypePty,
} ProcType;
typedef struct process Process;
typedef void (*process_exit_cb)(Process *proc, int status, void *data);
typedef void (*internal_process_cb)(Process *proc);
/// OS process
typedef struct proc Proc;
typedef void (*proc_exit_cb)(Proc *proc, int status, void *data);
typedef void (*internal_proc_cb)(Proc *proc);
struct process {
ProcessType type;
struct proc {
ProcType type;
Loop *loop;
void *data;
int pid, status, refcount;
uint8_t exit_signal; // Signal used when killing (on Windows).
uint64_t stopped_time; // process_stop() timestamp
uint64_t stopped_time; // proc_stop() timestamp
const char *cwd;
char **argv;
const char *exepath;
dict_T *env;
Stream in;
RStream out, err;
/// Exit handler. If set, user must call process_free().
process_exit_cb cb;
internal_process_cb internal_exit_cb, internal_close_cb;
/// Exit handler. If set, user must call proc_free().
proc_exit_cb cb;
internal_proc_cb internal_exit_cb, internal_close_cb;
bool closed, detach, overlapped, fwd_err;
MultiQueue *events;
};

View File

@ -5,9 +5,9 @@
#include "nvim/eval/typval.h"
#include "nvim/event/defs.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/libuv_proc.h"
#include "nvim/event/loop.h"
#include "nvim/event/process.h"
#include "nvim/event/proc.h"
#include "nvim/log.h"
#include "nvim/os/os.h"
#include "nvim/os/os_defs.h"
@ -15,15 +15,15 @@
#include "nvim/ui_client.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/libuv_process.c.generated.h"
# include "event/libuv_proc.c.generated.h"
#endif
/// @returns zero on success, or negative error code
int libuv_process_spawn(LibuvProcess *uvproc)
int libuv_proc_spawn(LibuvProc *uvproc)
FUNC_ATTR_NONNULL_ALL
{
Process *proc = (Process *)uvproc;
uvproc->uvopts.file = process_get_exepath(proc);
Proc *proc = (Proc *)uvproc;
uvproc->uvopts.file = proc_get_exepath(proc);
uvproc->uvopts.args = proc->argv;
uvproc->uvopts.flags = UV_PROCESS_WINDOWS_HIDE;
#ifdef MSWIN
@ -101,7 +101,7 @@ int libuv_process_spawn(LibuvProcess *uvproc)
return status;
}
void libuv_process_close(LibuvProcess *uvproc)
void libuv_proc_close(LibuvProc *uvproc)
FUNC_ATTR_NONNULL_ARG(1)
{
uv_close((uv_handle_t *)&uvproc->uv, close_cb);
@ -109,11 +109,11 @@ void libuv_process_close(LibuvProcess *uvproc)
static void close_cb(uv_handle_t *handle)
{
Process *proc = handle->data;
Proc *proc = handle->data;
if (proc->internal_close_cb) {
proc->internal_close_cb(proc);
}
LibuvProcess *uvproc = (LibuvProcess *)proc;
LibuvProc *uvproc = (LibuvProc *)proc;
if (uvproc->uvopts.env) {
os_free_fullenv(uvproc->uvopts.env);
}
@ -121,7 +121,7 @@ static void close_cb(uv_handle_t *handle)
static void exit_cb(uv_process_t *handle, int64_t status, int term_signal)
{
Process *proc = handle->data;
Proc *proc = handle->data;
#if defined(MSWIN)
// Use stored/expected signal.
term_signal = proc->exit_signal;
@ -130,10 +130,10 @@ static void exit_cb(uv_process_t *handle, int64_t status, int term_signal)
proc->internal_exit_cb(proc);
}
LibuvProcess libuv_process_init(Loop *loop, void *data)
LibuvProc libuv_proc_init(Loop *loop, void *data)
{
LibuvProcess rv = {
.process = process_init(loop, kProcessTypeUv, data)
LibuvProc rv = {
.proc = proc_init(loop, kProcTypeUv, data)
};
return rv;
}

View File

@ -5,12 +5,12 @@
#include "nvim/event/defs.h"
typedef struct {
Process process;
Proc proc;
uv_process_t uv;
uv_process_options_t uvopts;
uv_stdio_container_t uvstdio[4];
} LibuvProcess;
} LibuvProc;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/libuv_process.h.generated.h"
# include "event/libuv_proc.h.generated.h"
#endif

View File

@ -4,24 +4,24 @@
#include <uv.h>
#include "klib/klist.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/libuv_proc.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/process.h"
#include "nvim/event/proc.h"
#include "nvim/event/rstream.h"
#include "nvim/event/stream.h"
#include "nvim/event/wstream.h"
#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/main.h"
#include "nvim/os/process.h"
#include "nvim/os/pty_process.h"
#include "nvim/os/proc.h"
#include "nvim/os/pty_proc.h"
#include "nvim/os/shell.h"
#include "nvim/os/time.h"
#include "nvim/ui_client.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/process.c.generated.h"
# include "event/proc.c.generated.h"
#endif
// Time for a process to exit cleanly before we send KILL.
@ -33,13 +33,13 @@
void __gcov_flush(void);
#endif
static bool process_is_tearing_down = false;
static bool proc_is_tearing_down = false;
// Delay exit until handles are closed, to avoid deadlocks
static int exit_need_delay = 0;
/// @returns zero on success, or negative error code
int process_spawn(Process *proc, bool in, bool out, bool err)
int proc_spawn(Proc *proc, bool in, bool out, bool err)
FUNC_ATTR_NONNULL_ALL
{
// forwarding stderr contradicts with processing it internally
@ -70,11 +70,11 @@ int process_spawn(Process *proc, bool in, bool out, bool err)
int status;
switch (proc->type) {
case kProcessTypeUv:
status = libuv_process_spawn((LibuvProcess *)proc);
case kProcTypeUv:
status = libuv_proc_spawn((LibuvProc *)proc);
break;
case kProcessTypePty:
status = pty_process_spawn((PtyProcess *)proc);
case kProcTypePty:
status = pty_proc_spawn((PtyProc *)proc);
break;
}
@ -89,12 +89,12 @@ int process_spawn(Process *proc, bool in, bool out, bool err)
uv_close((uv_handle_t *)&proc->err.s.uv.pipe, NULL);
}
if (proc->type == kProcessTypeUv) {
uv_close((uv_handle_t *)&(((LibuvProcess *)proc)->uv), NULL);
if (proc->type == kProcTypeUv) {
uv_close((uv_handle_t *)&(((LibuvProc *)proc)->uv), NULL);
} else {
process_close(proc);
proc_close(proc);
}
process_free(proc);
proc_free(proc);
proc->status = -1;
return status;
}
@ -102,52 +102,52 @@ int process_spawn(Process *proc, bool in, bool out, bool err)
if (in) {
stream_init(NULL, &proc->in, -1, (uv_stream_t *)&proc->in.uv.pipe);
proc->in.internal_data = proc;
proc->in.internal_close_cb = on_process_stream_close;
proc->in.internal_close_cb = on_proc_stream_close;
proc->refcount++;
}
if (out) {
stream_init(NULL, &proc->out.s, -1, (uv_stream_t *)&proc->out.s.uv.pipe);
proc->out.s.internal_data = proc;
proc->out.s.internal_close_cb = on_process_stream_close;
proc->out.s.internal_close_cb = on_proc_stream_close;
proc->refcount++;
}
if (err) {
stream_init(NULL, &proc->err.s, -1, (uv_stream_t *)&proc->err.s.uv.pipe);
proc->err.s.internal_data = proc;
proc->err.s.internal_close_cb = on_process_stream_close;
proc->err.s.internal_close_cb = on_proc_stream_close;
proc->refcount++;
}
proc->internal_exit_cb = on_process_exit;
proc->internal_exit_cb = on_proc_exit;
proc->internal_close_cb = decref;
proc->refcount++;
kl_push(WatcherPtr, proc->loop->children, proc);
DLOG("new: pid=%d exepath=[%s]", proc->pid, process_get_exepath(proc));
DLOG("new: pid=%d exepath=[%s]", proc->pid, proc_get_exepath(proc));
return 0;
}
void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL
void proc_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL
{
process_is_tearing_down = true;
proc_is_tearing_down = true;
kl_iter(WatcherPtr, loop->children, current) {
Process *proc = (*current)->data;
if (proc->detach || proc->type == kProcessTypePty) {
Proc *proc = (*current)->data;
if (proc->detach || proc->type == kProcTypePty) {
// Close handles to process without killing it.
CREATE_EVENT(loop->events, process_close_handles, proc);
CREATE_EVENT(loop->events, proc_close_handles, proc);
} else {
process_stop(proc);
proc_stop(proc);
}
}
// Wait until all children exit and all close events are processed.
LOOP_PROCESS_EVENTS_UNTIL(loop, loop->events, -1,
kl_empty(loop->children) && multiqueue_empty(loop->events));
pty_process_teardown(loop);
pty_proc_teardown(loop);
}
void process_close_streams(Process *proc) FUNC_ATTR_NONNULL_ALL
void proc_close_streams(Proc *proc) FUNC_ATTR_NONNULL_ALL
{
wstream_may_close(&proc->in);
rstream_may_close(&proc->out);
@ -162,7 +162,7 @@ void process_close_streams(Process *proc) FUNC_ATTR_NONNULL_ALL
/// @return Exit code of the process. proc->status will have the same value.
/// -1 if the timeout expired while the process is still running.
/// -2 if the user interrupted the wait.
int process_wait(Process *proc, int ms, MultiQueue *events)
int proc_wait(Proc *proc, int ms, MultiQueue *events)
FUNC_ATTR_NONNULL_ARG(1)
{
if (!proc->refcount) {
@ -186,7 +186,7 @@ int process_wait(Process *proc, int ms, MultiQueue *events)
// Assume that a user hitting CTRL-C does not like the current job. Kill it.
if (got_int) {
got_int = false;
process_stop(proc);
proc_stop(proc);
if (ms == -1) {
// We can only return if all streams/handles are closed and the job
// exited.
@ -214,7 +214,7 @@ int process_wait(Process *proc, int ms, MultiQueue *events)
}
/// Ask a process to terminate and eventually kill if it doesn't respond
void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL
void proc_stop(Proc *proc) FUNC_ATTR_NONNULL_ALL
{
bool exited = (proc->status >= 0);
if (exited || proc->stopped_time) {
@ -224,13 +224,13 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL
proc->exit_signal = SIGTERM;
switch (proc->type) {
case kProcessTypeUv:
case kProcTypeUv:
os_proc_tree_kill(proc->pid, SIGTERM);
break;
case kProcessTypePty:
case kProcTypePty:
// close all streams for pty processes to send SIGHUP to the process
process_close_streams(proc);
pty_process_close_master((PtyProcess *)proc);
proc_close_streams(proc);
pty_proc_close_master((PtyProc *)proc);
break;
}
@ -240,7 +240,7 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL
}
/// Frees process-owned resources.
void process_free(Process *proc) FUNC_ATTR_NONNULL_ALL
void proc_free(Proc *proc) FUNC_ATTR_NONNULL_ALL
{
if (proc->argv != NULL) {
shell_free_argv(proc->argv);
@ -249,19 +249,19 @@ void process_free(Process *proc) FUNC_ATTR_NONNULL_ALL
}
/// Sends SIGKILL (or SIGTERM..SIGKILL for PTY jobs) to processes that did
/// not terminate after process_stop().
/// not terminate after proc_stop().
static void children_kill_cb(uv_timer_t *handle)
{
Loop *loop = handle->loop->data;
kl_iter(WatcherPtr, loop->children, current) {
Process *proc = (*current)->data;
Proc *proc = (*current)->data;
bool exited = (proc->status >= 0);
if (exited || !proc->stopped_time) {
continue;
}
uint64_t term_sent = UINT64_MAX == proc->stopped_time;
if (kProcessTypePty != proc->type || term_sent) {
if (kProcTypePty != proc->type || term_sent) {
proc->exit_signal = SIGKILL;
os_proc_tree_kill(proc->pid, SIGKILL);
} else {
@ -275,19 +275,19 @@ static void children_kill_cb(uv_timer_t *handle)
}
}
static void process_close_event(void **argv)
static void proc_close_event(void **argv)
{
Process *proc = argv[0];
Proc *proc = argv[0];
if (proc->cb) {
// User (hint: channel_job_start) is responsible for calling
// process_free().
// proc_free().
proc->cb(proc, proc->status, proc->data);
} else {
process_free(proc);
proc_free(proc);
}
}
static void decref(Process *proc)
static void decref(Proc *proc)
{
if (--proc->refcount != 0) {
return;
@ -303,13 +303,13 @@ static void decref(Process *proc)
}
assert(node);
kl_shift_at(WatcherPtr, loop->children, node);
CREATE_EVENT(proc->events, process_close_event, proc);
CREATE_EVENT(proc->events, proc_close_event, proc);
}
static void process_close(Process *proc)
static void proc_close(Proc *proc)
FUNC_ATTR_NONNULL_ARG(1)
{
if (process_is_tearing_down && (proc->detach || proc->type == kProcessTypePty)
if (proc_is_tearing_down && (proc->detach || proc->type == kProcTypePty)
&& proc->closed) {
// If a detached/pty process dies while tearing down it might get closed
// twice.
@ -319,17 +319,17 @@ static void process_close(Process *proc)
proc->closed = true;
if (proc->detach) {
if (proc->type == kProcessTypeUv) {
uv_unref((uv_handle_t *)&(((LibuvProcess *)proc)->uv));
if (proc->type == kProcTypeUv) {
uv_unref((uv_handle_t *)&(((LibuvProc *)proc)->uv));
}
}
switch (proc->type) {
case kProcessTypeUv:
libuv_process_close((LibuvProcess *)proc);
case kProcTypeUv:
libuv_proc_close((LibuvProc *)proc);
break;
case kProcessTypePty:
pty_process_close((PtyProcess *)proc);
case kProcTypePty:
pty_proc_close((PtyProc *)proc);
break;
}
}
@ -338,7 +338,7 @@ static void process_close(Process *proc)
///
/// @param proc Process, for which an output stream should be flushed.
/// @param stream Stream to flush.
static void flush_stream(Process *proc, RStream *stream)
static void flush_stream(Proc *proc, RStream *stream)
FUNC_ATTR_NONNULL_ARG(1)
{
if (!stream || stream->s.closed) {
@ -382,16 +382,16 @@ static void flush_stream(Process *proc, RStream *stream)
}
}
static void process_close_handles(void **argv)
static void proc_close_handles(void **argv)
{
Process *proc = argv[0];
Proc *proc = argv[0];
exit_need_delay++;
flush_stream(proc, &proc->out);
flush_stream(proc, &proc->err);
process_close_streams(proc);
process_close(proc);
proc_close_streams(proc);
proc_close(proc);
exit_need_delay--;
}
@ -426,7 +426,7 @@ void exit_from_channel(int status)
multiqueue_put(main_loop.fast_events, exit_event, (void *)(intptr_t)status);
}
static void on_process_exit(Process *proc)
static void on_proc_exit(Proc *proc)
{
Loop *loop = proc->loop;
ILOG("exited: pid=%d status=%d stoptime=%" PRIu64, proc->pid, proc->status,
@ -439,13 +439,13 @@ static void on_process_exit(Process *proc)
// Process has terminated, but there could still be data to be read from the
// OS. We are still in the libuv loop, so we cannot call code that polls for
// more data directly. Instead delay the reading after the libuv loop by
// queueing process_close_handles() as an event.
// queueing proc_close_handles() as an event.
MultiQueue *queue = proc->events ? proc->events : loop->events;
CREATE_EVENT(queue, process_close_handles, proc);
CREATE_EVENT(queue, proc_close_handles, proc);
}
static void on_process_stream_close(Stream *stream, void *data)
static void on_proc_stream_close(Stream *stream, void *data)
{
Process *proc = data;
Proc *proc = data;
decref(proc);
}

View File

@ -6,9 +6,9 @@
#include "nvim/event/defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h"
static inline Process process_init(Loop *loop, ProcessType type, void *data)
static inline Proc proc_init(Loop *loop, ProcType type, void *data)
{
return (Process) {
return (Proc) {
.type = type,
.data = data,
.loop = loop,
@ -33,17 +33,17 @@ static inline Process process_init(Loop *loop, ProcessType type, void *data)
}
/// Get the path to the executable of the process.
static inline const char *process_get_exepath(Process *proc)
static inline const char *proc_get_exepath(Proc *proc)
{
return proc->exepath != NULL ? proc->exepath : proc->argv[0];
}
static inline bool process_is_stopped(Process *proc)
static inline bool proc_is_stopped(Proc *proc)
{
bool exited = (proc->status >= 0);
return exited || (proc->stopped_time != 0);
}
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/process.h.generated.h"
# include "event/proc.h.generated.h"
#endif

View File

@ -94,14 +94,17 @@ void stream_init(Loop *loop, Stream *stream, int fd, uv_stream_t *uvstream)
stream->events = NULL;
}
void stream_close(Stream *stream, stream_close_cb on_stream_close, void *data, bool rstream)
void stream_may_close(Stream *stream, bool rstream)
FUNC_ATTR_NONNULL_ARG(1)
{
if (stream->closed) {
return;
}
assert(!stream->closed);
DLOG("closing Stream: %p", (void *)stream);
stream->closed = true;
stream->close_cb = on_stream_close;
stream->close_cb_data = data;
stream->close_cb = NULL;
stream->close_cb_data = NULL;
#ifdef MSWIN
if (UV_TTY == uv_guess_handle(stream->fd)) {
@ -115,13 +118,6 @@ void stream_close(Stream *stream, stream_close_cb on_stream_close, void *data, b
}
}
void stream_may_close(Stream *stream, bool rstream)
{
if (!stream->closed) {
stream_close(stream, NULL, NULL, rstream);
}
}
void stream_close_handle(Stream *stream, bool rstream)
FUNC_ATTR_NONNULL_ALL
{

View File

@ -288,6 +288,8 @@ static size_t spell_bad_len = 0; // length of located bad word
static int compl_selected_item = -1;
static int *compl_fuzzy_scores;
/// CTRL-X pressed in Insert mode.
void ins_ctrl_x(void)
{
@ -2991,7 +2993,7 @@ enum {
/// the "st->e_cpt" option value and process the next matching source.
/// INS_COMPL_CPT_END if all the values in "st->e_cpt" are processed.
static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_arg,
pos_T *start_match_pos)
pos_T *start_match_pos, bool in_fuzzy)
{
int compl_type = -1;
int status = INS_COMPL_CPT_OK;
@ -3007,7 +3009,7 @@ static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_ar
st->first_match_pos = *start_match_pos;
// Move the cursor back one character so that ^N can match the
// word immediately after the cursor.
if (ctrl_x_mode_normal() && dec(&st->first_match_pos) < 0) {
if (ctrl_x_mode_normal() && (!in_fuzzy && dec(&st->first_match_pos) < 0)) {
// Move the cursor to after the last character in the
// buffer, so that word at start of buffer is found
// correctly.
@ -3145,11 +3147,75 @@ static void get_next_tag_completion(void)
p_ic = save_p_ic;
}
/// Compare function for qsort
static int compare_scores(const void *a, const void *b)
{
int idx_a = *(const int *)a;
int idx_b = *(const int *)b;
int score_a = compl_fuzzy_scores[idx_a];
int score_b = compl_fuzzy_scores[idx_b];
return score_a == score_b ? (idx_a == idx_b ? 0 : (idx_a < idx_b ? -1 : 1))
: (score_a > score_b ? -1 : 1);
}
/// Get the next set of filename matching "compl_pattern".
static void get_next_filename_completion(void)
{
char **matches;
int num_matches;
char *leader = ins_compl_leader();
size_t leader_len = strlen(leader);
bool in_fuzzy = ((get_cot_flags() & COT_FUZZY) != 0 && leader_len > 0);
#ifdef BACKSLASH_IN_FILENAME
char pathsep = (curbuf->b_p_csl[0] == 's')
? '/' : (curbuf->b_p_csl[0] == 'b') ? '\\' : PATHSEP;
#else
char pathsep = PATHSEP;
#endif
if (in_fuzzy) {
#ifdef BACKSLASH_IN_FILENAME
if (curbuf->b_p_csl[0] == 's') {
for (size_t i = 0; i < leader_len; i++) {
if (leader[i] == '\\') {
leader[i] = '/';
}
}
} else if (curbuf->b_p_csl[0] == 'b') {
for (size_t i = 0; i < leader_len; i++) {
if (leader[i] == '/') {
leader[i] = '\\';
}
}
}
#endif
char *last_sep = strrchr(leader, pathsep);
if (last_sep == NULL) {
// No path separator or separator is the last character,
// fuzzy match the whole leader
xfree(compl_pattern);
compl_pattern = xstrdup("*");
compl_patternlen = strlen(compl_pattern);
} else if (*(last_sep + 1) == NUL) {
in_fuzzy = false;
} else {
// Split leader into path and file parts
size_t path_len = (size_t)(last_sep - leader) + 1;
size_t path_with_wildcard_len = path_len + 2;
char *path_with_wildcard = xmalloc(path_with_wildcard_len);
xmemcpyz(path_with_wildcard, leader, path_len);
xstrlcat(path_with_wildcard, "*", path_with_wildcard_len);
xfree(compl_pattern);
compl_pattern = path_with_wildcard;
compl_patternlen = strlen(compl_pattern);
// Move leader to the file part
leader = last_sep + 1;
leader_len = strlen(leader);
}
}
if (expand_wildcards(1, &compl_pattern, &num_matches, &matches,
EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) != OK) {
return;
@ -3172,8 +3238,47 @@ static void get_next_filename_completion(void)
}
}
#endif
if (in_fuzzy) {
garray_T fuzzy_indices;
ga_init(&fuzzy_indices, sizeof(int), 10);
compl_fuzzy_scores = (int *)xmalloc(sizeof(int) * (size_t)num_matches);
for (int i = 0; i < num_matches; i++) {
char *ptr = matches[i];
int score = fuzzy_match_str(ptr, leader);
if (score > 0) {
GA_APPEND(int, &fuzzy_indices, i);
compl_fuzzy_scores[i] = score;
}
}
// prevent qsort from deref NULL pointer
if (fuzzy_indices.ga_len > 0) {
int *fuzzy_indices_data = (int *)fuzzy_indices.ga_data;
qsort(fuzzy_indices_data, (size_t)fuzzy_indices.ga_len, sizeof(int), compare_scores);
char **sorted_matches = (char **)xmalloc(sizeof(char *) * (size_t)fuzzy_indices.ga_len);
for (int i = 0; i < fuzzy_indices.ga_len; i++) {
sorted_matches[i] = xstrdup(matches[fuzzy_indices_data[i]]);
}
FreeWild(num_matches, matches);
matches = sorted_matches;
num_matches = fuzzy_indices.ga_len;
} else if (leader_len > 0) {
FreeWild(num_matches, matches);
num_matches = 0;
}
xfree(compl_fuzzy_scores);
ga_clear(&fuzzy_indices);
}
if (num_matches > 0) {
ins_compl_add_matches(num_matches, matches, p_fic || p_wic);
}
}
/// Get the next set of command-line completions matching "compl_pattern".
static void get_next_cmdline_completion(void)
@ -3293,6 +3398,11 @@ static char *ins_compl_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_po
/// @return OK if a new next match is found, otherwise FAIL.
static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_pos)
{
char *ptr = NULL;
int len = 0;
bool in_fuzzy = (get_cot_flags() & COT_FUZZY) != 0 && compl_length > 0;
char *leader = ins_compl_leader();
// If 'infercase' is set, don't use 'smartcase' here
const int save_p_scs = p_scs;
assert(st->ins_buf);
@ -3307,7 +3417,7 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_
const int save_p_ws = p_ws;
if (st->ins_buf != curbuf) {
p_ws = false;
} else if (*st->e_cpt == '.') {
} else if (*st->e_cpt == '.' && !in_fuzzy) {
p_ws = true;
}
bool looped_around = false;
@ -3318,9 +3428,14 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_
msg_silent++; // Don't want messages for wrapscan.
// ctrl_x_mode_line_or_eval() || word-wise search that
// has added a word that was at the beginning of the line.
if (ctrl_x_mode_line_or_eval() || (compl_cont_status & CONT_SOL)) {
if ((ctrl_x_mode_whole_line() && !in_fuzzy) || ctrl_x_mode_eval()
|| (compl_cont_status & CONT_SOL)) {
found_new_match = search_for_exact_line(st->ins_buf, st->cur_match_pos,
compl_direction, compl_pattern);
} else if (in_fuzzy) {
found_new_match = search_for_fuzzy_match(st->ins_buf,
st->cur_match_pos, leader, compl_direction,
start_pos, &len, &ptr, ctrl_x_mode_whole_line());
} else {
found_new_match = searchit(NULL, st->ins_buf, st->cur_match_pos,
NULL, compl_direction, compl_pattern, compl_patternlen,
@ -3366,12 +3481,15 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_
&& start_pos->col == st->cur_match_pos->col) {
continue;
}
int len;
char *ptr = ins_compl_get_next_word_or_line(st->ins_buf, st->cur_match_pos,
if (!in_fuzzy) {
ptr = ins_compl_get_next_word_or_line(st->ins_buf, st->cur_match_pos,
&len, &cont_s_ipos);
}
if (ptr == NULL) {
continue;
}
if (ins_compl_add_infercase(ptr, len, p_ic,
st->ins_buf == curbuf ? NULL : st->ins_buf->b_sfname,
0, cont_s_ipos) != NOTDONE) {
@ -3472,6 +3590,7 @@ static int ins_compl_get_exp(pos_T *ini)
static bool st_cleared = false;
int found_new_match;
int type = ctrl_x_mode;
bool in_fuzzy = (get_cot_flags() & COT_FUZZY) != 0;
assert(curbuf != NULL);
@ -3508,7 +3627,7 @@ static int ins_compl_get_exp(pos_T *ini)
// entries from 'complete' that look in loaded buffers.
if ((ctrl_x_mode_normal() || ctrl_x_mode_line_or_eval())
&& (!compl_started || st.found_all)) {
int status = process_next_cpt_value(&st, &type, ini);
int status = process_next_cpt_value(&st, &type, ini, in_fuzzy);
if (status == INS_COMPL_CPT_END) {
break;
}
@ -4452,6 +4571,7 @@ static int ins_compl_start(void)
line = ml_get(curwin->w_cursor.lnum);
}
bool in_fuzzy = get_cot_flags() & COT_FUZZY;
if (compl_status_adding()) {
edit_submode_pre = _(" Adding");
if (ctrl_x_mode_line_or_eval()) {
@ -4465,6 +4585,9 @@ static int ins_compl_start(void)
curbuf->b_p_com = old;
compl_length = 0;
compl_col = curwin->w_cursor.col;
} else if (ctrl_x_mode_normal() && in_fuzzy) {
compl_startpos = curwin->w_cursor;
compl_cont_status &= CONT_S_IPOS;
}
} else {
edit_submode_pre = NULL;

View File

@ -29,6 +29,7 @@
#include "nvim/os/stdpaths_defs.h"
#include "nvim/os/time.h"
#include "nvim/path.h"
#include "nvim/ui_client.h"
/// Cached location of the expanded log file path decided by log_path_init().
static char log_file_path[MAXPATHL + 1] = { 0 };
@ -322,20 +323,28 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, const char *context,
millis = (int)curtime.tv_usec / 1000;
}
bool ui = !!ui_client_channel_id; // Running as a UI client (--remote-ui).
// Regenerate the name when:
// - UI client (to ensure "ui" is in the name)
// - not set yet
// - no v:servername yet
bool regen = ui || name[0] == NUL || name[0] == '?';
// Get a name for this Nvim instance.
// TODO(justinmk): expose this as v:name ?
if (name[0] == NUL) {
// Parent servername.
if (regen) {
// Parent servername ($NVIM).
const char *parent = path_tail(os_getenv(ENV_NVIM));
// Servername. Empty until starting=false.
const char *serv = path_tail(get_vim_var_str(VV_SEND_SERVER));
if (parent[0] != NUL) {
snprintf(name, sizeof(name), "%s/c", parent); // "/c" indicates child.
snprintf(name, sizeof(name), ui ? "ui/c/%s" : "c/%s", parent); // "c/" = child of $NVIM.
} else if (serv[0] != NUL) {
snprintf(name, sizeof(name), "%s", serv);
snprintf(name, sizeof(name), ui ? "ui/%s" : "%s", serv);
} else {
int64_t pid = os_get_pid();
snprintf(name, sizeof(name), "?.%-5" PRId64, pid);
snprintf(name, sizeof(name), "%s.%-5" PRId64, ui ? "ui" : "?", pid);
}
}
@ -348,10 +357,6 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, const char *context,
log_levels[log_level], date_time, millis, name,
(context == NULL ? "" : context),
func_name, line_num);
if (name[0] == '?') {
// No v:servername yet. Clear `name` so that the next log can try again.
name[0] = NUL;
}
if (rv < 0) {
return false;

View File

@ -43,7 +43,7 @@
#include "nvim/eval/userfunc.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/process.h"
#include "nvim/event/proc.h"
#include "nvim/event/stream.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_docmd.h"
@ -174,7 +174,7 @@ bool event_teardown(void)
loop_poll_events(&main_loop, 0); // Drain thread_events, fast_events.
input_stop();
channel_teardown();
process_teardown(&main_loop);
proc_teardown(&main_loop);
timer_teardown();
server_teardown();
signal_teardown();
@ -2207,7 +2207,7 @@ static void usage(void)
printf(_(" --headless Don't start a user interface\n"));
printf(_(" --listen <address> Serve RPC API from this address\n"));
printf(_(" --remote[-subcommand] Execute commands remotely on a server\n"));
printf(_(" --server <address> Specify RPC server to send commands to\n"));
printf(_(" --server <address> Connect to this Nvim server\n"));
printf(_(" --startuptime <file> Write startup timing messages to <file>\n"));
printf(_("\nSee \":help startup-options\" for all options.\n"));
}

View File

@ -84,7 +84,7 @@
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/os/os_defs.h"
#include "nvim/os/process.h"
#include "nvim/os/proc.h"
#include "nvim/os/time.h"
#include "nvim/os/time_defs.h"
#include "nvim/path.h"
@ -743,7 +743,7 @@ static void add_b0_fenc(ZeroBlock *b0p, buf_T *buf)
/// @param swap_fname Name of the swapfile. If it's from before a reboot, the result is 0.
///
/// @return PID, or 0 if process is not running or the swapfile is from before a reboot.
static int swapfile_process_running(const ZeroBlock *b0p, const char *swap_fname)
static int swapfile_proc_running(const ZeroBlock *b0p, const char *swap_fname)
{
FileInfo st;
double uptime;
@ -1214,7 +1214,7 @@ void ml_recover(bool checkext)
msg(_("Recovery completed. Buffer contents equals file contents."), 0);
}
msg_puts(_("\nYou may want to delete the .swp file now."));
if (swapfile_process_running(b0p, fname_used)) {
if (swapfile_proc_running(b0p, fname_used)) {
// Warn there could be an active Vim on the same file, the user may
// want to kill it.
msg_puts(_("\nNote: process STILL RUNNING: "));
@ -1462,7 +1462,7 @@ char *make_percent_swname(char *dir, char *dir_end, const char *name)
}
// PID of swapfile owner, or zero if not running.
static int process_running;
static int proc_running;
/// For Vimscript "swapinfo()".
///
@ -1488,7 +1488,7 @@ void swapfile_dict(const char *fname, dict_T *d)
tv_dict_add_str_len(d, S_LEN("fname"), b0.b0_fname,
B0_FNAME_SIZE_ORG);
tv_dict_add_nr(d, S_LEN("pid"), swapfile_process_running(&b0, fname));
tv_dict_add_nr(d, S_LEN("pid"), swapfile_proc_running(&b0, fname));
tv_dict_add_nr(d, S_LEN("mtime"), char_to_long(b0.b0_mtime));
tv_dict_add_nr(d, S_LEN("dirty"), b0.b0_dirty ? 1 : 0);
tv_dict_add_nr(d, S_LEN("inode"), char_to_long(b0.b0_ino));
@ -1572,7 +1572,7 @@ static time_t swapfile_info(char *fname)
if (char_to_long(b0.b0_pid) != 0) {
msg_puts(_("\n process ID: "));
msg_outnum((int)char_to_long(b0.b0_pid));
if ((process_running = swapfile_process_running(&b0, fname))) {
if ((proc_running = swapfile_proc_running(&b0, fname))) {
msg_puts(_(" (STILL RUNNING)"));
}
}
@ -1640,7 +1640,7 @@ static bool swapfile_unchanged(char *fname)
}
// process must be known and not running.
if (char_to_long(b0.b0_pid) == 0 || swapfile_process_running(&b0, fname)) {
if (char_to_long(b0.b0_pid) == 0 || swapfile_proc_running(&b0, fname)) {
ret = false;
}
@ -3399,7 +3399,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
fd = os_open(fname, O_RDONLY, 0);
if (fd >= 0) {
if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) {
process_running = swapfile_process_running(&b0, fname);
proc_running = swapfile_proc_running(&b0, fname);
// If the swapfile has the same directory as the
// buffer don't compare the directory names, they can
@ -3459,7 +3459,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
choice = SEA_CHOICE_READONLY;
}
process_running = 0; // Set by attention_message..swapfile_info.
proc_running = 0; // Set by attention_message..swapfile_info.
if (choice == SEA_CHOICE_NONE) {
// Show info about the existing swapfile.
attention_message(buf, fname);
@ -3491,12 +3491,12 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
= do_dialog(VIM_WARNING,
_("VIM - ATTENTION"),
name,
process_running
proc_running
? _("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort")
: _("&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"),
1, NULL, false);
if (process_running && dialog_result >= 4) {
if (proc_running && dialog_result >= 4) {
// compensate for missing "Delete it" button
dialog_result++;
}

View File

@ -14,7 +14,7 @@
#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/process.h"
#include "nvim/event/proc.h"
#include "nvim/event/rstream.h"
#include "nvim/event/wstream.h"
#include "nvim/globals.h"

View File

@ -53,7 +53,7 @@ bool server_init(const char *listen_addr)
int rv = server_start(listen_addr);
// TODO(justinmk): this is for logging_spec. Can remove this after nvim_log #7062 is merged.
// TODO(justinmk): this is for log_spec. Can remove this after nvim_log #7062 is merged.
if (os_env_exists("__NVIM_TEST_LOG")) {
ELOG("test log message");
}

View File

@ -210,39 +210,53 @@ static void set_init_default_backupskip(void)
OptIndex opt_idx = kOptBackupskip;
ga_init(&ga, 1, 100);
for (size_t n = 0; n < ARRAY_SIZE(names); n++) {
for (size_t i = 0; i < ARRAY_SIZE(names); i++) {
bool mustfree = true;
char *p;
size_t plen;
#ifdef UNIX
if (*names[n] == NUL) {
if (*names[i] == NUL) {
# ifdef __APPLE__
p = "/private/tmp";
plen = STRLEN_LITERAL("/private/tmp");
# else
p = "/tmp";
plen = STRLEN_LITERAL("/tmp");
# endif
mustfree = false;
} else
#endif
{
p = vim_getenv(names[n]);
p = vim_getenv(names[i]);
plen = 0; // will be calcuated below
}
if (p != NULL && *p != NUL) {
// First time count the NUL, otherwise count the ','.
const size_t len = strlen(p) + 3;
char *item = xmalloc(len);
xstrlcpy(item, p, len);
add_pathsep(item);
xstrlcat(item, "*", len);
if (find_dup_item(ga.ga_data, item, options[opt_idx].flags)
== NULL) {
ga_grow(&ga, (int)len);
if (!GA_EMPTY(&ga)) {
strcat(ga.ga_data, ",");
bool has_trailing_path_sep = false;
if (plen == 0) {
// the value was retrieved from the environment
plen = strlen(p);
// does the value include a trailing path separator?
if (after_pathsep(p, p + plen)) {
has_trailing_path_sep = true;
}
strcat(ga.ga_data, p);
add_pathsep(ga.ga_data);
strcat(ga.ga_data, "*");
ga.ga_len += (int)len;
}
// item size needs to be large enough to include "/*" and a trailing NUL
// note: the value (and therefore plen) may already include a path separator
size_t itemsize = plen + (has_trailing_path_sep ? 0 : 1) + 2;
char *item = xmalloc(itemsize);
// add a preceeding comma as a separator after the first item
size_t itemseplen = (ga.ga_len == 0) ? 0 : 1;
size_t itemlen = (size_t)vim_snprintf(item, itemsize, "%s%s*", p,
has_trailing_path_sep ? "" : PATHSEPSTR);
if (find_dup_item(ga.ga_data, item, itemlen, options[opt_idx].flags) == NULL) {
ga_grow(&ga, (int)(itemseplen + itemlen + 1));
ga.ga_len += vim_snprintf((char *)ga.ga_data + ga.ga_len,
itemseplen + itemlen + 1,
"%s%s", (itemseplen > 0) ? "," : "", item);
}
xfree(item);
}
@ -526,7 +540,8 @@ static void set_string_default(OptIndex opt_idx, char *val, bool allocated)
/// For an option value that contains comma separated items, find "newval" in
/// "origval". Return NULL if not found.
static char *find_dup_item(char *origval, const char *newval, uint32_t flags)
static char *find_dup_item(char *origval, const char *newval, const size_t newvallen,
uint32_t flags)
FUNC_ATTR_NONNULL_ARG(2)
{
if (origval == NULL) {
@ -535,11 +550,10 @@ static char *find_dup_item(char *origval, const char *newval, uint32_t flags)
int bs = 0;
const size_t newlen = strlen(newval);
for (char *s = origval; *s != NUL; s++) {
if ((!(flags & P_COMMA) || s == origval || (s[-1] == ',' && !(bs & 1)))
&& strncmp(s, newval, newlen) == 0
&& (!(flags & P_COMMA) || s[newlen] == ',' || s[newlen] == NUL)) {
&& strncmp(s, newval, newvallen) == 0
&& (!(flags & P_COMMA) || s[newvallen] == ',' || s[newvallen] == NUL)) {
return s;
}
// Count backslashes. Only a comma with an even number of backslashes
@ -697,10 +711,10 @@ void set_helplang_default(const char *lang)
}
p_hlg = xmemdupz(lang, lang_len);
// zh_CN becomes "cn", zh_TW becomes "tw".
if (STRNICMP(p_hlg, "zh_", 3) == 0 && strlen(p_hlg) >= 5) {
if (STRNICMP(p_hlg, "zh_", 3) == 0 && lang_len >= 5) {
p_hlg[0] = (char)TOLOWER_ASC(p_hlg[3]);
p_hlg[1] = (char)TOLOWER_ASC(p_hlg[4]);
} else if (strlen(p_hlg) >= 1 && *p_hlg == 'C') {
} else if (lang_len && *p_hlg == 'C') {
// any C like setting, such as C.UTF-8, becomes "en"
p_hlg[0] = 'e';
p_hlg[1] = 'n';
@ -950,7 +964,7 @@ static char *stropt_get_newval(int nextchar, OptIndex opt_idx, char **argp, void
int len = 0;
if (op == OP_REMOVING || (flags & P_NODUP)) {
len = (int)strlen(newval);
s = find_dup_item(origval, newval, flags);
s = find_dup_item(origval, newval, (size_t)len, flags);
// do not add if already there
if ((op == OP_ADDING || op == OP_PREPENDING) && s != NULL) {
@ -1464,11 +1478,10 @@ int do_set(char *arg, int opt_flags)
}
if (errmsg != NULL) {
xstrlcpy(IObuff, _(errmsg), IOSIZE);
int i = (int)strlen(IObuff) + 2;
int i = vim_snprintf((char *)IObuff, IOSIZE, "%s", _(errmsg)) + 2;
if (i + (arg - startarg) < IOSIZE) {
// append the argument with the error
xstrlcat(IObuff, ": ", IOSIZE);
xstrlcpy(IObuff + i - 2, ": ", (size_t)(IOSIZE - i + 2));
assert(arg >= startarg);
memmove(IObuff + i, startarg, (size_t)(arg - startarg));
IObuff[i + (arg - startarg)] = NUL;
@ -5431,7 +5444,8 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
xp->xp_pattern = arg;
return;
}
char *p = arg + strlen(arg) - 1;
char *const argend = arg + strlen(arg);
char *p = argend - 1;
if (*p == ' ' && *(p - 1) != '\\') {
xp->xp_pattern = p + 1;
return;
@ -5618,7 +5632,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
// Triple-backslashed escaped file names (e.g. 'path') can also be
// delimited by space.
if ((flags & P_EXPAND) || (flags & P_COMMA) || (flags & P_COLON)) {
for (p = arg + strlen(arg) - 1; p > xp->xp_pattern; p--) {
for (p = argend - 1; p > xp->xp_pattern; p--) {
// count number of backslashes before ' ' or ','
if (*p == ' ' || *p == ',' || (*p == ':' && (flags & P_COLON))) {
char *s = p;
@ -5642,7 +5656,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
// An option that is a list of single-character flags should always start
// at the end as we don't complete words.
if (flags & P_FLAGLIST) {
xp->xp_pattern = arg + strlen(arg);
xp->xp_pattern = argend;
}
// Some options can either be using file/dir expansions, or custom value
@ -5952,7 +5966,7 @@ int ExpandSettingSubtract(expand_T *xp, regmatch_T *regmatch, int *numMatches, c
int count = 0;
(*matches)[count++] = xstrdup(option_val);
(*matches)[count++] = xmemdupz(option_val, num_flags);
if (num_flags > 1) {
// If more than one flags, split the flags up and expose each

View File

@ -1467,10 +1467,7 @@ return {
fuzzy Enable |fuzzy-matching| for completion candidates. This
allows for more flexible and intuitive matching, where
characters can be skipped and matches can be found even
if the exact sequence is not typed. Only makes a
difference how completion candidates are reduced from the
list of alternatives, but not how the candidates are
collected (using different completion types).
if the exact sequence is not typed.
]=],
expand_cb = 'expand_set_completeopt',
full_name = 'completeopt',
@ -9047,7 +9044,7 @@ return {
desc = [=[
When on, the title of the window will be set to the value of
'titlestring' (if it is not empty), or to:
filename [+=-] (path) - NVIM
filename [+=-] (path) - Nvim
Where:
filename the name of the file being edited
- indicates the file cannot be modified, 'ma' off
@ -9055,11 +9052,11 @@ return {
= indicates the file is read-only
=+ indicates the file is read-only and modified
(path) is the path of the file being edited
- NVIM the server name |v:servername| or "NVIM"
- Nvim the server name |v:servername| or "Nvim"
]=],
full_name = 'title',
scope = { 'global' },
short_desc = N_('Vim set the title of the window'),
short_desc = N_('set the title of the window'),
type = 'boolean',
varname = 'p_title',
},

View File

@ -344,7 +344,7 @@ char *os_getenvname_at_index(size_t index)
#endif
}
/// Get the process ID of the Neovim process.
/// Get the process ID of the Nvim process.
///
/// @return the process ID.
int64_t os_get_pid(void)

View File

@ -100,7 +100,7 @@ static void reset_cursorhold_wait(int tb_change_cnt)
///
/// Originally based on the Vim `mch_inchar` function.
///
/// @param buf Buffer to store read input.
/// @param buf Buffer to store consumed input.
/// @param maxlen Maximum bytes to read into `buf`, or 0 to skip reading.
/// @param ms Timeout in milliseconds. -1 for indefinite wait, 0 for no wait.
/// @param tb_change_cnt Used to detect when typeahead changes.
@ -493,7 +493,7 @@ static TriState inbuf_poll(int ms, MultiQueue *events)
blocking = true;
multiqueue_process_events(ch_before_blocking_events);
}
DLOG("blocking... events=%d pending=%d", !!events, pending_events(events));
DLOG("blocking... events=%s", !!events ? "true" : "false");
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, ms, os_input_ready(events) || input_eof);
blocking = false;

View File

@ -37,24 +37,24 @@
#include "nvim/log.h"
#include "nvim/memory.h"
#include "nvim/os/process.h"
#include "nvim/os/proc.h"
#ifdef MSWIN
# include "nvim/api/private/helpers.h"
#endif
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/process.c.generated.h"
# include "os/proc.c.generated.h"
#endif
#ifdef MSWIN
static bool os_proc_tree_kill_rec(HANDLE process, int sig)
static bool os_proc_tree_kill_rec(HANDLE proc, int sig)
{
if (process == NULL) {
if (proc == NULL) {
return false;
}
PROCESSENTRY32 pe;
DWORD pid = GetProcessId(process);
DWORD pid = GetProcessId(proc);
if (pid != 0) {
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
@ -77,7 +77,7 @@ static bool os_proc_tree_kill_rec(HANDLE process, int sig)
}
theend:
return (bool)TerminateProcess(process, (unsigned)sig);
return (bool)TerminateProcess(proc, (unsigned)sig);
}
/// Kills process `pid` and its descendants recursively.
bool os_proc_tree_kill(int pid, int sig)

View File

@ -7,5 +7,5 @@
#endif
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/process.h.generated.h"
# include "os/proc.h.generated.h"
#endif

View File

@ -143,7 +143,7 @@ finished:
return conpty_object;
}
bool os_conpty_spawn(conpty_t *conpty_object, HANDLE *process_handle, wchar_t *name,
bool os_conpty_spawn(conpty_t *conpty_object, HANDLE *proc_handle, wchar_t *name,
wchar_t *cmd_line, wchar_t *cwd, wchar_t *env)
{
PROCESS_INFORMATION pi = { 0 };
@ -159,7 +159,7 @@ bool os_conpty_spawn(conpty_t *conpty_object, HANDLE *process_handle, wchar_t *n
&pi)) {
return false;
}
*process_handle = pi.hProcess;
*proc_handle = pi.hProcess;
return true;
}

7
src/nvim/os/pty_proc.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#ifdef MSWIN
# include "nvim/os/pty_proc_win.h"
#else
# include "nvim/os/pty_proc_unix.h"
#endif

View File

@ -34,16 +34,16 @@
#include "nvim/eval/typval.h"
#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
#include "nvim/event/process.h"
#include "nvim/event/proc.h"
#include "nvim/log.h"
#include "nvim/os/fs.h"
#include "nvim/os/os_defs.h"
#include "nvim/os/pty_process.h"
#include "nvim/os/pty_process_unix.h"
#include "nvim/os/pty_proc.h"
#include "nvim/os/pty_proc_unix.h"
#include "nvim/types_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/pty_process_unix.c.generated.h"
# include "os/pty_proc_unix.c.generated.h"
#endif
#if defined(__sun) && !defined(HAVE_FORKPTY)
@ -158,7 +158,7 @@ static pid_t forkpty(int *amaster, char *name, struct termios *termp, struct win
#endif
/// @returns zero on success, or negative error code
int pty_process_spawn(PtyProcess *ptyproc)
int pty_proc_spawn(PtyProc *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
// termios initialized at first use
@ -168,7 +168,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
}
int status = 0; // zero or negative error code (libuv convention)
Process *proc = (Process *)ptyproc;
Proc *proc = (Proc *)ptyproc;
assert(proc->err.s.closed);
uv_signal_start(&proc->loop->children_watcher, chld_handler, SIGCHLD);
ptyproc->winsize = (struct winsize){ ptyproc->height, ptyproc->width, 0, 0 };
@ -224,29 +224,29 @@ error:
return status;
}
const char *pty_process_tty_name(PtyProcess *ptyproc)
const char *pty_proc_tty_name(PtyProc *ptyproc)
{
return ptsname(ptyproc->tty_fd);
}
void pty_process_resize(PtyProcess *ptyproc, uint16_t width, uint16_t height)
void pty_proc_resize(PtyProc *ptyproc, uint16_t width, uint16_t height)
FUNC_ATTR_NONNULL_ALL
{
ptyproc->winsize = (struct winsize){ height, width, 0, 0 };
ioctl(ptyproc->tty_fd, TIOCSWINSZ, &ptyproc->winsize);
}
void pty_process_close(PtyProcess *ptyproc)
void pty_proc_close(PtyProc *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
pty_process_close_master(ptyproc);
Process *proc = (Process *)ptyproc;
pty_proc_close_master(ptyproc);
Proc *proc = (Proc *)ptyproc;
if (proc->internal_close_cb) {
proc->internal_close_cb(proc);
}
}
void pty_process_close_master(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL
void pty_proc_close_master(PtyProc *ptyproc) FUNC_ATTR_NONNULL_ALL
{
if (ptyproc->tty_fd >= 0) {
close(ptyproc->tty_fd);
@ -254,12 +254,12 @@ void pty_process_close_master(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL
}
}
void pty_process_teardown(Loop *loop)
void pty_proc_teardown(Loop *loop)
{
uv_signal_stop(&loop->children_watcher);
}
static void init_child(PtyProcess *ptyproc)
static void init_child(PtyProc *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
#if defined(HAVE__NSGETENVIRON)
@ -277,13 +277,13 @@ static void init_child(PtyProcess *ptyproc)
signal(SIGTERM, SIG_DFL);
signal(SIGALRM, SIG_DFL);
Process *proc = (Process *)ptyproc;
Proc *proc = (Proc *)ptyproc;
if (proc->cwd && os_chdir(proc->cwd) != 0) {
ELOG("chdir(%s) failed: %s", proc->cwd, strerror(errno));
return;
}
const char *prog = process_get_exepath(proc);
const char *prog = proc_get_exepath(proc);
assert(proc->env);
environ = tv_dict_to_env(proc->env);
@ -388,7 +388,7 @@ static void chld_handler(uv_signal_t *handle, int signum)
Loop *loop = handle->loop->data;
kl_iter(WatcherPtr, loop->children, current) {
Process *proc = (*current)->data;
Proc *proc = (*current)->data;
do {
pid = waitpid(proc->pid, &stat, WNOHANG);
} while (pid < 0 && errno == EINTR);
@ -406,10 +406,10 @@ static void chld_handler(uv_signal_t *handle, int signum)
}
}
PtyProcess pty_process_init(Loop *loop, void *data)
PtyProc pty_proc_init(Loop *loop, void *data)
{
PtyProcess rv;
rv.process = process_init(loop, kProcessTypePty, data);
PtyProc rv;
rv.proc = proc_init(loop, kProcTypePty, data);
rv.width = 80;
rv.height = 24;
rv.tty_fd = -1;

View File

@ -1,5 +1,5 @@
#pragma once
// IWYU pragma: private, include "nvim/os/pty_process.h"
// IWYU pragma: private, include "nvim/os/pty_proc.h"
#include <stdint.h>
#include <sys/ioctl.h>
@ -7,12 +7,12 @@
#include "nvim/event/defs.h"
typedef struct {
Process process;
Proc proc;
uint16_t width, height;
struct winsize winsize;
int tty_fd;
} PtyProcess;
} PtyProc;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/pty_process_unix.h.generated.h"
# include "os/pty_proc_unix.h.generated.h"
#endif

View File

@ -10,20 +10,20 @@
#include "nvim/memory.h"
#include "nvim/os/os.h"
#include "nvim/os/pty_conpty_win.h"
#include "nvim/os/pty_process_win.h"
#include "nvim/os/pty_proc_win.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/pty_process_win.c.generated.h"
# include "os/pty_proc_win.c.generated.h"
#endif
static void CALLBACK pty_process_finish1(void *context, BOOLEAN unused)
static void CALLBACK pty_proc_finish1(void *context, BOOLEAN unused)
FUNC_ATTR_NONNULL_ALL
{
PtyProcess *ptyproc = (PtyProcess *)context;
Process *proc = (Process *)ptyproc;
PtyProc *ptyproc = (PtyProc *)context;
Proc *proc = (Proc *)ptyproc;
os_conpty_free(ptyproc->conpty);
// NB: pty_process_finish1() is called on a separate thread,
// NB: pty_proc_finish1() is called on a separate thread,
// but the timer only works properly if it's started by the main thread.
loop_schedule_fast(proc->loop, event_create(start_wait_eof_timer, ptyproc));
}
@ -31,7 +31,7 @@ static void CALLBACK pty_process_finish1(void *context, BOOLEAN unused)
static void start_wait_eof_timer(void **argv)
FUNC_ATTR_NONNULL_ALL
{
PtyProcess *ptyproc = (PtyProcess *)argv[0];
PtyProc *ptyproc = (PtyProc *)argv[0];
if (ptyproc->finish_wait != NULL) {
uv_timer_start(&ptyproc->wait_eof_timer, wait_eof_timer_cb, 200, 200);
@ -39,15 +39,15 @@ static void start_wait_eof_timer(void **argv)
}
/// @returns zero on success, or negative error code.
int pty_process_spawn(PtyProcess *ptyproc)
int pty_proc_spawn(PtyProc *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
Process *proc = (Process *)ptyproc;
Proc *proc = (Proc *)ptyproc;
int status = 0;
conpty_t *conpty_object = NULL;
char *in_name = NULL;
char *out_name = NULL;
HANDLE process_handle = NULL;
HANDLE proc_handle = NULL;
uv_connect_t *in_req = NULL;
uv_connect_t *out_req = NULL;
wchar_t *cmd_line = NULL;
@ -69,7 +69,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
uv_pipe_connect(in_req,
&proc->in.uv.pipe,
in_name,
pty_process_connect_cb);
pty_proc_connect_cb);
}
if (!proc->out.s.closed) {
@ -77,7 +77,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
uv_pipe_connect(out_req,
&proc->out.s.uv.pipe,
out_name,
pty_process_connect_cb);
pty_proc_connect_cb);
}
if (proc->cwd != NULL) {
@ -105,7 +105,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
}
if (!os_conpty_spawn(conpty_object,
&process_handle,
&proc_handle,
NULL,
cmd_line,
cwd,
@ -114,42 +114,42 @@ int pty_process_spawn(PtyProcess *ptyproc)
status = (int)GetLastError();
goto cleanup;
}
proc->pid = (int)GetProcessId(process_handle);
proc->pid = (int)GetProcessId(proc_handle);
uv_timer_init(&proc->loop->uv, &ptyproc->wait_eof_timer);
ptyproc->wait_eof_timer.data = (void *)ptyproc;
if (!RegisterWaitForSingleObject(&ptyproc->finish_wait,
process_handle,
pty_process_finish1,
proc_handle,
pty_proc_finish1,
ptyproc,
INFINITE,
WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE)) {
abort();
}
// Wait until pty_process_connect_cb is called.
// Wait until pty_proc_connect_cb is called.
while ((in_req != NULL && in_req->handle != NULL)
|| (out_req != NULL && out_req->handle != NULL)) {
uv_run(&proc->loop->uv, UV_RUN_ONCE);
}
ptyproc->conpty = conpty_object;
ptyproc->process_handle = process_handle;
ptyproc->proc_handle = proc_handle;
conpty_object = NULL;
process_handle = NULL;
proc_handle = NULL;
cleanup:
if (status) {
// In the case of an error of MultiByteToWideChar or CreateProcessW.
ELOG("pty_process_spawn(%s): %s: error code: %d",
ELOG("pty_proc_spawn(%s): %s: error code: %d",
proc->argv[0], emsg, status);
status = os_translate_sys_error(status);
}
os_conpty_free(conpty_object);
xfree(in_name);
xfree(out_name);
if (process_handle != NULL) {
CloseHandle(process_handle);
if (proc_handle != NULL) {
CloseHandle(proc_handle);
}
xfree(in_req);
xfree(out_req);
@ -159,32 +159,32 @@ cleanup:
return status;
}
const char *pty_process_tty_name(PtyProcess *ptyproc)
const char *pty_proc_tty_name(PtyProc *ptyproc)
{
return "?";
}
void pty_process_resize(PtyProcess *ptyproc, uint16_t width, uint16_t height)
void pty_proc_resize(PtyProc *ptyproc, uint16_t width, uint16_t height)
FUNC_ATTR_NONNULL_ALL
{
os_conpty_set_size(ptyproc->conpty, width, height);
}
void pty_process_close(PtyProcess *ptyproc)
void pty_proc_close(PtyProc *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
Process *proc = (Process *)ptyproc;
Proc *proc = (Proc *)ptyproc;
pty_process_close_master(ptyproc);
pty_proc_close_master(ptyproc);
if (ptyproc->finish_wait != NULL) {
UnregisterWaitEx(ptyproc->finish_wait, NULL);
ptyproc->finish_wait = NULL;
uv_close((uv_handle_t *)&ptyproc->wait_eof_timer, NULL);
}
if (ptyproc->process_handle != NULL) {
CloseHandle(ptyproc->process_handle);
ptyproc->process_handle = NULL;
if (ptyproc->proc_handle != NULL) {
CloseHandle(ptyproc->proc_handle);
ptyproc->proc_handle = NULL;
}
if (proc->internal_close_cb) {
@ -192,17 +192,17 @@ void pty_process_close(PtyProcess *ptyproc)
}
}
void pty_process_close_master(PtyProcess *ptyproc)
void pty_proc_close_master(PtyProc *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
}
void pty_process_teardown(Loop *loop)
void pty_proc_teardown(Loop *loop)
FUNC_ATTR_NONNULL_ALL
{
}
static void pty_process_connect_cb(uv_connect_t *req, int status)
static void pty_proc_connect_cb(uv_connect_t *req, int status)
FUNC_ATTR_NONNULL_ALL
{
assert(status == 0);
@ -212,23 +212,23 @@ static void pty_process_connect_cb(uv_connect_t *req, int status)
static void wait_eof_timer_cb(uv_timer_t *wait_eof_timer)
FUNC_ATTR_NONNULL_ALL
{
PtyProcess *ptyproc = wait_eof_timer->data;
Process *proc = (Process *)ptyproc;
PtyProc *ptyproc = wait_eof_timer->data;
Proc *proc = (Proc *)ptyproc;
assert(ptyproc->finish_wait != NULL);
if (proc->out.s.closed || proc->out.did_eof || !uv_is_readable(proc->out.s.uvstream)) {
uv_timer_stop(&ptyproc->wait_eof_timer);
pty_process_finish2(ptyproc);
pty_proc_finish2(ptyproc);
}
}
static void pty_process_finish2(PtyProcess *ptyproc)
static void pty_proc_finish2(PtyProc *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
Process *proc = (Process *)ptyproc;
Proc *proc = (Proc *)ptyproc;
DWORD exit_code = 0;
GetExitCodeProcess(ptyproc->process_handle, &exit_code);
GetExitCodeProcess(ptyproc->proc_handle, &exit_code);
proc->status = proc->exit_signal ? 128 + proc->exit_signal : (int)exit_code;
proc->internal_exit_cb(proc);
@ -427,14 +427,14 @@ cleanup:
return rc;
}
PtyProcess pty_process_init(Loop *loop, void *data)
PtyProc pty_proc_init(Loop *loop, void *data)
{
PtyProcess rv;
rv.process = process_init(loop, kProcessTypePty, data);
PtyProc rv;
rv.proc = proc_init(loop, kProcTypePty, data);
rv.width = 80;
rv.height = 24;
rv.conpty = NULL;
rv.finish_wait = NULL;
rv.process_handle = NULL;
rv.proc_handle = NULL;
return rv;
}

View File

@ -1,20 +1,20 @@
#pragma once
// IWYU pragma: private, include "nvim/os/pty_process.h"
// IWYU pragma: private, include "nvim/os/pty_proc.h"
#include <uv.h>
#include "nvim/event/process.h"
#include "nvim/event/proc.h"
#include "nvim/lib/queue_defs.h"
#include "nvim/os/pty_conpty_win.h"
typedef struct pty_process {
Process process;
Proc proc;
uint16_t width, height;
conpty_t *conpty;
HANDLE finish_wait;
HANDLE process_handle;
HANDLE proc_handle;
uv_timer_t wait_eof_timer;
} PtyProcess;
} PtyProc;
// Structure used by build_cmd_line()
typedef struct arg_node {
@ -23,5 +23,5 @@ typedef struct arg_node {
} ArgNode;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/pty_process_win.h.generated.h"
# include "os/pty_proc_win.h.generated.h"
#endif

View File

@ -1,7 +0,0 @@
#pragma once
#ifdef MSWIN
# include "nvim/os/pty_process_win.h"
#else
# include "nvim/os/pty_process_unix.h"
#endif

View File

@ -14,10 +14,10 @@
#include "nvim/eval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/event/defs.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/libuv_proc.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/process.h"
#include "nvim/event/proc.h"
#include "nvim/event/rstream.h"
#include "nvim/event/stream.h"
#include "nvim/event/wstream.h"
@ -872,12 +872,12 @@ static int do_os_system(char **argv, const char *input, size_t len, char **outpu
char prog[MAXPATHL];
xstrlcpy(prog, argv[0], MAXPATHL);
LibuvProcess uvproc = libuv_process_init(&main_loop, &buf);
Process *proc = &uvproc.process;
LibuvProc uvproc = libuv_proc_init(&main_loop, &buf);
Proc *proc = &uvproc.proc;
MultiQueue *events = multiqueue_new_child(main_loop.events);
proc->events = events;
proc->argv = argv;
int status = process_spawn(proc, has_input, true, true);
int status = proc_spawn(proc, has_input, true, true);
if (status) {
loop_poll_events(&main_loop, 0);
// Failed, probably 'shell' is not executable.
@ -910,7 +910,7 @@ static int do_os_system(char **argv, const char *input, size_t len, char **outpu
if (!wstream_write(&proc->in, input_buffer)) {
// couldn't write, stop the process and tell the user about it
process_stop(proc);
proc_stop(proc);
return -1;
}
// close the input stream after everything is written
@ -927,7 +927,7 @@ static int do_os_system(char **argv, const char *input, size_t len, char **outpu
msg_no_more = true;
lines_left = -1;
}
int exitcode = process_wait(proc, -1, NULL);
int exitcode = proc_wait(proc, -1, NULL);
if (!got_int && out_data_decide_throttle(0)) {
// Last chunk of output was skipped; display it now.
out_data_ring(NULL, SIZE_MAX);
@ -1292,7 +1292,7 @@ static void shell_write_cb(Stream *stream, void *data, int status)
msg_schedule_semsg(_("E5677: Error writing input to shell-command: %s"),
uv_err_name(status));
}
stream_close(stream, NULL, NULL, false);
stream_may_close(stream, false);
}
/// Applies 'shellxescape' (p_sxe) and 'shellxquote' (p_sxq) to a command.

View File

@ -950,8 +950,8 @@ void time_msg(const char *mesg, const proftime_T *start)
/// Initializes the `time_fd` stream for the --startuptime report.
///
/// @param fname startuptime report file path
/// @param process_name name of the current Nvim process to write in the report.
void time_init(const char *fname, const char *process_name)
/// @param proc_name name of the current Nvim process to write in the report.
void time_init(const char *fname, const char *proc_name)
{
const size_t bufsize = 8192; // Big enough for the entire --startuptime report.
time_fd = fopen(fname, "a");
@ -972,7 +972,7 @@ void time_init(const char *fname, const char *process_name)
semsg("time_init: setvbuf failed: %d %s", r, uv_err_name(r));
return;
}
fprintf(time_fd, "--- Startup times for process: %s ---\n", process_name);
fprintf(time_fd, "--- Startup times for process: %s ---\n", proc_name);
}
/// Flushes the startuptimes to disk for the current process

View File

@ -6875,7 +6875,8 @@ bool set_ref_in_quickfix(int copyID)
// In a location list window and none of the other windows is
// referring to this location list. Mark the location list
// context as still in use.
if (mark_quickfix_ctx(win->w_llist_ref, copyID)) {
if (mark_quickfix_ctx(win->w_llist_ref, copyID)
|| mark_quickfix_user_data(win->w_llist_ref, copyID)) {
return true;
}
}

View File

@ -3561,6 +3561,166 @@ garray_T *fuzzy_match_str_with_pos(char *const str, const char *const pat)
return match_positions;
}
/// This function searches for a fuzzy match of the pattern `pat` within the
/// line pointed to by `*ptr`. It splits the line into words, performs fuzzy
/// matching on each word, and returns the length and position of the first
/// matched word.
static bool fuzzy_match_str_in_line(char **ptr, char *pat, int *len, pos_T *current_pos)
{
char *str = *ptr;
char *strBegin = str;
char *end = NULL;
char *start = NULL;
bool found = false;
if (str == NULL || pat == NULL) {
return found;
}
while (*str != NUL) {
// Skip non-word characters
start = find_word_start(str);
if (*start == NUL) {
break;
}
end = find_word_end(start);
// Extract the word from start to end
char save_end = *end;
*end = NUL;
// Perform fuzzy match
int result = fuzzy_match_str(start, pat);
*end = save_end;
if (result > 0) {
*len = (int)(end - start);
current_pos->col += (int)(end - strBegin);
found = true;
*ptr = start;
break;
}
// Move to the end of the current word for the next iteration
str = end;
// Ensure we continue searching after the current word
while (*str != NUL && !vim_iswordp(str)) {
MB_PTR_ADV(str);
}
}
return found;
}
/// Search for the next fuzzy match in the specified buffer.
/// This function attempts to find the next occurrence of the given pattern
/// in the buffer, starting from the current position. It handles line wrapping
/// and direction of search.
///
/// Return true if a match is found, otherwise false.
bool search_for_fuzzy_match(buf_T *buf, pos_T *pos, char *pattern, int dir, pos_T *start_pos,
int *len, char **ptr, bool whole_line)
{
pos_T current_pos = *pos;
pos_T circly_end;
bool found_new_match = false;
bool looped_around = false;
char *next_word_end = NULL;
char *match_word = NULL;
if (whole_line) {
current_pos.lnum += dir;
}
if (buf == curbuf) {
circly_end = *start_pos;
} else {
circly_end.lnum = buf->b_ml.ml_line_count;
circly_end.col = 0;
circly_end.coladd = 0;
}
while (true) {
// Check if looped around and back to start position
if (looped_around && equalpos(current_pos, circly_end)) {
break;
}
// Ensure current_pos is valid
if (current_pos.lnum >= 1 && current_pos.lnum <= buf->b_ml.ml_line_count) {
// Get the current line buffer
*ptr = ml_get_buf(buf, current_pos.lnum);
// If ptr is end of line is reached, move to next line
// or previous line based on direction
if (**ptr != NUL) {
if (!whole_line) {
*ptr += current_pos.col;
// Try to find a fuzzy match in the current line starting from current position
found_new_match = fuzzy_match_str_in_line(ptr, pattern, len, &current_pos);
if (found_new_match) {
if (ctrl_x_mode_normal()) {
match_word = xstrnsave(*ptr, (size_t)(*len));
if (strcmp(match_word, pattern) == 0) {
next_word_end = find_word_start(*ptr + *len);
if (*next_word_end != NUL && *next_word_end != NL) {
// Find end of the word.
while (*next_word_end != NUL) {
int l = utfc_ptr2len(next_word_end);
if (l < 2 && !vim_iswordc(*next_word_end)) {
break;
}
next_word_end += l;
}
} else if (looped_around) {
found_new_match = false;
}
*len = (int)(next_word_end - *ptr);
current_pos.col = *len;
}
xfree(match_word);
}
*pos = current_pos;
break;
} else if (looped_around && current_pos.lnum == circly_end.lnum) {
break;
}
} else {
if (fuzzy_match_str(*ptr, pattern) > 0) {
found_new_match = true;
*pos = current_pos;
*len = (int)strlen(*ptr);
break;
}
}
}
}
// Move to the next line or previous line based on direction
if (dir == FORWARD) {
if (++current_pos.lnum > buf->b_ml.ml_line_count) {
if (p_ws) {
current_pos.lnum = 1;
looped_around = true;
} else {
break;
}
}
} else {
if (--current_pos.lnum < 1) {
if (p_ws) {
current_pos.lnum = buf->b_ml.ml_line_count;
looped_around = true;
} else {
break;
}
}
}
current_pos.col = 0;
}
return found_new_match;
}
/// Copy a list of fuzzy matches into a string list after sorting the matches by
/// the fuzzy score. Frees the memory allocated for "fuzmatch".
void fuzzymatches_to_strmatches(fuzmatch_str_T *const fuzmatch, char ***const matches,

View File

@ -22,6 +22,7 @@
#include "nvim/memory_defs.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/os/os.h"
#include "nvim/os/os_defs.h"
#include "nvim/tui/tui.h"
#include "nvim/tui/tui_defs.h"
@ -126,6 +127,11 @@ void ui_client_run(bool remote_ui)
ui_client_attach(width, height, term, rgb);
// TODO(justinmk): this is for log_spec. Can remove this after nvim_log #7062 is merged.
if (os_env_exists("__NVIM_TEST_LOG")) {
ELOG("test log message");
}
// os_exit() will be invoked when the client channel detaches
while (true) {
LOOP_PROCESS_EVENTS(&main_loop, resize_events, -1);

View File

@ -14,7 +14,7 @@ EXTERN size_t grid_line_buf_size INIT( = 0);
EXTERN schar_T *grid_line_buf_char INIT( = NULL);
EXTERN sattr_T *grid_line_buf_attr INIT( = NULL);
// ID of the ui client channel. If zero, the client is not running.
// Client-side UI channel. Zero during early startup or if not a (--remote-ui) UI client.
EXTERN uint64_t ui_client_channel_id INIT( = 0);
// exit status from embedded nvim process

View File

@ -103,7 +103,7 @@ Debugging tests
DBG 2022-06-15T18:37:45.227 T57.58016.0/c UI: stop
INF 2022-06-15T18:37:45.227 T57.58016.0/c os_exit:595: Nvim exit: 0
DBG 2022-06-15T18:37:45.229 T57.58016.0 read_cb:118: closing Stream (0x7fd5d700ea18): EOF (end of file)
INF 2022-06-15T18:37:45.229 T57.58016.0 on_process_exit:400: exited: pid=58017 status=0 stoptime=0
INF 2022-06-15T18:37:45.229 T57.58016.0 on_proc_exit:400: exited: pid=58017 status=0 stoptime=0
```
- You can set `$GDB` to [run functional tests under gdbserver](https://github.com/neovim/neovim/pull/1527):

View File

@ -114,6 +114,7 @@ function Session:request(method, ...)
return true, result
end
--- Runs the event loop.
function Session:run(request_cb, notification_cb, setup_cb, timeout)
local function on_request(method, args, response)
coroutine_exec(request_cb, method, args, function(status, result, flag)

View File

@ -1,6 +1,6 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local clear = n.clear
local feed_command = n.feed_command

View File

@ -1,6 +1,6 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local uv = vim.uv
local clear, command, testprg = n.clear, n.command, n.testprg
@ -199,7 +199,7 @@ end)
describe('autocmd TextChangedT', function()
clear()
local screen = tt.screen_setup()
local screen = tt.setup_screen()
it('works', function()
command('autocmd TextChangedT * ++once let g:called = 1')

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local clear = n.clear
local eq = t.eq

View File

@ -1,5 +1,6 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.testterm')
local assert_log = t.assert_log
local clear = n.clear
@ -29,10 +30,54 @@ describe('log', function()
assert(request('nvim__stats').log_skip <= 13)
end)
it('messages are formatted with name or test id', function()
it('TUI client name is "ui"', function()
local function setup(env)
clear()
-- Start Nvim with builtin UI.
local screen = tt.setup_child_nvim({
'-u',
'NONE',
'-i',
'NONE',
'--cmd',
n.nvim_set,
}, {
env = env,
})
screen:expect([[
{1: } |
~ |*4
|
{3:-- TERMINAL --} |
]])
end
-- Without $NVIM parent.
setup({
NVIM = '',
NVIM_LISTEN_ADDRESS = '',
NVIM_LOG_FILE = testlog,
__NVIM_TEST_LOG = '1',
})
-- Example:
-- ERR 2024-09-11T16:40:02.421 ui.47056 ui_client_run:165: test log message
assert_log(' ui%.%d+% +ui_client_run:%d+: test log message', testlog, 100)
-- With $NVIM parent.
setup({
NVIM_LOG_FILE = testlog,
__NVIM_TEST_LOG = '1',
})
-- Example:
-- ERR 2024-09-11T16:41:17.539 ui/c/T2.47826.0 ui_client_run:165: test log message
local tid = _G._nvim_test_id
assert_log(' ui/c/' .. tid .. '%.%d+%.%d +ui_client_run:%d+: test log message', testlog, 100)
end)
it('formats messages with session name or test id', function()
-- Examples:
-- ERR 2022-05-29T12:30:03.800 T2 log_init:110: test log message
-- ERR 2022-05-29T12:30:03.814 T2/child log_init:110: test log message
-- ERR 2024-09-11T16:44:33.794 T3.49429.0 server_init:58: test log message
-- ERR 2024-09-11T16:44:33.823 c/T3.49429.0 server_init:58: test log message
clear({
env = {
@ -47,10 +92,10 @@ describe('log', function()
exec_lua([[
local j1 = vim.fn.jobstart({ vim.v.progpath, '-es', '-V1', '+foochild', '+qa!' }, vim.empty_dict())
vim.fn.jobwait({ j1 }, 10000)
vim.fn.jobwait({ j1 }, 5000)
]])
-- Child Nvim spawned by jobstart() appends "/c" to parent name.
assert_log('%.%d+%.%d/c +server_init:%d+: test log message', testlog, 100)
-- Child Nvim spawned by jobstart() prepends "c/" to parent name.
assert_log('c/' .. tid .. '%.%d+%.%d +server_init:%d+: test log message', testlog, 100)
end)
end)

View File

@ -40,11 +40,22 @@ describe(':checkhealth', function()
matches('ERROR $VIM .* zub', curbuf_contents())
end)
it('completions can be listed via getcompletion()', function()
clear()
it('getcompletion()', function()
clear { args = { '-u', 'NORC', '+set runtimepath+=test/functional/fixtures' } }
eq('vim.deprecated', getcompletion('vim', 'checkhealth')[1])
eq('vim.provider', getcompletion('vim.prov', 'checkhealth')[1])
eq('vim.lsp', getcompletion('vim.ls', 'checkhealth')[1])
-- "test_plug/health/init.lua" should complete as "test_plug", not "test_plug.health". #30342
eq({
'test_plug',
'test_plug.full_render',
'test_plug.submodule',
'test_plug.submodule_empty',
'test_plug.success1',
'test_plug.success2',
}, getcompletion('test_plug', 'checkhealth'))
end)
it('completion checks for vim.health._complete() return type #28456', function()
@ -57,11 +68,9 @@ describe(':checkhealth', function()
end)
end)
describe('health.vim', function()
describe('vim.health', function()
before_each(function()
clear { args = { '-u', 'NORC' } }
-- Provides healthcheck functions
command('set runtimepath+=test/functional/fixtures')
clear { args = { '-u', 'NORC', '+set runtimepath+=test/functional/fixtures' } }
end)
describe(':checkhealth', function()
@ -207,9 +216,7 @@ end)
describe(':checkhealth window', function()
before_each(function()
clear { args = { '-u', 'NORC' } }
-- Provides healthcheck functions
command('set runtimepath+=test/functional/fixtures')
clear { args = { '-u', 'NORC', '+set runtimepath+=test/functional/fixtures' } }
command('set nofoldenable nowrap laststatus=0')
end)

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local clear, eq, api = n.clear, t.eq, n.api
local feed = n.feed
local feed_data = tt.feed_data
@ -17,7 +17,7 @@ describe(':terminal altscreen', function()
before_each(function()
clear()
screen = tt.screen_setup()
screen = tt.setup_screen()
feed_data({
'line1',
'line2',

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local ok = t.ok
if t.skip(t.is_os('win')) then

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local assert_alive = n.assert_alive
local feed, clear = n.feed, n.clear
@ -29,7 +29,7 @@ describe(':terminal buffer', function()
before_each(function()
clear()
command('set modifiable swapfile undolevels=20')
screen = tt.screen_setup()
screen = tt.setup_screen()
end)
it('terminal-mode forces various options', function()
@ -574,7 +574,7 @@ if is_os('win') then
feed_command('set modifiable swapfile undolevels=20')
poke_eventloop()
local cmd = { 'cmd.exe', '/K', 'PROMPT=$g$s' }
screen = tt.screen_setup(nil, cmd)
screen = tt.setup_screen(nil, cmd)
end)
it('"put" operator sends data normally', function()

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local feed, clear = n.feed, n.clear
local testprg, command = n.testprg, n.command
@ -18,7 +18,7 @@ describe(':terminal cursor', function()
before_each(function()
clear()
screen = tt.screen_setup()
screen = tt.setup_screen()
end)
it('moves the screen cursor when focused', function()

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local feed, clear = n.feed, n.clear
local api = n.api

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local clear, eq, eval = n.clear, t.eq, n.eval
local feed, api, command = n.feed, n.api, n.command
local feed_data = tt.feed_data
@ -14,7 +14,7 @@ describe(':terminal mouse', function()
before_each(function()
clear()
api.nvim_set_option_value('statusline', '==========', {})
screen = tt.screen_setup()
screen = tt.setup_screen()
command('highlight StatusLine NONE')
command('highlight StatusLineNC NONE')
command('highlight StatusLineTerm NONE')

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local clear, eq = n.clear, t.eq
local feed, testprg = n.feed, n.testprg
@ -22,7 +22,7 @@ describe(':terminal scrollback', function()
before_each(function()
clear()
screen = tt.screen_setup(nil, nil, 30)
screen = tt.setup_screen(nil, nil, 30)
end)
describe('when the limit is exceeded', function()
@ -399,9 +399,9 @@ describe("'scrollback' option", function()
it('set to 0 behaves as 1', function()
local screen
if is_os('win') then
screen = tt.screen_setup(nil, { 'cmd.exe' }, 30)
screen = tt.setup_screen(nil, { 'cmd.exe' }, 30)
else
screen = tt.screen_setup(nil, { 'sh' }, 30)
screen = tt.setup_screen(nil, { 'sh' }, 30)
end
api.nvim_set_option_value('scrollback', 0, {})
@ -416,10 +416,10 @@ describe("'scrollback' option", function()
local screen
if is_os('win') then
command([[let $PROMPT='$$']])
screen = tt.screen_setup(nil, { 'cmd.exe' }, 30)
screen = tt.setup_screen(nil, { 'cmd.exe' }, 30)
else
command('let $PS1 = "$"')
screen = tt.screen_setup(nil, { 'sh' }, 30)
screen = tt.setup_screen(nil, { 'sh' }, 30)
end
api.nvim_set_option_value('scrollback', 200, {})
@ -480,8 +480,8 @@ describe("'scrollback' option", function()
end)
it('deletes extra lines immediately', function()
-- Scrollback is 10 on screen_setup
local screen = tt.screen_setup(nil, nil, 30)
-- Scrollback is 10 on setup_screen
local screen = tt.setup_screen(nil, nil, 30)
local lines = {}
for i = 1, 30 do
table.insert(lines, 'line' .. tostring(i))

View File

@ -7,7 +7,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local eq = t.eq
local feed_data = tt.feed_data
@ -2111,7 +2111,7 @@ describe('TUI', function()
finally(function()
os.remove('testF')
end)
local screen = tt.screen_setup(
local screen = tt.setup_screen(
0,
('"%s" -u NONE -i NONE --cmd "set noswapfile noshowcmd noruler" --cmd "normal iabc" > /dev/null 2>&1 && cat testF && rm testF'):format(
nvim_prog

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local feed_data = tt.feed_data
local feed, clear = n.feed, n.clear
local poke_eventloop = n.poke_eventloop
@ -37,7 +37,7 @@ describe(':terminal window', function()
before_each(function()
clear()
screen = tt.screen_setup()
screen = tt.setup_screen()
end)
it('sets topline correctly #8556', function()
@ -198,7 +198,7 @@ describe(':terminal with multigrid', function()
before_each(function()
clear()
screen = tt.screen_setup(0, nil, 50, nil, { ext_multigrid = true })
screen = tt.setup_screen(0, nil, 50, nil, { ext_multigrid = true })
end)
it('resizes to requested size', function()

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local assert_alive = n.assert_alive
local clear = n.clear
local feed = n.feed
@ -22,7 +22,7 @@ describe(':terminal', function()
-- set the statusline to a constant value because of variables like pid
-- and current directory and to improve visibility of splits
api.nvim_set_option_value('statusline', '==========', {})
screen = tt.screen_setup(3)
screen = tt.setup_screen(3)
command('highlight StatusLine NONE')
command('highlight StatusLineNC NONE')
command('highlight StatusLineTerm NONE')

View File

@ -250,6 +250,8 @@ function M.set_method_error(err)
method_error = err
end
--- Runs the event loop of the given session.
---
--- @param lsession test.Session
--- @param request_cb function?
--- @param notification_cb function?
@ -296,6 +298,7 @@ function M.run_session(lsession, request_cb, notification_cb, setup_cb, timeout)
return lsession.eof_err
end
--- Runs the event loop of the current global session.
function M.run(request_cb, notification_cb, setup_cb, timeout)
assert(session)
return M.run_session(session, request_cb, notification_cb, setup_cb, timeout)

View File

@ -1,6 +1,13 @@
-- To test tui/input.c, this module spawns `nvim` inside :terminal and sends
-- bytes via jobsend(). Note: the functional/testutil.lua test-session methods
-- operate on the _host_ session, _not_ the child session.
-- Functions to test :terminal and the Nvim TUI.
-- Starts a child process in a `:terminal` and sends bytes to the child via nvim_chan_send().
-- Note: the global functional/testutil.lua test-session is _host_ session, _not_
-- the child session.
--
-- - Use `setup_screen()` to test `:terminal` behavior with an arbitrary command.
-- - Use `setup_child_nvim()` to test the Nvim TUI.
-- - NOTE: Only use this if your test actually needs the full lifecycle/capabilities of the
-- builtin Nvim TUI. Most tests should just use `Screen.new()` directly, or plain old API calls.
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
@ -9,18 +16,20 @@ local exec_lua = n.exec_lua
local api = n.api
local nvim_prog = n.nvim_prog
local function feed_data(data)
local M = {}
function M.feed_data(data)
if type(data) == 'table' then
data = table.concat(data, '\n')
end
exec_lua('vim.api.nvim_chan_send(vim.b.terminal_job_id, ...)', data)
end
local function feed_termcode(data)
feed_data('\027' .. data)
function M.feed_termcode(data)
M.feed_data('\027' .. data)
end
local function make_lua_executor(session)
function M.make_lua_executor(session)
return function(code, ...)
local status, rv = session:request('nvim_exec_lua', code, { ... })
if not status then
@ -34,60 +43,68 @@ end
-- some t for controlling the terminal. the codes were taken from
-- infocmp xterm-256color which is less what libvterm understands
-- civis/cnorm
local function hide_cursor()
feed_termcode('[?25l')
function M.hide_cursor()
M.feed_termcode('[?25l')
end
local function show_cursor()
feed_termcode('[?25h')
function M.show_cursor()
M.feed_termcode('[?25h')
end
-- smcup/rmcup
local function enter_altscreen()
feed_termcode('[?1049h')
function M.enter_altscreen()
M.feed_termcode('[?1049h')
end
local function exit_altscreen()
feed_termcode('[?1049l')
function M.exit_altscreen()
M.feed_termcode('[?1049l')
end
-- character attributes
local function set_fg(num)
feed_termcode('[38;5;' .. num .. 'm')
function M.set_fg(num)
M.feed_termcode('[38;5;' .. num .. 'm')
end
local function set_bg(num)
feed_termcode('[48;5;' .. num .. 'm')
function M.set_bg(num)
M.feed_termcode('[48;5;' .. num .. 'm')
end
local function set_bold()
feed_termcode('[1m')
function M.set_bold()
M.feed_termcode('[1m')
end
local function set_italic()
feed_termcode('[3m')
function M.set_italic()
M.feed_termcode('[3m')
end
local function set_underline()
feed_termcode('[4m')
function M.set_underline()
M.feed_termcode('[4m')
end
local function set_underdouble()
feed_termcode('[4:2m')
function M.set_underdouble()
M.feed_termcode('[4:2m')
end
local function set_undercurl()
feed_termcode('[4:3m')
function M.set_undercurl()
M.feed_termcode('[4:3m')
end
local function set_strikethrough()
feed_termcode('[9m')
function M.set_strikethrough()
M.feed_termcode('[9m')
end
local function clear_attrs()
feed_termcode('[0;10m')
function M.clear_attrs()
M.feed_termcode('[0;10m')
end
-- mouse
local function enable_mouse()
feed_termcode('[?1002h')
function M.enable_mouse()
M.feed_termcode('[?1002h')
end
local function disable_mouse()
feed_termcode('[?1002l')
function M.disable_mouse()
M.feed_termcode('[?1002l')
end
local default_command = { testprg('tty-test') }
local function screen_setup(extra_rows, command, cols, env, screen_opts)
--- Runs `cmd` in a :terminal, and returns a `Screen` object.
---
---@param extra_rows? integer Extra rows to add to the default screen.
---@param cmd? string|string[] Command to run in the terminal (default: `{ 'tty-test' }`)
---@param cols? integer Create screen with this many columns (default: 50)
---@param env? table Environment set on the `cmd` job.
---@param screen_opts? table Options for `Screen.new()`.
---@return test.functional.ui.screen # Screen attached to the global (not child) Nvim session.
function M.setup_screen(extra_rows, cmd, cols, env, screen_opts)
extra_rows = extra_rows and extra_rows or 0
command = command and command or default_command
cmd = cmd and cmd or default_command
cols = cols and cols or 50
api.nvim_command('highlight TermCursor cterm=reverse')
@ -120,7 +137,7 @@ local function screen_setup(extra_rows, command, cols, env, screen_opts)
screen:attach(screen_opts or { rgb = false })
api.nvim_command('enew')
api.nvim_call_function('termopen', { command, env and { env = env } or nil })
api.nvim_call_function('termopen', { cmd, env and { env = env } or nil })
api.nvim_input('<CR>')
local vim_errmsg = api.nvim_eval('v:errmsg')
if vim_errmsg and '' ~= vim_errmsg then
@ -133,7 +150,7 @@ local function screen_setup(extra_rows, command, cols, env, screen_opts)
-- tty-test puts the terminal into raw mode and echoes input. Tests work by
-- feeding termcodes to control the display and asserting by screen:expect.
if command == default_command and screen_opts == nil then
if cmd == default_command and screen_opts == nil then
-- Wait for "tty ready" to be printed before each test or the terminal may
-- still be in canonical mode (will echo characters for example).
local empty_line = (' '):rep(cols)
@ -160,37 +177,24 @@ local function screen_setup(extra_rows, command, cols, env, screen_opts)
return screen
end
local function setup_child_nvim(args, opts)
--- Spawns Nvim with `args` in a :terminal, and returns a `Screen` object.
---
--- @note Only use this if you actually need the full lifecycle/capabilities of the builtin Nvim
--- TUI. Most tests should just use `Screen.new()` directly, or plain old API calls.
---
---@param args? string[] Args passed to child Nvim.
---@param opts? table Options
---@return test.functional.ui.screen # Screen attached to the global (not child) Nvim session.
function M.setup_child_nvim(args, opts)
opts = opts or {}
local argv = { nvim_prog, unpack(args) }
local argv = { nvim_prog, unpack(args or {}) }
local env = opts.env or {}
if not env.VIMRUNTIME then
env.VIMRUNTIME = os.getenv('VIMRUNTIME')
end
return screen_setup(opts.extra_rows, argv, opts.cols, env)
return M.setup_screen(opts.extra_rows, argv, opts.cols, env)
end
return {
feed_data = feed_data,
feed_termcode = feed_termcode,
make_lua_executor = make_lua_executor,
hide_cursor = hide_cursor,
show_cursor = show_cursor,
enter_altscreen = enter_altscreen,
exit_altscreen = exit_altscreen,
set_fg = set_fg,
set_bg = set_bg,
set_bold = set_bold,
set_italic = set_italic,
set_underline = set_underline,
set_underdouble = set_underdouble,
set_undercurl = set_undercurl,
set_strikethrough = set_strikethrough,
clear_attrs = clear_attrs,
enable_mouse = enable_mouse,
disable_mouse = disable_mouse,
screen_setup = screen_setup,
setup_child_nvim = setup_child_nvim,
}
return M

View File

@ -8,6 +8,7 @@ local exec_lua = n.exec_lua
local pcall_err = t.pcall_err
local matches = t.matches
local insert = n.insert
local NIL = vim.NIL
before_each(clear)
@ -15,10 +16,12 @@ describe('treesitter language API', function()
-- error tests not requiring a parser library
it('handles missing language', function()
eq(
".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
'.../treesitter.lua:0: Parser not found.',
pcall_err(exec_lua, "parser = vim.treesitter.get_parser(0, 'borklang')")
)
eq(NIL, exec_lua("return vim.treesitter._get_parser(0, 'borklang')"))
-- actual message depends on platform
matches(
"Failed to load parser for language 'borklang': uv_dlopen: .+",
@ -105,9 +108,10 @@ describe('treesitter language API', function()
command('set filetype=borklang')
-- Should throw an error when filetype changes to borklang
eq(
".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
'.../treesitter.lua:0: Parser not found.',
pcall_err(exec_lua, "new_parser = vim.treesitter.get_parser(0, 'borklang')")
)
eq(NIL, exec_lua("return vim.treesitter._get_parser(0, 'borklang')"))
end
)

View File

@ -135,9 +135,7 @@ void ui_refresh(void)
insert(test_text)
eq(
'.../treesitter.lua:0: There is no parser available for buffer 1 and one'
.. ' could not be created because lang could not be determined. Either'
.. ' pass lang or set the buffer filetype',
'.../treesitter.lua:0: Parser not found.',
pcall_err(exec_lua, 'vim.treesitter.get_parser(0)')
)

View File

@ -1078,6 +1078,44 @@ describe('CursorLine and CursorLineNr highlights', function()
]])
end)
-- oldtest: Test_cursorline_screenline_resize()
it("'cursorlineopt' screenline is updated on window resize", function()
local screen = Screen.new(75, 8)
screen:attach()
exec([[
50vnew
call setline(1, repeat('xyz ', 30))
setlocal number cursorline cursorlineopt=screenline
normal! $
]])
screen:expect([[
{8: 1 }xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xy |
{8: }z xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz {1:~ }|
{8: }{21:xyz xyz xyz xyz xyz xyz xyz^ }{1:~ }|
{1:~ }{1:~ }|*3
{3:[No Name] [+] }{2:[No Name] }|
|
]])
command('vertical resize -4')
screen:expect([[
{8: 1 }xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xy |
{8: }z xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz {1:~ }|
{8: }{21:xyz xyz xyz xyz xyz xyz xyz xyz xyz^ }{1:~ }|
{1:~ }{1:~ }|*3
{3:[No Name] [+] }{2:[No Name] }|
|
]])
command('set cpoptions+=n')
screen:expect([[
{8: 1 }xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xy |
z xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz {1:~ }|
{21:xyz xyz xyz xyz xyz xyz xyz xyz^ }{1:~ }|
{1:~ }{1:~ }|*3
{3:[No Name] [+] }{2:[No Name] }|
|
]])
end)
-- oldtest: Test_cursorline_after_yank()
it('always updated. vim-patch:8.1.0849', function()
local screen = Screen.new(50, 5)

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil')
local tt = require('test.functional.testterm')
local clear, insert = n.clear, n.insert
local command = n.command

Some files were not shown because too many files have changed in this diff Show More