mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
Compare commits
56 Commits
e990b7fca1
...
e5a6044eb7
Author | SHA1 | Date | |
---|---|---|---|
|
e5a6044eb7 | ||
|
4c5bce9cb4 | ||
|
5d7853f229 | ||
|
f279d1ae33 | ||
|
9ddfcb64bf | ||
|
8e81212e15 | ||
|
648d6426c8 | ||
|
f0334c2c71 | ||
|
c8e3618e0e | ||
|
ed832b9ddf | ||
|
8a2aec9974 | ||
|
3a88113246 | ||
|
08153ddd1c | ||
|
003b8a251d | ||
|
0cfbc6eaff | ||
|
95b65a7554 | ||
|
e37404f7fe | ||
|
b40ec083ae | ||
|
d338ec9cb2 | ||
|
5ddf2ab768 | ||
|
3d1110674e | ||
|
738a84de09 | ||
|
439d031742 | ||
|
c81cb02dd6 | ||
|
fa99afe35e | ||
|
9570ad24f5 | ||
|
d60c753cff | ||
|
e36e68d35c | ||
|
f4d823b123 | ||
|
76aa3e52be | ||
|
f9108378b7 | ||
|
975aeee537 | ||
|
882a450a29 | ||
|
220b8aa6fe | ||
|
51088b67cb | ||
|
34ded4d97b | ||
|
b6e350a6b4 | ||
|
7b7c95dac9 | ||
|
45e76acaa0 | ||
|
fdd3a9cdf7 | ||
|
d1d7d54680 | ||
|
ceddaedfad | ||
|
ea2d949351 | ||
|
ae9674704a | ||
|
96128a5076 | ||
|
137f98cf64 | ||
|
ef8067a19d | ||
|
60ea046741 | ||
|
50a576ba57 | ||
|
a8fc799e8b | ||
|
13c739a664 | ||
|
bcae8be91f | ||
|
61e9137394 | ||
|
6913c5e1d9 | ||
|
318c0415d5 | ||
|
97f8d1de1c |
1
BUILD.md
1
BUILD.md
@ -12,7 +12,6 @@
|
||||
- To build on Windows, see the [Building on Windows](#building-on-windows) section. _MSVC (Visual Studio) is recommended._
|
||||
4. `sudo make install`
|
||||
- Default install location is `/usr/local`
|
||||
- On Debian/Ubuntu, instead of installing files directly with `sudo make install`, you can run `cd build && cpack -G DEB && sudo dpkg -i nvim-linux64.deb` to build DEB-package and install it. This should help ensuring the clean removal of installed files.
|
||||
|
||||
**Notes**:
|
||||
- From the repository's root directory, running `make` will download and build all the needed dependencies and put the `nvim` executable in `build/bin`.
|
||||
|
@ -160,7 +160,6 @@ These dependencies are "vendored" (inlined), we must update the sources manually
|
||||
* Needs to be updated when LPeg is updated.
|
||||
* `src/bit.c`: only for PUC lua: port of `require'bit'` from luajit https://bitop.luajit.org/
|
||||
* `runtime/lua/coxpcall.lua`: coxpcall (only needed for PUC lua, builtin to luajit)
|
||||
* `src/termkey`: [libtermkey](https://github.com/neovim/libtermkey)
|
||||
|
||||
Other dependencies
|
||||
--------------------------
|
||||
|
2
Makefile
2
Makefile
@ -14,7 +14,7 @@ else
|
||||
TOUCH := touch
|
||||
RM := rm -rf
|
||||
CMAKE := $(shell (command -v cmake3 || echo cmake))
|
||||
CMAKE_GENERATOR ?= $(shell (command -v ninja > /dev/null 2>&1 && echo "Ninja") || echo "Unix Makefiles")
|
||||
CMAKE_GENERATOR ?= "$(shell (command -v ninja > /dev/null 2>&1 && echo "Ninja") || echo "Unix Makefiles")"
|
||||
define rmdir
|
||||
rm -rf $1
|
||||
endef
|
||||
|
@ -1,5 +1,5 @@
|
||||
LIBUV_URL https://github.com/libuv/libuv/archive/v1.48.0.tar.gz
|
||||
LIBUV_SHA256 8c253adb0f800926a6cbd1c6576abae0bc8eb86a4f891049b72f9e5b7dc58f33
|
||||
LIBUV_URL https://github.com/libuv/libuv/archive/0a00e80c3686b93eccb9a801954e86bd7d7fe6ab.tar.gz
|
||||
LIBUV_SHA256 8d240ad56f779ebca94a249b2a2c71725d89182e732cf53c1f6d85098cc9bcb3
|
||||
|
||||
LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/f725e44cda8f359869bf8f92ce71787ddca45618.tar.gz
|
||||
LUAJIT_SHA256 2b5514bd6a6573cb6111b43d013e952cbaf46762d14ebe26c872ddb80b5a84e0
|
||||
|
40
runtime/autoload/hcl.vim
Normal file
40
runtime/autoload/hcl.vim
Normal file
@ -0,0 +1,40 @@
|
||||
" Language: HCL
|
||||
" Maintainer: Gregory Anders
|
||||
" Last Change: 2024-09-03
|
||||
" Based on: https://github.com/hashivim/vim-terraform
|
||||
|
||||
function! hcl#indentexpr(lnum)
|
||||
" Beginning of the file should have no indent
|
||||
if a:lnum == 0
|
||||
return 0
|
||||
endif
|
||||
|
||||
" Usual case is to continue at the same indent as the previous non-blank line.
|
||||
let prevlnum = prevnonblank(a:lnum-1)
|
||||
let thisindent = indent(prevlnum)
|
||||
|
||||
" If that previous line is a non-comment ending in [ { (, increase the
|
||||
" indent level.
|
||||
let prevline = getline(prevlnum)
|
||||
if prevline !~# '^\s*\(#\|//\)' && prevline =~# '[\[{\(]\s*$'
|
||||
let thisindent += &shiftwidth
|
||||
endif
|
||||
|
||||
" If the current line ends a block, decrease the indent level.
|
||||
let thisline = getline(a:lnum)
|
||||
if thisline =~# '^\s*[\)}\]]'
|
||||
let thisindent -= &shiftwidth
|
||||
endif
|
||||
|
||||
" If the previous line starts a block comment /*, increase by one
|
||||
if prevline =~# '/\*'
|
||||
let thisindent += 1
|
||||
endif
|
||||
|
||||
" If the previous line ends a block comment */, decrease by one
|
||||
if prevline =~# '\*/'
|
||||
let thisindent -= 1
|
||||
endif
|
||||
|
||||
return thisindent
|
||||
endfunction
|
@ -140,6 +140,18 @@ function! provider#clipboard#Executable() abort
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'win32yank'
|
||||
elseif executable('putclip') && executable('getclip')
|
||||
let s:copy['+'] = ['putclip']
|
||||
let s:paste['+'] = ['getclip']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'putclip'
|
||||
elseif executable('clip') && executable('powershell')
|
||||
let s:copy['+'] = ['clip']
|
||||
let s:paste['+'] = ['powershell', '-NoProfile', '-NoLogo', '-Command', 'Get-Clipboard']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'clip'
|
||||
elseif executable('termux-clipboard-set')
|
||||
let s:copy['+'] = ['termux-clipboard-set']
|
||||
let s:paste['+'] = ['termux-clipboard-get']
|
||||
|
1
runtime/doc/builtin.txt
generated
1
runtime/doc/builtin.txt
generated
@ -4361,6 +4361,7 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
|
||||
"lhsrawalt" The {lhs} of the mapping as raw bytes, alternate
|
||||
form, only present when it differs from "lhsraw"
|
||||
"rhs" The {rhs} of the mapping as typed.
|
||||
"callback" Lua function, if RHS was defined as such.
|
||||
"silent" 1 for a |:map-silent| mapping, else 0.
|
||||
"noremap" 1 if the {rhs} of the mapping is not remappable.
|
||||
"script" 1 if mapping was defined with <script>.
|
||||
|
@ -138,15 +138,15 @@ DOCUMENTATION *dev-doc*
|
||||
- Write docstrings (as opposed to inline comments) with present tense ("Gets"),
|
||||
not imperative ("Get"). This tends to reduce ambiguity and improve clarity
|
||||
by describing "What" instead of "How". >
|
||||
GOOD:
|
||||
✅ OK:
|
||||
/// Gets a highlight definition.
|
||||
BAD:
|
||||
❌ NO:
|
||||
/// Get a highlight definition.
|
||||
- Avoid starting docstrings with "The" or "A" unless needed to avoid
|
||||
ambiguity. This is a visual aid and reduces noise. >
|
||||
GOOD:
|
||||
✅ OK:
|
||||
/// @param dirname Path fragment before `pend`
|
||||
BAD:
|
||||
❌ NO:
|
||||
/// @param dirname The path fragment before `pend`
|
||||
- Vim differences:
|
||||
- Do not prefix help tags with "nvim-". Use |vim_diff.txt| to catalog
|
||||
@ -329,13 +329,20 @@ Where possible, these patterns apply to _both_ Lua and the API:
|
||||
- When accepting a buffer id, etc., 0 means "current buffer", nil means "all
|
||||
buffers". Likewise for window id, tabpage id, etc.
|
||||
- Examples: |vim.lsp.codelens.clear()| |vim.diagnostic.enable()|
|
||||
- Any function signature that accepts a callback function should define the
|
||||
callback as the LAST parameter, if possible. This improves readability of
|
||||
calls by placing the less "noisy" arguments near the start. >
|
||||
GOOD:
|
||||
filter(table, opts, function() … end)
|
||||
BAD:
|
||||
filter(function() … end, table, opts)
|
||||
- Any function signature that accepts a callback (example: |table.foreach()|)
|
||||
should place it as the LAST parameter (after opts), if possible (or ALWAYS
|
||||
for "continuation callbacks"—functions called exactly once).
|
||||
- Improves readability by placing the less "noisy" arguments near the start.
|
||||
- Consistent with luv.
|
||||
- Useful for future async lib which transforms functions of the form
|
||||
`function(<args>, cb(<ret)>))` => `function(<args>) -> <ret>`.
|
||||
- Example: >lua
|
||||
-- ✅ OK:
|
||||
filter(…, opts, function() … end)
|
||||
-- ❌ NO:
|
||||
filter(function() … end, …, opts)
|
||||
-- ❌ NO:
|
||||
filter(…, function() … end, opts)
|
||||
- "Enable" ("toggle") interface and behavior:
|
||||
- `enable(…, nil)` and `enable(…, {buf=nil})` are synonyms and control the
|
||||
the "global" enablement of a feature.
|
||||
@ -566,10 +573,10 @@ a good name: it's idiomatic and unambiguous. If the package is named "neovim",
|
||||
it confuses users, and complicates documentation and discussions.
|
||||
|
||||
Examples of API-client package names:
|
||||
- GOOD: nvim-racket
|
||||
- GOOD: pynvim
|
||||
- BAD: python-client
|
||||
- BAD: neovim_
|
||||
- ✅ OK: nvim-racket
|
||||
- ✅ OK: pynvim
|
||||
- ❌ NO: python-client
|
||||
- ❌ NO: neovim_
|
||||
|
||||
API client implementation guidelines ~
|
||||
|
||||
|
@ -444,6 +444,10 @@ when the right mouse button is pressed, if 'mousemodel' is set to popup or
|
||||
popup_setpos.
|
||||
|
||||
The default "PopUp" menu is: >vim
|
||||
anoremenu PopUp.Go\ to\ definition <Cmd>lua vim.lsp.buf.definition()<CR>
|
||||
amenu PopUp.Open\ in\ web\ browser gx
|
||||
anoremenu PopUp.Inspect <Cmd>Inspect<CR>
|
||||
anoremenu PopUp.-1- <Nop>
|
||||
vnoremenu PopUp.Cut "+x
|
||||
vnoremenu PopUp.Copy "+y
|
||||
anoremenu PopUp.Paste "+gP
|
||||
@ -452,8 +456,7 @@ The default "PopUp" menu is: >vim
|
||||
nnoremenu PopUp.Select\ All ggVG
|
||||
vnoremenu PopUp.Select\ All gg0oG$
|
||||
inoremenu PopUp.Select\ All <C-Home><C-O>VG
|
||||
anoremenu PopUp.Inspect <Cmd>Inspect<CR>
|
||||
anoremenu PopUp.-1- <Nop>
|
||||
anoremenu PopUp.-2- <Nop>
|
||||
anoremenu PopUp.How-to\ disable\ mouse <Cmd>help disable-mouse<CR>
|
||||
<
|
||||
|
||||
|
@ -7,10 +7,10 @@
|
||||
Type |gO| to see the table of contents.
|
||||
|
||||
==============================================================================
|
||||
Checkhealth *health*
|
||||
Checkhealth *vim.health* *health*
|
||||
|
||||
|
||||
health.vim is a minimal framework to help users troubleshoot configuration and
|
||||
vim.health is a minimal framework to help users troubleshoot configuration and
|
||||
any other environment conditions that a plugin might care about. Nvim ships
|
||||
with healthchecks for configuration, performance, python support, ruby
|
||||
support, clipboard support, and more.
|
||||
@ -49,7 +49,7 @@ Commands *health-commands*
|
||||
:checkhealth vim*
|
||||
<
|
||||
|
||||
Create a healthcheck *health-dev* *vim.health*
|
||||
Create a healthcheck *health-dev*
|
||||
|
||||
Healthchecks are functions that check the user environment, configuration, or
|
||||
any other prerequisites that a plugin cares about. Nvim ships with
|
||||
|
@ -1639,8 +1639,7 @@ Lua module: vim.lsp.completion *lsp-completion*
|
||||
Fields: ~
|
||||
• {autotrigger}? (`boolean`) Whether to trigger completion
|
||||
automatically. Default: false
|
||||
• {convert}? (`fun(item: lsp.CompletionItem): table`) An optional
|
||||
function used to customize the transformation of an
|
||||
• {convert}? (`fun(item: lsp.CompletionItem): table`) Transforms an
|
||||
LSP CompletionItem to |complete-items|.
|
||||
|
||||
|
||||
|
@ -352,16 +352,14 @@ Example: >vim
|
||||
<
|
||||
*lua-table-ambiguous*
|
||||
Lua tables are used as both dictionaries and lists, so it is impossible to
|
||||
determine whether empty table is meant to be empty list or empty dictionary.
|
||||
Additionally Lua does not have integer numbers. To distinguish between these
|
||||
cases there is the following agreement:
|
||||
decide whether empty table is a list or a dict. Also Lua does not have integer
|
||||
numbers. To disambiguate these cases, we define:
|
||||
*lua-list*
|
||||
0. Empty table is empty list.
|
||||
1. Table with N consecutive integer indices starting from 1 and ending with
|
||||
N is considered a list. See also |list-iterator|.
|
||||
0. Empty table is a list. Use |vim.empty_dict()| to represent empty dict.
|
||||
1. Table with N consecutive (no `nil` values, aka "holes") integer keys 1…N is
|
||||
a list. See also |list-iterator|.
|
||||
*lua-dict*
|
||||
2. Table with string keys, none of which contains NUL byte, is considered to
|
||||
be a dictionary.
|
||||
2. Table with string keys, none of which contains NUL byte, is a dict.
|
||||
3. Table with string keys, at least one of which contains NUL byte, is also
|
||||
considered to be a dictionary, but this time it is converted to
|
||||
a |msgpack-special-map|.
|
||||
@ -2232,6 +2230,12 @@ vim.tbl_count({t}) *vim.tbl_count()*
|
||||
vim.tbl_deep_extend({behavior}, {...}) *vim.tbl_deep_extend()*
|
||||
Merges recursively two or more tables.
|
||||
|
||||
Only values that are empty tables or tables that are not |lua-list|s
|
||||
(indexed by consecutive integers starting from 1) are merged recursively.
|
||||
This is useful for merging nested tables like default and user
|
||||
configurations where lists should be treated as literals (i.e., are
|
||||
overwritten instead of merged).
|
||||
|
||||
Parameters: ~
|
||||
• {behavior} (`'error'|'keep'|'force'`) Decides what to do if a key is
|
||||
found in more than one map:
|
||||
@ -3839,10 +3843,12 @@ argument into an *Iter* object with methods (such as |Iter:filter()| and
|
||||
chained to create iterator "pipelines": the output of each pipeline stage is
|
||||
input to the next stage. The first stage depends on the type passed to
|
||||
`vim.iter()`:
|
||||
• List tables (arrays, |lua-list|) yield only the value of each element.
|
||||
• Holes (nil values) are allowed.
|
||||
• Lists or arrays (|lua-list|) yield only the value of each element.
|
||||
• Holes (nil values) are allowed (but discarded).
|
||||
• Use pairs() to treat array/list tables as dicts (preserve holes and
|
||||
non-contiguous integer keys): `vim.iter(pairs(…))`.
|
||||
• Use |Iter:enumerate()| to also pass the index to the next stage.
|
||||
• Or initialize with ipairs(): `vim.iter(ipairs(…))`.
|
||||
• Or initialize with ipairs(): `vim.iter(ipairs(…))`.
|
||||
• Non-list tables (|lua-dict|) yield both the key and value of each element.
|
||||
• Function |iterator|s yield all values returned by the underlying function.
|
||||
• Tables with a |__call()| metamethod are treated as function iterators.
|
||||
|
@ -53,21 +53,14 @@ EDITOR
|
||||
documented and skips help buffers if run from a non-help buffer, otherwise
|
||||
it moves to another help buffer.
|
||||
|
||||
VIM SCRIPT
|
||||
|
||||
• |v:msgpack_types| has the type "binary" removed. |msgpackparse()| no longer
|
||||
treats BIN, STR and FIXSTR as separate types. Any of these is returned as a
|
||||
string if possible, or a |blob| if the value contained embedded NUL:s.
|
||||
|
||||
EVENTS
|
||||
|
||||
• TODO
|
||||
|
||||
LSP
|
||||
|
||||
• Add convert field in |vim.lsp.completion.BufferOpts| of
|
||||
|vim.lsp.completion.enable()| an optional function used to customize the
|
||||
transformation of an Lsp CompletionItem to |complete-items|.
|
||||
• |vim.lsp.completion.enable()| gained the `convert` callback which enables
|
||||
customizing the transformation of an LSP CompletionItem to |complete-items|.
|
||||
• |vim.lsp.diagnostic.from()| can be used to convert a list of
|
||||
|vim.Diagnostic| objects into their LSP diagnostic representation.
|
||||
|
||||
@ -89,12 +82,22 @@ PLUGINS
|
||||
|
||||
TREESITTER
|
||||
|
||||
• TODO
|
||||
• |Query:iter_matches()| correctly returns all matching nodes in a match
|
||||
instead of only the last node. This means that the returned table maps
|
||||
capture IDs to a list of nodes that need to be iterated over. For
|
||||
backwards compatibility, an option `all=false` (only return the last
|
||||
matching node) is provided that will be removed in a future release.
|
||||
|
||||
TUI
|
||||
|
||||
• TODO
|
||||
|
||||
VIMSCRIPT
|
||||
|
||||
• |v:msgpack_types| has the type "binary" removed. |msgpackparse()| no longer
|
||||
treats BIN, STR and FIXSTR as separate types. Any of these is returned as a
|
||||
string if possible, or a |blob| if the value contained embedded NUL:s.
|
||||
|
||||
==============================================================================
|
||||
NEW FEATURES *news-features*
|
||||
|
||||
@ -111,6 +114,10 @@ DEFAULTS
|
||||
• |grr| in Normal mode maps to |vim.lsp.buf.references()|
|
||||
• |gra| in Normal and Visual mode maps to |vim.lsp.buf.code_action()|
|
||||
• CTRL-S in Insert mode maps to |vim.lsp.buf.signature_help()|
|
||||
• Mouse |popup-menu| includes an "Open in web browser" item when you right-click
|
||||
on a URL.
|
||||
• Mouse |popup-menu| includes a "Go to definition" item when LSP is active
|
||||
in the buffer.
|
||||
|
||||
• Snippet:
|
||||
• `<Tab>` in Insert and Select mode maps to `vim.snippet.jump({ direction = 1 })`
|
||||
@ -159,7 +166,8 @@ PLUGINS
|
||||
|
||||
STARTUP
|
||||
|
||||
• TODO
|
||||
• Nvim will fail if the |--listen| or |$NVIM_LISTEN_ADDRESS| address is
|
||||
invalid, instead of silently skipping an invalid address.
|
||||
|
||||
TERMINAL
|
||||
|
||||
@ -192,7 +200,7 @@ CHANGED FEATURES *news-changed*
|
||||
|
||||
These existing features changed their behavior.
|
||||
|
||||
• 'scrollbind' now works properly with buffers that contain virutal lines.
|
||||
• 'scrollbind' now works properly with buffers that contain virtual lines.
|
||||
|
||||
Scrollbind works by aligning to a target top line of each window in a tab
|
||||
page. Previously this was done by calculating the difference between the old
|
||||
|
@ -1129,9 +1129,9 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
list:{n} Adds an additional indent for lines that match a
|
||||
numbered or bulleted list (using the
|
||||
'formatlistpat' setting).
|
||||
list:-1 Uses the length of a match with 'formatlistpat'
|
||||
for indentation.
|
||||
(default: 0)
|
||||
list:-1 Uses the width of a match with 'formatlistpat' for
|
||||
indentation.
|
||||
column:{n} Indent at column {n}. Will overrule the other
|
||||
sub-options. Note: an additional indent may be
|
||||
added for the 'showbreak' setting.
|
||||
|
@ -194,6 +194,8 @@ registers. Nvim looks for these clipboard tools, in order of priority:
|
||||
- lemonade (for SSH) https://github.com/pocke/lemonade
|
||||
- doitclient (for SSH) https://www.chiark.greenend.org.uk/~sgtatham/doit/
|
||||
- win32yank (Windows)
|
||||
- putclip, getclip (Windows) https://cygwin.com/packages/summary/cygutils.html
|
||||
- clip, powershell (Windows) https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/clip
|
||||
- termux (via termux-clipboard-set, termux-clipboard-set)
|
||||
- tmux (if $TMUX is set)
|
||||
|
||||
@ -248,8 +250,8 @@ For Windows WSL, try this g:clipboard definition:
|
||||
\ '*': 'clip.exe',
|
||||
\ },
|
||||
\ 'paste': {
|
||||
\ '+': 'powershell.exe -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))',
|
||||
\ '*': 'powershell.exe -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))',
|
||||
\ '+': 'powershell.exe -NoLogo -NoProfile -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))',
|
||||
\ '*': 'powershell.exe -NoLogo -NoProfile -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))',
|
||||
\ },
|
||||
\ 'cache_enabled': 0,
|
||||
\ }
|
||||
|
@ -1036,9 +1036,8 @@ add_directive({name}, {handler}, {opts})
|
||||
the same name
|
||||
• {all}? (`boolean`) Use the correct implementation of the
|
||||
match table where capture IDs map to a list of nodes
|
||||
instead of a single node. Defaults to false (for backward
|
||||
compatibility). This option will eventually become the
|
||||
default and removed.
|
||||
instead of a single node. Defaults to true. This option
|
||||
will be removed in a future release.
|
||||
|
||||
*vim.treesitter.query.add_predicate()*
|
||||
add_predicate({name}, {handler}, {opts})
|
||||
@ -1049,14 +1048,13 @@ add_predicate({name}, {handler}, {opts})
|
||||
• {handler} (`fun(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: vim.treesitter.query.TSMetadata)`)
|
||||
• see |vim.treesitter.query.add_directive()| for argument
|
||||
meanings
|
||||
• {opts} (`table`) A table with the following fields:
|
||||
• {opts} (`table?`) A table with the following fields:
|
||||
• {force}? (`boolean`) Override an existing predicate of
|
||||
the same name
|
||||
• {all}? (`boolean`) Use the correct implementation of the
|
||||
match table where capture IDs map to a list of nodes
|
||||
instead of a single node. Defaults to false (for backward
|
||||
compatibility). This option will eventually become the
|
||||
default and removed.
|
||||
instead of a single node. Defaults to true. This option
|
||||
will be removed in a future release.
|
||||
|
||||
edit({lang}) *vim.treesitter.query.edit()*
|
||||
Opens a live editor to query the buffer you started from.
|
||||
@ -1216,14 +1214,8 @@ Query:iter_matches({node}, {source}, {start}, {stop}, {opts})
|
||||
indices to a list of nodes, and metadata from any directives processing
|
||||
the match.
|
||||
|
||||
WARNING: Set `all=true` to ensure all matching nodes in a match are
|
||||
returned, otherwise only the last node in a match is returned, breaking
|
||||
captures involving quantifiers such as `(comment)+ @comment`. The default
|
||||
option `all=false` is only provided for backward compatibility and will be
|
||||
removed after Nvim 0.10.
|
||||
|
||||
Example: >lua
|
||||
for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, 0, -1, { all = true }) do
|
||||
for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, 0, -1) do
|
||||
for id, nodes in pairs(match) do
|
||||
local name = query.captures[id]
|
||||
for _, node in ipairs(nodes) do
|
||||
@ -1248,12 +1240,11 @@ Query:iter_matches({node}, {source}, {start}, {stop}, {opts})
|
||||
start depth for each match. This is used to prevent
|
||||
traversing too deep into a tree.
|
||||
• match_limit (integer) Set the maximum number of
|
||||
in-progress matches (Default: 256).
|
||||
• all (boolean) When set, the returned match table maps
|
||||
capture IDs to a list of nodes. Older versions of
|
||||
iter_matches incorrectly mapped capture IDs to a single
|
||||
node, which is incorrect behavior. This option will
|
||||
eventually become the default and removed.
|
||||
in-progress matches (Default: 256). all (boolean) When
|
||||
`false` (default `true`), the returned table maps capture
|
||||
IDs to a single (last) node instead of the full list of
|
||||
matching nodes. This option is only for backward
|
||||
compatibility and will be removed in a future release.
|
||||
|
||||
Return: ~
|
||||
(`fun(): integer, table<integer, TSNode[]>, vim.treesitter.query.TSMetadata`)
|
||||
|
@ -106,23 +106,28 @@ standard actions ("Cut", "Copy", "Paste", …). Mouse is NOT enabled in
|
||||
|command-mode| or the |more-prompt|, so you can temporarily disable it just by
|
||||
typing ":".
|
||||
|
||||
If you don't like this you can disable the mouse in your |config| using any of
|
||||
the following:
|
||||
Or you can disable the popup-menu using any of the following:
|
||||
- Disable mouse completely by unsetting the 'mouse' option: >vim
|
||||
set mouse=
|
||||
- Pressing <RightMouse> extends selection instead of showing popup-menu: >vim
|
||||
- Change the 'mousemodel', so <RightMouse> extends selection instead of
|
||||
showing the popup-menu: >vim
|
||||
set mousemodel=extend
|
||||
- Pressing <A-LeftMouse> releases mouse until the cursor moves: >vim
|
||||
- Map <A-LeftMouse> so that it temporarily disables mouse until the cursor
|
||||
moves: >vim
|
||||
nnoremap <A-LeftMouse> <Cmd>
|
||||
\ set mouse=<Bar>
|
||||
\ echo 'mouse OFF until next cursor-move'<Bar>
|
||||
\ autocmd CursorMoved * ++once set mouse&<Bar>
|
||||
\ echo 'mouse ON'<CR>
|
||||
<
|
||||
To remove the "How-to disable mouse" menu item and the separator above it: >vim
|
||||
To remove the default popup-menu without disabling mouse: >vim
|
||||
aunmenu PopUp
|
||||
autocmd! nvim_popupmenu
|
||||
|
||||
To remove only the "How-to disable mouse" menu item (and its separator): >vim
|
||||
aunmenu PopUp.How-to\ disable\ mouse
|
||||
aunmenu PopUp.-1-
|
||||
<
|
||||
aunmenu PopUp.-2-
|
||||
|
||||
DEFAULT MAPPINGS
|
||||
*default-mappings*
|
||||
Nvim creates the following default mappings at |startup|. You can disable any
|
||||
|
@ -53,11 +53,17 @@ active yes yes 'a'
|
||||
hidden no yes 'h'
|
||||
inactive no no ' '
|
||||
|
||||
Note: All CTRL-W commands can also be executed with |:wincmd|, for those
|
||||
places where a Normal mode command can't be used or is inconvenient.
|
||||
*buffer-reuse*
|
||||
Each buffer has a unique number and the number will not change within a Vim
|
||||
session. The |bufnr()| and |bufname()| functions can be used to convert
|
||||
between a buffer name and the buffer number. There is one exception: if a new
|
||||
empty buffer is created and it is not modified, the buffer will be re-used
|
||||
when loading another file into that buffer. This also means the buffer number
|
||||
will not change.
|
||||
|
||||
The main Vim window can hold several split windows. There are also tab pages
|
||||
|tab-page|, each of which can hold multiple windows.
|
||||
|
||||
*window-ID* *winid* *windowid*
|
||||
Each window has a unique identifier called the window ID. This identifier
|
||||
will not change within a Vim session. The |win_getid()| and |win_id2tabwin()|
|
||||
@ -69,9 +75,6 @@ across tabs. For most functions that take a window ID or a window number, the
|
||||
window number only applies to the current tab, while the window ID can refer
|
||||
to a window in any tab.
|
||||
|
||||
Each buffer has a unique number and the number will not change within a Vim
|
||||
session. The |bufnr()| and |bufname()| functions can be used to convert
|
||||
between a buffer name and the buffer number.
|
||||
|
||||
==============================================================================
|
||||
2. Starting Vim *windows-starting*
|
||||
@ -468,6 +471,10 @@ These commands can also be executed with ":wincmd":
|
||||
:exe nr .. "wincmd w"
|
||||
< This goes to window "nr".
|
||||
|
||||
Note: All CTRL-W commands can also be executed with |:wincmd|, for those
|
||||
places where a Normal mode command can't be used or is inconvenient (e.g.
|
||||
in a browser-based terminal).
|
||||
|
||||
==============================================================================
|
||||
5. Moving windows around *window-moving*
|
||||
|
||||
|
3
runtime/ftplugin/dot.lua
Normal file
3
runtime/ftplugin/dot.lua
Normal file
@ -0,0 +1,3 @@
|
||||
vim.bo.commentstring = '// %s'
|
||||
|
||||
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '') .. '\n setl commentstring<'
|
3
runtime/ftplugin/faust.lua
Normal file
3
runtime/ftplugin/faust.lua
Normal file
@ -0,0 +1,3 @@
|
||||
vim.bo.commentstring = '// %s'
|
||||
|
||||
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '') .. '\n setl commentstring<'
|
10
runtime/ftplugin/hcl.vim
Normal file
10
runtime/ftplugin/hcl.vim
Normal file
@ -0,0 +1,10 @@
|
||||
" Vim filetype plugin
|
||||
" Language: HCL
|
||||
" Maintainer: Gregory Anders
|
||||
" Last Change: 2024-09-03
|
||||
|
||||
if exists('b:did_ftplugin')
|
||||
finish
|
||||
endif
|
||||
|
||||
runtime! ftplugin/terraform.vim
|
3
runtime/ftplugin/stata.lua
Normal file
3
runtime/ftplugin/stata.lua
Normal file
@ -0,0 +1,3 @@
|
||||
vim.bo.commentstring = '// %s'
|
||||
|
||||
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '') .. '\n setl commentstring<'
|
3
runtime/ftplugin/supercollider.lua
Normal file
3
runtime/ftplugin/supercollider.lua
Normal file
@ -0,0 +1,3 @@
|
||||
vim.bo.commentstring = '// %s'
|
||||
|
||||
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '') .. '\n setl commentstring<'
|
3
runtime/ftplugin/swift.lua
Normal file
3
runtime/ftplugin/swift.lua
Normal file
@ -0,0 +1,3 @@
|
||||
vim.bo.commentstring = '// %s'
|
||||
|
||||
vim.b.undo_ftplugin = vim.b.undo_ftplugin .. ' | setl commentstring<'
|
16
runtime/indent/hcl.vim
Normal file
16
runtime/indent/hcl.vim
Normal file
@ -0,0 +1,16 @@
|
||||
" Vim indent file
|
||||
" Language: HCL
|
||||
" Maintainer: Gregory Anders
|
||||
" Upstream: https://github.com/hashivim/vim-terraform
|
||||
" Last Change: 2024-09-03
|
||||
|
||||
if exists('b:did_indent')
|
||||
finish
|
||||
endif
|
||||
let b:did_indent = 1
|
||||
|
||||
setlocal autoindent shiftwidth=2 tabstop=2 softtabstop=2 expandtab
|
||||
setlocal indentexpr=hcl#indentexpr(v:lnum)
|
||||
setlocal indentkeys+=<:>,0=},0=)
|
||||
|
||||
let b:undo_indent = 'setlocal ai< sw< ts< sts< et< inde< indk<'
|
11
runtime/indent/terraform.vim
Normal file
11
runtime/indent/terraform.vim
Normal file
@ -0,0 +1,11 @@
|
||||
" Vim indent file
|
||||
" Language: Terraform
|
||||
" Maintainer: Gregory Anders
|
||||
" Upstream: https://github.com/hashivim/vim-terraform
|
||||
" Last Change: 2024-09-03
|
||||
|
||||
if exists('b:did_indent')
|
||||
finish
|
||||
endif
|
||||
|
||||
runtime! indent/hcl.vim
|
@ -1293,9 +1293,25 @@ local function opt_to_global_state(opt, title)
|
||||
local fonts = {}
|
||||
if opt.font then
|
||||
fonts = type(opt.font) == 'string' and { opt.font } or opt.font --[[@as (string[])]]
|
||||
for i, v in pairs(fonts) do
|
||||
fonts[i] = ('"%s"'):format(v)
|
||||
end
|
||||
elseif vim.o.guifont:match('^[^:]+') then
|
||||
table.insert(fonts, vim.o.guifont:match('^[^:]+'))
|
||||
-- Example:
|
||||
-- Input: "Font,Escape\,comma, Ignore space after comma"
|
||||
-- Output: { "Font","Escape,comma","Ignore space after comma" }
|
||||
local prev = ''
|
||||
for name in vim.gsplit(vim.o.guifont:match('^[^:]+'), ',', { trimempty = true }) do
|
||||
if vim.endswith(name, '\\') then
|
||||
prev = prev .. vim.trim(name:sub(1, -2) .. ',')
|
||||
elseif vim.trim(name) ~= '' then
|
||||
table.insert(fonts, ('"%s%s"'):format(prev, vim.trim(name)))
|
||||
prev = ''
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Generic family names (monospace here) must not be quoted
|
||||
-- because the browser recognizes them as font families.
|
||||
table.insert(fonts, 'monospace')
|
||||
--- @type vim.tohtml.state.global
|
||||
local state = {
|
||||
|
@ -213,20 +213,48 @@ end
|
||||
--- Default menus
|
||||
do
|
||||
--- Right click popup menu
|
||||
-- TODO VimScript, no l10n
|
||||
vim.cmd([[
|
||||
vnoremenu PopUp.Cut "+x
|
||||
vnoremenu PopUp.Copy "+y
|
||||
anoremenu PopUp.Paste "+gP
|
||||
vnoremenu PopUp.Paste "+P
|
||||
vnoremenu PopUp.Delete "_x
|
||||
nnoremenu PopUp.Select\ All ggVG
|
||||
vnoremenu PopUp.Select\ All gg0oG$
|
||||
inoremenu PopUp.Select\ All <C-Home><C-O>VG
|
||||
anoremenu PopUp.Inspect <Cmd>Inspect<CR>
|
||||
anoremenu PopUp.-1- <Nop>
|
||||
anoremenu PopUp.How-to\ disable\ mouse <Cmd>help disable-mouse<CR>
|
||||
]])
|
||||
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
|
||||
anoremenu PopUp.Inspect <Cmd>Inspect<CR>
|
||||
anoremenu PopUp.-1- <Nop>
|
||||
vnoremenu PopUp.Cut "+x
|
||||
vnoremenu PopUp.Copy "+y
|
||||
anoremenu PopUp.Paste "+gP
|
||||
vnoremenu PopUp.Paste "+P
|
||||
vnoremenu PopUp.Delete "_x
|
||||
nnoremenu PopUp.Select\ All ggVG
|
||||
vnoremenu PopUp.Select\ All gg0oG$
|
||||
inoremenu PopUp.Select\ All <C-Home><C-O>VG
|
||||
anoremenu PopUp.-2- <Nop>
|
||||
anoremenu PopUp.How-to\ disable\ mouse <Cmd>help disable-mouse<CR>
|
||||
|
||||
amenu disable PopUp.Go\ to\ definition
|
||||
amenu disable PopUp.Open\ in\ web\ browser
|
||||
]])
|
||||
|
||||
if ctx == 'url' then
|
||||
vim.cmd([[amenu enable PopUp.Open\ in\ web\ browser]])
|
||||
elseif ctx == 'lsp' then
|
||||
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', {
|
||||
pattern = '*',
|
||||
group = nvim_popupmenu_augroup,
|
||||
desc = 'Mouse popup menu',
|
||||
-- nested = true,
|
||||
callback = function()
|
||||
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)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
--- Default autocommands. See |default-autocmds|
|
||||
|
@ -1,17 +1,19 @@
|
||||
-- Nvim-Lua stdlib: the `vim` module (:help lua-stdlib)
|
||||
--
|
||||
-- Lua code lives in one of three places:
|
||||
-- 1. runtime/lua/vim/ (the runtime): For "nice to have" features, e.g. the
|
||||
-- `inspect` and `lpeg` modules.
|
||||
-- 2. runtime/lua/vim/shared.lua: pure Lua functions which always
|
||||
-- are available. Used in the test runner, as well as worker threads
|
||||
-- and processes launched from Nvim.
|
||||
-- 3. runtime/lua/vim/_editor.lua: Code which directly interacts with
|
||||
-- the Nvim editor state. Only available in the main thread.
|
||||
-- Lua code lives in one of four places:
|
||||
-- 1. Plugins! Not everything needs to live on "vim.*". Plugins are the correct model for
|
||||
-- non-essential features which the user may want to disable or replace with a third-party
|
||||
-- plugin. Examples: "editorconfig", "comment".
|
||||
-- - "opt-out": runtime/plugin/*.lua
|
||||
-- - "opt-in": runtime/pack/dist/opt/
|
||||
-- 2. runtime/lua/vim/ (the runtime): Lazy-loaded modules. Examples: `inspect`, `lpeg`.
|
||||
-- 3. runtime/lua/vim/shared.lua: pure Lua functions which always are available. Used in the test
|
||||
-- runner, as well as worker threads and processes launched from Nvim.
|
||||
-- 4. runtime/lua/vim/_editor.lua: Eager-loaded code which directly interacts with the Nvim
|
||||
-- editor state. Only available in the main thread.
|
||||
--
|
||||
-- Guideline: "If in doubt, put it in the runtime".
|
||||
--
|
||||
-- Most functions should live directly in `vim.`, not in submodules.
|
||||
-- The top level "vim.*" namespace is for fundamental Lua and editor features. Use submodules for
|
||||
-- everything else (but avoid excessive "nesting"), or plugins (see above).
|
||||
--
|
||||
-- Compatibility with Vim's `if_lua` is explicitly a non-goal.
|
||||
--
|
||||
@ -19,9 +21,7 @@
|
||||
-- - https://github.com/luafun/luafun
|
||||
-- - https://github.com/rxi/lume
|
||||
-- - http://leafo.net/lapis/reference/utilities.html
|
||||
-- - https://github.com/torch/paths
|
||||
-- - https://github.com/bakpakin/Fennel (pretty print, repl)
|
||||
-- - https://github.com/howl-editor/howl/tree/master/lib/howl/util
|
||||
|
||||
-- These are for loading runtime modules lazily since they aren't available in
|
||||
-- the nvim binary as specified in executor.c
|
||||
|
@ -23,7 +23,7 @@ error('Cannot require a meta file')
|
||||
--- @field conceal? boolean
|
||||
--- @field spell? boolean
|
||||
--- @field ui_watched? boolean
|
||||
--- @field url? boolean
|
||||
--- @field url? string
|
||||
--- @field hl_mode? string
|
||||
---
|
||||
--- @field virt_text? [string, string][]
|
||||
|
4
runtime/lua/vim/_meta/options.lua
generated
4
runtime/lua/vim/_meta/options.lua
generated
@ -558,9 +558,9 @@ vim.wo.bri = vim.wo.breakindent
|
||||
--- list:{n} Adds an additional indent for lines that match a
|
||||
--- numbered or bulleted list (using the
|
||||
--- 'formatlistpat' setting).
|
||||
--- list:-1 Uses the length of a match with 'formatlistpat'
|
||||
--- for indentation.
|
||||
--- (default: 0)
|
||||
--- list:-1 Uses the width of a match with 'formatlistpat' for
|
||||
--- indentation.
|
||||
--- column:{n} Indent at column {n}. Will overrule the other
|
||||
--- sub-options. Note: an additional indent may be
|
||||
--- added for the 'showbreak' setting.
|
||||
|
1
runtime/lua/vim/_meta/vimfn.lua
generated
1
runtime/lua/vim/_meta/vimfn.lua
generated
@ -5262,6 +5262,7 @@ function vim.fn.map(expr1, expr2) end
|
||||
--- "lhsrawalt" The {lhs} of the mapping as raw bytes, alternate
|
||||
--- form, only present when it differs from "lhsraw"
|
||||
--- "rhs" The {rhs} of the mapping as typed.
|
||||
--- "callback" Lua function, if RHS was defined as such.
|
||||
--- "silent" 1 for a |:map-silent| mapping, else 0.
|
||||
--- "noremap" 1 if the {rhs} of the mapping is not remappable.
|
||||
--- "script" 1 if mapping was defined with <script>.
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- @brief
|
||||
---<pre>help
|
||||
--- health.vim is a minimal framework to help users troubleshoot configuration and
|
||||
--- vim.health is a minimal framework to help users troubleshoot configuration and
|
||||
--- any other environment conditions that a plugin might care about. Nvim ships
|
||||
--- with healthchecks for configuration, performance, python support, ruby
|
||||
--- support, clipboard support, and more.
|
||||
@ -39,7 +39,7 @@
|
||||
--- :checkhealth vim*
|
||||
--- <
|
||||
---
|
||||
--- Create a healthcheck *health-dev* *vim.health*
|
||||
--- Create a healthcheck *health-dev*
|
||||
---
|
||||
--- Healthchecks are functions that check the user environment, configuration, or
|
||||
--- any other prerequisites that a plugin cares about. Nvim ships with
|
||||
|
@ -6,10 +6,12 @@
|
||||
--- of each pipeline stage is input to the next stage. The first stage depends on the type passed to
|
||||
--- `vim.iter()`:
|
||||
---
|
||||
--- - List tables (arrays, |lua-list|) yield only the value of each element.
|
||||
--- - Holes (nil values) are allowed.
|
||||
--- - Lists or arrays (|lua-list|) yield only the value of each element.
|
||||
--- - Holes (nil values) are allowed (but discarded).
|
||||
--- - Use pairs() to treat array/list tables as dicts (preserve holes and non-contiguous integer
|
||||
--- keys): `vim.iter(pairs(…))`.
|
||||
--- - Use |Iter:enumerate()| to also pass the index to the next stage.
|
||||
--- - Or initialize with ipairs(): `vim.iter(ipairs(…))`.
|
||||
--- - Or initialize with ipairs(): `vim.iter(ipairs(…))`.
|
||||
--- - Non-list tables (|lua-dict|) yield both the key and value of each element.
|
||||
--- - Function |iterator|s yield all values returned by the underlying function.
|
||||
--- - Tables with a |__call()| metamethod are treated as function iterators.
|
||||
@ -1034,7 +1036,7 @@ function Iter.new(src, ...)
|
||||
if type(k) ~= 'number' or k <= 0 or math.floor(k) ~= k then
|
||||
return Iter.new(pairs(src))
|
||||
end
|
||||
t[#t + 1] = v
|
||||
t[#t + 1] = v -- Coerce to list-like table.
|
||||
end
|
||||
return ArrayIter.new(t)
|
||||
end
|
||||
|
@ -597,7 +597,7 @@ end
|
||||
|
||||
--- @class vim.lsp.completion.BufferOpts
|
||||
--- @field autotrigger? boolean Whether to trigger completion automatically. Default: false
|
||||
--- @field convert? fun(item: lsp.CompletionItem): table An optional function used to customize the transformation of an LSP CompletionItem to |complete-items|.
|
||||
--- @field convert? fun(item: lsp.CompletionItem): table Transforms an LSP CompletionItem to |complete-items|.
|
||||
|
||||
---@param client_id integer
|
||||
---@param bufnr integer
|
||||
|
@ -77,12 +77,7 @@ function M.on_inlayhint(err, result, ctx, _)
|
||||
local col = position.character
|
||||
if col > 0 then
|
||||
local line = lines[position.line + 1] or ''
|
||||
local ok, convert_result
|
||||
ok, convert_result = pcall(util._str_byteindex_enc, line, col, client.offset_encoding)
|
||||
if ok then
|
||||
return convert_result
|
||||
end
|
||||
return math.min(#line, col)
|
||||
return util._str_byteindex_enc(line, col, client.offset_encoding)
|
||||
end
|
||||
return col
|
||||
end
|
||||
|
@ -703,7 +703,9 @@ function M.connect(host_or_path, port)
|
||||
if port == nil then
|
||||
handle:connect(host_or_path, on_connect)
|
||||
else
|
||||
handle:connect(host_or_path, port, on_connect)
|
||||
local info = uv.getaddrinfo(host_or_path, nil)
|
||||
local resolved_host = info and info[1] and info[1].addr or host_or_path
|
||||
handle:connect(resolved_host, port, on_connect)
|
||||
end
|
||||
|
||||
return public_client(client)
|
||||
|
@ -140,12 +140,7 @@ local function tokens_to_ranges(data, bufnr, client, request)
|
||||
local function _get_byte_pos(col)
|
||||
if col > 0 then
|
||||
local buf_line = lines[line + 1] or ''
|
||||
local ok, result
|
||||
ok, result = pcall(util._str_byteindex_enc, buf_line, col, client.offset_encoding)
|
||||
if ok then
|
||||
return result
|
||||
end
|
||||
return math.min(#buf_line, col)
|
||||
return util._str_byteindex_enc(buf_line, col, client.offset_encoding)
|
||||
end
|
||||
return col
|
||||
end
|
||||
|
@ -119,6 +119,7 @@ end
|
||||
---@param encoding string|nil utf-8|utf-16|utf-32|nil defaults to utf-16
|
||||
---@return integer `encoding` index of `index` in `line`
|
||||
function M._str_utfindex_enc(line, index, encoding)
|
||||
local len32, len16 = vim.str_utfindex(line)
|
||||
if not encoding then
|
||||
encoding = 'utf-16'
|
||||
end
|
||||
@ -129,9 +130,15 @@ function M._str_utfindex_enc(line, index, encoding)
|
||||
return #line
|
||||
end
|
||||
elseif encoding == 'utf-16' then
|
||||
if not index or index > len16 then
|
||||
return len16
|
||||
end
|
||||
local _, col16 = vim.str_utfindex(line, index)
|
||||
return col16
|
||||
elseif encoding == 'utf-32' then
|
||||
if not index or index > len32 then
|
||||
return len32
|
||||
end
|
||||
local col32, _ = vim.str_utfindex(line, index)
|
||||
return col32
|
||||
else
|
||||
@ -147,6 +154,12 @@ 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)
|
||||
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
|
||||
return len
|
||||
end
|
||||
if not encoding then
|
||||
encoding = 'utf-16'
|
||||
end
|
||||
@ -165,9 +178,6 @@ function M._str_byteindex_enc(line, index, encoding)
|
||||
end
|
||||
end
|
||||
|
||||
local _str_utfindex_enc = M._str_utfindex_enc
|
||||
local _str_byteindex_enc = M._str_byteindex_enc
|
||||
|
||||
--- Replaces text in a range with new text.
|
||||
---
|
||||
--- CAUTION: Changes in-place!
|
||||
@ -334,12 +344,7 @@ local function get_line_byte_from_position(bufnr, position, offset_encoding)
|
||||
-- character
|
||||
if col > 0 then
|
||||
local line = get_line(bufnr, position.line) or ''
|
||||
local ok, result
|
||||
ok, result = pcall(_str_byteindex_enc, line, col, offset_encoding)
|
||||
if ok then
|
||||
return result
|
||||
end
|
||||
return math.min(#line, col)
|
||||
return M._str_byteindex_enc(line, col, offset_encoding or 'utf-16')
|
||||
end
|
||||
return col
|
||||
end
|
||||
@ -436,14 +441,15 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
|
||||
e.end_col = last_line_len
|
||||
has_eol_text_edit = true
|
||||
else
|
||||
-- If the replacement is over the end of a line (i.e. e.end_col is out of bounds and the
|
||||
-- If the replacement is over the end of a line (i.e. e.end_col is equal to the line length and the
|
||||
-- replacement text ends with a newline We can likely assume that the replacement is assumed
|
||||
-- to be meant to replace the newline with another newline and we need to make sure this
|
||||
-- doesn't add an extra empty line. E.g. when the last line to be replaced contains a '\r'
|
||||
-- in the file some servers (clangd on windows) will include that character in the line
|
||||
-- while nvim_buf_set_text doesn't count it as part of the line.
|
||||
if
|
||||
e.end_col > last_line_len
|
||||
e.end_col >= last_line_len
|
||||
and text_edit.range['end'].character > e.end_col
|
||||
and #text_edit.newText > 0
|
||||
and string.sub(text_edit.newText, -1) == '\n'
|
||||
then
|
||||
@ -1795,8 +1801,10 @@ function M.locations_to_items(locations, offset_encoding)
|
||||
local row = pos.line
|
||||
local end_row = end_pos.line
|
||||
local line = lines[row] or ''
|
||||
local end_line = lines[end_row] or ''
|
||||
local col = M._str_byteindex_enc(line, pos.character, offset_encoding)
|
||||
local end_col = M._str_byteindex_enc(lines[end_row] or '', end_pos.character, offset_encoding)
|
||||
local end_col = M._str_byteindex_enc(end_line, end_pos.character, offset_encoding)
|
||||
|
||||
table.insert(items, {
|
||||
filename = filename,
|
||||
lnum = row + 1,
|
||||
@ -1925,7 +1933,7 @@ local function make_position_param(window, offset_encoding)
|
||||
return { line = 0, character = 0 }
|
||||
end
|
||||
|
||||
col = _str_utfindex_enc(line, col, offset_encoding)
|
||||
col = M._str_utfindex_enc(line, col, offset_encoding)
|
||||
|
||||
return { line = row, character = col }
|
||||
end
|
||||
@ -2107,11 +2115,7 @@ function M.character_offset(buf, row, col, offset_encoding)
|
||||
)
|
||||
offset_encoding = vim.lsp.get_clients({ bufnr = buf })[1].offset_encoding
|
||||
end
|
||||
-- If the col is past the EOL, use the line length.
|
||||
if col > #line then
|
||||
return _str_utfindex_enc(line, nil, offset_encoding)
|
||||
end
|
||||
return _str_utfindex_enc(line, col, offset_encoding)
|
||||
return M._str_utfindex_enc(line, col, offset_encoding)
|
||||
end
|
||||
|
||||
--- Helper function to return nested values in language server settings
|
||||
|
@ -354,37 +354,28 @@ function vim.tbl_isempty(t)
|
||||
return next(t) == nil
|
||||
end
|
||||
|
||||
--- We only merge empty tables or tables that are not an array (indexed by integers)
|
||||
--- We only merge empty tables or tables that are not list-like (indexed by consecutive integers
|
||||
--- starting from 1)
|
||||
local function can_merge(v)
|
||||
return type(v) == 'table' and (vim.tbl_isempty(v) or not vim.isarray(v))
|
||||
return type(v) == 'table' and (vim.tbl_isempty(v) or not vim.islist(v))
|
||||
end
|
||||
|
||||
local function tbl_extend(behavior, deep_extend, ...)
|
||||
if behavior ~= 'error' and behavior ~= 'keep' and behavior ~= 'force' then
|
||||
error('invalid "behavior": ' .. tostring(behavior))
|
||||
end
|
||||
|
||||
if select('#', ...) < 2 then
|
||||
error(
|
||||
'wrong number of arguments (given '
|
||||
.. tostring(1 + select('#', ...))
|
||||
.. ', expected at least 3)'
|
||||
)
|
||||
end
|
||||
|
||||
--- Recursive worker for tbl_extend
|
||||
--- @param behavior 'error'|'keep'|'force'
|
||||
--- @param deep_extend boolean
|
||||
--- @param ... table<any,any>
|
||||
local function tbl_extend_rec(behavior, deep_extend, ...)
|
||||
local ret = {} --- @type table<any,any>
|
||||
if vim._empty_dict_mt ~= nil and getmetatable(select(1, ...)) == vim._empty_dict_mt then
|
||||
ret = vim.empty_dict()
|
||||
end
|
||||
|
||||
for i = 1, select('#', ...) do
|
||||
local tbl = select(i, ...)
|
||||
vim.validate('after the second argument', tbl, 'table')
|
||||
--- @cast tbl table<any,any>
|
||||
local tbl = select(i, ...) --[[@as table<any,any>]]
|
||||
if tbl then
|
||||
for k, v in pairs(tbl) do
|
||||
if deep_extend and can_merge(v) and can_merge(ret[k]) then
|
||||
ret[k] = tbl_extend(behavior, true, ret[k], v)
|
||||
ret[k] = tbl_extend_rec(behavior, true, ret[k], v)
|
||||
elseif behavior ~= 'force' and ret[k] ~= nil then
|
||||
if behavior == 'error' then
|
||||
error('key found in more than one map: ' .. k)
|
||||
@ -395,9 +386,31 @@ local function tbl_extend(behavior, deep_extend, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
--- @param behavior 'error'|'keep'|'force'
|
||||
--- @param deep_extend boolean
|
||||
--- @param ... table<any,any>
|
||||
local function tbl_extend(behavior, deep_extend, ...)
|
||||
if behavior ~= 'error' and behavior ~= 'keep' and behavior ~= 'force' then
|
||||
error('invalid "behavior": ' .. tostring(behavior))
|
||||
end
|
||||
|
||||
local nargs = select('#', ...)
|
||||
|
||||
if nargs < 2 then
|
||||
error(('wrong number of arguments (given %d, expected at least 3)'):format(1 + nargs))
|
||||
end
|
||||
|
||||
for i = 1, nargs do
|
||||
vim.validate('after the second argument', select(i, ...), 'table')
|
||||
end
|
||||
|
||||
return tbl_extend_rec(behavior, deep_extend, ...)
|
||||
end
|
||||
|
||||
--- Merges two or more tables.
|
||||
---
|
||||
---@see |extend()|
|
||||
@ -414,6 +427,11 @@ end
|
||||
|
||||
--- Merges recursively two or more tables.
|
||||
---
|
||||
--- Only values that are empty tables or tables that are not |lua-list|s (indexed by consecutive
|
||||
--- integers starting from 1) are merged recursively. This is useful for merging nested tables
|
||||
--- like default and user configurations where lists should be treated as literals (i.e., are
|
||||
--- overwritten instead of merged).
|
||||
---
|
||||
---@see |vim.tbl_extend()|
|
||||
---
|
||||
---@generic T1: table
|
||||
|
@ -131,9 +131,7 @@ local function compute_folds_levels(bufnr, info, srow, erow, parse_injections)
|
||||
|
||||
-- Collect folds starting from srow - 1, because we should first subtract the folds that end at
|
||||
-- srow - 1 from the level of srow - 1 to get accurate level of srow.
|
||||
for _, match, metadata in
|
||||
query:iter_matches(tree:root(), bufnr, math.max(srow - 1, 0), erow, { all = true })
|
||||
do
|
||||
for _, match, metadata in query:iter_matches(tree:root(), bufnr, math.max(srow - 1, 0), erow) do
|
||||
for id, nodes in pairs(match) do
|
||||
if query.captures[id] == 'fold' then
|
||||
local range = ts.get_range(nodes[1], bufnr, metadata[id])
|
||||
|
@ -176,7 +176,7 @@ function M.lint(buf, opts)
|
||||
parser:parse()
|
||||
parser:for_each_tree(function(tree, ltree)
|
||||
if ltree:lang() == 'query' then
|
||||
for _, match, _ in query:iter_matches(tree:root(), buf, 0, -1, { all = true }) do
|
||||
for _, match, _ in query:iter_matches(tree:root(), buf, 0, -1) do
|
||||
local lang_context = {
|
||||
lang = lang,
|
||||
parser_info = parser_info,
|
||||
|
@ -833,13 +833,7 @@ function LanguageTree:_get_injections()
|
||||
local start_line, _, end_line, _ = root_node:range()
|
||||
|
||||
for pattern, match, metadata in
|
||||
self._injection_query:iter_matches(
|
||||
root_node,
|
||||
self._source,
|
||||
start_line,
|
||||
end_line + 1,
|
||||
{ all = true }
|
||||
)
|
||||
self._injection_query:iter_matches(root_node, self._source, start_line, end_line + 1)
|
||||
do
|
||||
local lang, combined, ranges = self:_get_injection(match, metadata)
|
||||
if lang then
|
||||
|
@ -620,8 +620,8 @@ local directive_handlers = {
|
||||
--- @field force? boolean
|
||||
---
|
||||
--- Use the correct implementation of the match table where capture IDs map to
|
||||
--- a list of nodes instead of a single node. Defaults to false (for backward
|
||||
--- compatibility). This option will eventually become the default and removed.
|
||||
--- a list of nodes instead of a single node. Defaults to true. This option will
|
||||
--- be removed in a future release.
|
||||
--- @field all? boolean
|
||||
|
||||
--- Adds a new predicate to be used in queries
|
||||
@ -629,7 +629,7 @@ local directive_handlers = {
|
||||
---@param name string Name of the predicate, without leading #
|
||||
---@param handler fun(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: vim.treesitter.query.TSMetadata)
|
||||
--- - see |vim.treesitter.query.add_directive()| for argument meanings
|
||||
---@param opts vim.treesitter.query.add_predicate.Opts
|
||||
---@param opts? vim.treesitter.query.add_predicate.Opts
|
||||
function M.add_predicate(name, handler, opts)
|
||||
-- Backward compatibility: old signature had "force" as boolean argument
|
||||
if type(opts) == 'boolean' then
|
||||
@ -642,7 +642,7 @@ function M.add_predicate(name, handler, opts)
|
||||
error(string.format('Overriding existing predicate %s', name))
|
||||
end
|
||||
|
||||
if opts.all then
|
||||
if opts.all ~= false then
|
||||
predicate_handlers[name] = handler
|
||||
else
|
||||
--- @param match table<integer, TSNode[]>
|
||||
@ -894,16 +894,10 @@ end
|
||||
--- index of the pattern in the query, a table mapping capture indices to a list
|
||||
--- of nodes, and metadata from any directives processing the match.
|
||||
---
|
||||
--- WARNING: Set `all=true` to ensure all matching nodes in a match are
|
||||
--- returned, otherwise only the last node in a match is returned, breaking captures
|
||||
--- involving quantifiers such as `(comment)+ @comment`. The default option
|
||||
--- `all=false` is only provided for backward compatibility and will be removed
|
||||
--- after Nvim 0.10.
|
||||
---
|
||||
--- Example:
|
||||
---
|
||||
--- ```lua
|
||||
--- for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, 0, -1, { all = true }) do
|
||||
--- for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, 0, -1) do
|
||||
--- for id, nodes in pairs(match) do
|
||||
--- local name = query.captures[id]
|
||||
--- for _, node in ipairs(nodes) do
|
||||
@ -925,9 +919,9 @@ end
|
||||
--- - max_start_depth (integer) if non-zero, sets the maximum start depth
|
||||
--- for each match. This is used to prevent traversing too deep into a tree.
|
||||
--- - match_limit (integer) Set the maximum number of in-progress matches (Default: 256).
|
||||
--- - all (boolean) When set, the returned match table maps capture IDs to a list of nodes.
|
||||
--- Older versions of iter_matches incorrectly mapped capture IDs to a single node, which is
|
||||
--- incorrect behavior. This option will eventually become the default and removed.
|
||||
--- - all (boolean) When `false` (default `true`), the returned table maps capture IDs to a single
|
||||
--- (last) node instead of the full list of matching nodes. This option is only for backward
|
||||
--- compatibility and will be removed in a future release.
|
||||
---
|
||||
---@return (fun(): integer, table<integer, TSNode[]>, vim.treesitter.query.TSMetadata): pattern id, match, metadata
|
||||
function Query:iter_matches(node, source, start, stop, opts)
|
||||
@ -960,10 +954,10 @@ function Query:iter_matches(node, source, start, stop, opts)
|
||||
|
||||
local captures = match:captures()
|
||||
|
||||
if not opts.all then
|
||||
if opts.all == false then
|
||||
-- Convert the match table into the old buggy version for backward
|
||||
-- compatibility. This is slow. Plugin authors, if you're reading this, set the "all"
|
||||
-- option!
|
||||
-- compatibility. This is slow, but we only do it when the caller explicitly opted into it by
|
||||
-- setting `all` to `false`.
|
||||
local old_match = {} ---@type table<integer, TSNode>
|
||||
for k, v in pairs(captures or {}) do
|
||||
old_match[k] = v[#v]
|
||||
|
@ -152,14 +152,14 @@ function M.open(path)
|
||||
else
|
||||
return nil, 'vim.ui.open: rundll32 not found'
|
||||
end
|
||||
elseif vim.fn.executable('wslview') == 1 then
|
||||
cmd = { 'wslview', path }
|
||||
elseif vim.fn.executable('explorer.exe') == 1 then
|
||||
cmd = { 'explorer.exe', path }
|
||||
elseif vim.fn.executable('xdg-open') == 1 then
|
||||
cmd = { 'xdg-open', path }
|
||||
opts.stdout = false
|
||||
opts.stderr = false
|
||||
elseif vim.fn.executable('wslview') == 1 then
|
||||
cmd = { 'wslview', path }
|
||||
elseif vim.fn.executable('explorer.exe') == 1 then
|
||||
cmd = { 'explorer.exe', path }
|
||||
else
|
||||
return nil, 'vim.ui.open: no handler found (tried: wslview, explorer.exe, xdg-open)'
|
||||
end
|
||||
@ -170,7 +170,7 @@ end
|
||||
--- Returns all URLs at cursor, if any.
|
||||
--- @return string[]
|
||||
function M._get_urls()
|
||||
local urls = {}
|
||||
local urls = {} ---@type string[]
|
||||
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local cursor = vim.api.nvim_win_get_cursor(0)
|
||||
@ -183,7 +183,7 @@ function M._get_urls()
|
||||
})
|
||||
for _, v in ipairs(extmarks) do
|
||||
local details = v[4]
|
||||
if details.url then
|
||||
if details and details.url then
|
||||
urls[#urls + 1] = details.url
|
||||
end
|
||||
end
|
||||
@ -195,15 +195,16 @@ function M._get_urls()
|
||||
local lang = ltree:lang()
|
||||
local query = vim.treesitter.query.get(lang, 'highlights')
|
||||
if query then
|
||||
local tree = ltree:tree_for_range(range)
|
||||
for _, match, metadata in query:iter_matches(tree:root(), bufnr, row, row + 1, { all = true }) do
|
||||
local tree = assert(ltree:tree_for_range(range))
|
||||
for _, match, metadata in query:iter_matches(tree:root(), bufnr, row, row + 1) do
|
||||
for id, nodes in pairs(match) do
|
||||
for _, node in ipairs(nodes) do
|
||||
if vim.treesitter.node_contains(node, range) then
|
||||
local url = metadata[id] and metadata[id].url
|
||||
if url and match[url] then
|
||||
for _, n in ipairs(match[url]) do
|
||||
urls[#urls + 1] = vim.treesitter.get_node_text(n, bufnr, metadata[url])
|
||||
urls[#urls + 1] =
|
||||
vim.treesitter.get_node_text(n, bufnr, { metadata = metadata[url] })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
66
runtime/syntax/hcl.vim
Normal file
66
runtime/syntax/hcl.vim
Normal file
@ -0,0 +1,66 @@
|
||||
" Vim syntax file
|
||||
" Language: HCL
|
||||
" Maintainer: Gregory Anders
|
||||
" Upstream: https://github.com/hashivim/vim-terraform
|
||||
" Last Change: 2024-09-03
|
||||
|
||||
if exists('b:current_syntax')
|
||||
finish
|
||||
endif
|
||||
|
||||
syn iskeyword a-z,A-Z,48-57,_,-
|
||||
|
||||
syn case match
|
||||
|
||||
" A block is introduced by a type, some number of labels - which are either
|
||||
" strings or identifiers - and an opening curly brace. Match the type.
|
||||
syn match hclBlockType /^\s*\zs\K\k*\ze\s\+\(\("\K\k*"\|\K\k*\)\s\+\)*{/
|
||||
|
||||
" An attribute name is an identifier followed by an equals sign.
|
||||
syn match hclAttributeAssignment /\(\K\k*\.\)*\K\k*\s\+=\s/ contains=hclAttributeName
|
||||
syn match hclAttributeName /\<\K\k*\>/ contained
|
||||
|
||||
syn keyword hclValueBool true false
|
||||
|
||||
syn keyword hclTodo contained TODO FIXME XXX BUG
|
||||
syn region hclComment start="/\*" end="\*/" contains=hclTodo,@Spell
|
||||
syn region hclComment start="#" end="$" contains=hclTodo,@Spell
|
||||
syn region hclComment start="//" end="$" contains=hclTodo,@Spell
|
||||
|
||||
""" misc.
|
||||
syn match hclValueDec "\<[0-9]\+\([kKmMgG]b\?\)\?\>"
|
||||
syn match hclValueHexaDec "\<0x[0-9a-f]\+\([kKmMgG]b\?\)\?\>"
|
||||
syn match hclBraces "[\[\]]"
|
||||
|
||||
""" skip \" and \\ in strings.
|
||||
syn region hclValueString start=/"/ skip=/\\\\\|\\"/ end=/"/ contains=hclStringInterp
|
||||
syn region hclStringInterp matchgroup=hclBraces start=/\(^\|[^$]\)\$\zs{/ end=/}/ contained contains=ALLBUT,hclAttributeName
|
||||
syn region hclHereDocText start=/<<-\?\z([a-z0-9A-Z]\+\)/ end=/^\s*\z1/ contains=hclStringInterp
|
||||
|
||||
"" Functions.
|
||||
syn match hclFunction "[a-z0-9]\+(\@="
|
||||
|
||||
""" HCL2
|
||||
syn keyword hclRepeat for in
|
||||
syn keyword hclConditional if
|
||||
syn keyword hclValueNull null
|
||||
|
||||
" enable block folding
|
||||
syn region hclBlockBody matchgroup=hclBraces start="{" end="}" fold transparent
|
||||
|
||||
hi def link hclComment Comment
|
||||
hi def link hclTodo Todo
|
||||
hi def link hclBraces Delimiter
|
||||
hi def link hclAttributeName Identifier
|
||||
hi def link hclBlockType Type
|
||||
hi def link hclValueBool Boolean
|
||||
hi def link hclValueDec Number
|
||||
hi def link hclValueHexaDec Number
|
||||
hi def link hclValueString String
|
||||
hi def link hclHereDocText String
|
||||
hi def link hclFunction Function
|
||||
hi def link hclRepeat Repeat
|
||||
hi def link hclConditional Conditional
|
||||
hi def link hclValueNull Constant
|
||||
|
||||
let b:current_syntax = 'hcl'
|
@ -2,9 +2,10 @@
|
||||
" Language: sudoers(5) configuration files
|
||||
" Maintainer: Eisuke Kawashima ( e.kawaschima+vim AT gmail.com )
|
||||
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
|
||||
" Latest Revision: 2021 Mar 15
|
||||
" Latest Revision: 2024 Sep 02
|
||||
" Recent Changes: Support for #include and #includedir.
|
||||
" Added many new options (Samuel D. Leslie)
|
||||
" Update allowed Tag_Spec Runas_Spec syntax items
|
||||
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
@ -22,7 +23,7 @@ syn match sudoersUserSpec '^' nextgroup=@sudoersUserInSpec skipwhite
|
||||
|
||||
syn match sudoersSpecEquals contained '=' nextgroup=@sudoersCmndSpecList skipwhite
|
||||
|
||||
syn cluster sudoersCmndSpecList contains=sudoersUserRunasBegin,sudoersPASSWD,@sudoersCmndInSpec
|
||||
syn cluster sudoersCmndSpecList contains=sudoersUserRunasBegin,sudoersTagSpec,@sudoersCmndInSpec
|
||||
|
||||
syn keyword sudoersTodo contained TODO FIXME XXX NOTE
|
||||
|
||||
@ -92,10 +93,11 @@ syn cluster sudoersUserList contains=sudoersUserListComma,sudoersUserLis
|
||||
syn match sudoersUserSpecComma contained ',' nextgroup=@sudoersUserInSpec skipwhite skipnl
|
||||
syn cluster sudoersUserSpec contains=sudoersUserSpecComma,@sudoersHostInSpec
|
||||
|
||||
syn match sudoersUserRunasBegin contained '(' nextgroup=@sudoersUserInRunas skipwhite skipnl
|
||||
syn match sudoersUserRunasBegin contained '(' nextgroup=@sudoersUserInRunas,sudoersUserRunasColon skipwhite skipnl
|
||||
syn match sudoersUserRunasComma contained ',' nextgroup=@sudoersUserInRunas skipwhite skipnl
|
||||
syn match sudoersUserRunasEnd contained ')' nextgroup=sudoersPASSWD,@sudoersCmndInSpec skipwhite skipnl
|
||||
syn cluster sudoersUserRunas contains=sudoersUserRunasComma,@sudoersUserInRunas,sudoersUserRunasEnd
|
||||
syn match sudoersUserRunasColon contained ':' nextgroup=@sudoersUserInRunas skipwhite skipnl
|
||||
syn match sudoersUserRunasEnd contained ')' nextgroup=sudoersTagSpec,@sudoersCmndInSpec skipwhite skipnl
|
||||
syn cluster sudoersUserRunas contains=sudoersUserRunasComma,sudoersUserRunasColon,@sudoersUserInRunas,sudoersUserRunasEnd
|
||||
|
||||
|
||||
syn match sudoersHostAliasEquals contained '=' nextgroup=@sudoersHostInList skipwhite skipnl
|
||||
@ -291,7 +293,7 @@ syn region sudoersStringValue contained start=+"+ skip=+\\"+ end=+"+ nextgroup
|
||||
syn match sudoersListValue contained '[^[:space:],:=\\]*\%(\\[[:space:],:=\\][^[:space:],:=\\]*\)*' nextgroup=sudoersParameterListComma skipwhite skipnl
|
||||
syn region sudoersListValue contained start=+"+ skip=+\\"+ end=+"+ nextgroup=sudoersParameterListComma skipwhite skipnl
|
||||
|
||||
syn match sudoersPASSWD contained '\%(NO\)\=PASSWD:' nextgroup=@sudoersCmndInSpec skipwhite
|
||||
syn match sudoersTagSpec contained '\%(NO\)\=\%(EXEC\|FOLLOW\|LOG_\%(INPUT\|OUTPUT\)\|MAIL\|INTERCEPT\|PASSWD\|SETENV\):' nextgroup=sudoersTagSpec,@sudoersCmndInSpec skipwhite
|
||||
|
||||
hi def link sudoersSpecEquals Operator
|
||||
hi def link sudoersTodo Todo
|
||||
@ -345,6 +347,7 @@ hi def link sudoersUserListColon Delimiter
|
||||
hi def link sudoersUserSpecComma Delimiter
|
||||
hi def link sudoersUserRunasBegin Delimiter
|
||||
hi def link sudoersUserRunasComma Delimiter
|
||||
hi def link sudoersUserRunasColon Delimiter
|
||||
hi def link sudoersUserRunasEnd Delimiter
|
||||
hi def link sudoersHostAliasEquals Operator
|
||||
hi def link sudoersHostListComma Delimiter
|
||||
@ -381,7 +384,7 @@ hi def link sudoersListParameterEquals Operator
|
||||
hi def link sudoersIntegerValue Number
|
||||
hi def link sudoersStringValue String
|
||||
hi def link sudoersListValue String
|
||||
hi def link sudoersPASSWD Special
|
||||
hi def link sudoersTagSpec Special
|
||||
hi def link sudoersInclude Statement
|
||||
|
||||
let b:current_syntax = "sudoers"
|
||||
|
17
runtime/syntax/terraform.vim
Normal file
17
runtime/syntax/terraform.vim
Normal file
@ -0,0 +1,17 @@
|
||||
" Vim syntax file
|
||||
" Language: Terraform
|
||||
" Maintainer: Gregory Anders
|
||||
" Upstream: https://github.com/hashivim/vim-terraform
|
||||
" Last Change: 2024-09-03
|
||||
|
||||
if exists('b:current_syntax')
|
||||
finish
|
||||
endif
|
||||
|
||||
runtime! syntax/hcl.vim
|
||||
|
||||
syn keyword terraType string bool number object tuple list map set any
|
||||
|
||||
hi def link terraType Type
|
||||
|
||||
let b:current_syntax = 'terraform'
|
@ -1,5 +1,5 @@
|
||||
" Language: tmux(1) configuration file
|
||||
" Version: 3.4 (git-171004df)
|
||||
" Version: 3.4 (git-3d8ead8a)
|
||||
" URL: https://github.com/ericpruitt/tmux.vim/
|
||||
" Maintainer: Eric Pruitt <eric.pruitt@gmail.com>
|
||||
" License: 2-Clause BSD (http://opensource.org/licenses/BSD-2-Clause)
|
||||
@ -37,7 +37,7 @@ syn match tmuxInvalidVariableExpansion /\${[^}]*$/ display
|
||||
syn match tmuxInvalidVariableExpansion /\${[^A-Za-z_][^}]*}/ display
|
||||
syn match tmuxInvalidVariableExpansion /\$[^A-Za-z_{ \t]/ display
|
||||
" Contains invalid character.
|
||||
syn match tmuxInvalidVariableExpansion /\${[^}]*[^A-Za-z0-9_][^}]*}/ display
|
||||
syn match tmuxInvalidVariableExpansion /\${[^}]*[^A-Za-z0-9_}][^}]*}/ display
|
||||
|
||||
syn region tmuxComment start=/#/ skip=/\\\@<!\\$/ end=/$/ contains=tmuxTodo,@Spell
|
||||
|
||||
|
@ -177,10 +177,11 @@ syn match vimNumber '\%(^\|\A\)\zs#\x\{6}' skipwhite nextgroup=vimGlobal,vimSub
|
||||
syn case match
|
||||
|
||||
" All vimCommands are contained by vimIsCommand. {{{2
|
||||
syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimCall,vimCatch,vimConst,vimDef,@vimEcho,vimEnddef,vimEndfunction,vimExecute,vimIsCommand,vimExtCmd,vimFor,vimFunction,vimGlobal,vimHighlight,vimLet,vimLoadkeymap,vimMap,vimMark,vimMatch,vimNotFunc,vimNorm,vimSet,vimSleep,vimSyntax,vimThrow,vimUnlet,vimUnmap,vimUserCmd,vimMenu,vimMenutranslate,@vim9CmdList
|
||||
syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimCall,vimCatch,vimConst,vimDef,vimDelcommand,@vimEcho,vimEnddef,vimEndfunction,vimExecute,vimIsCommand,vimExtCmd,vimFor,vimFunction,vimGlobal,vimHighlight,vimLet,vimLoadkeymap,vimMap,vimMark,vimMatch,vimNotFunc,vimNorm,vimSet,vimSleep,vimSyntax,vimThrow,vimUnlet,vimUnmap,vimUserCmd,vimMenu,vimMenutranslate,@vim9CmdList
|
||||
syn cluster vim9CmdList contains=vim9Const,vim9Final,vim9For,vim9Var
|
||||
syn match vimCmdSep "[:|]\+" skipwhite nextgroup=@vimCmdList,vimSubst1
|
||||
syn match vimIsCommand "\<\%(\h\w*\|[23]mat\%[ch]\)\>" contains=vimCommand
|
||||
syn match vimBang contained "!"
|
||||
syn match vimVar contained "\<\h[a-zA-Z0-9#_]*\>"
|
||||
syn match vimVar "\<[bwglstav]:\h[a-zA-Z0-9#_]*\>"
|
||||
syn match vimVar "\s\zs&\%([lg]:\)\=\a\+\>"
|
||||
@ -353,33 +354,46 @@ syn match vimSpecFileMod "\(:[phtre]\)\+" contained
|
||||
" User-Specified Commands: {{{2
|
||||
" =======================
|
||||
syn cluster vimUserCmdList contains=@vimCmdList,vimCmplxRepeat,@vimComment,vimCtrlChar,vimEscapeBrace,vimFunc,vimNotation,vimNumber,vimOper,vimRegister,vimSpecFile,vimString,vimSubst,vimSubstRep,vimSubstRange
|
||||
syn keyword vimUserCommand contained com[mand]
|
||||
syn match vimUserCmdName contained "\<\u\w*\>" nextgroup=vimUserCmdBlock skipwhite
|
||||
syn match vimUserCmd "\<com\%[mand]!\=\>.*$" contains=vimUserAttrb,vimUserAttrbError,vimUserCommand,@vimUserCmdList,vimComFilter,vimCmdBlock,vimUserCmdName
|
||||
syn match vimUserAttrbError contained "-\a\+\ze\s"
|
||||
syn match vimUserAttrb contained "-nargs=[01*?+]" contains=vimUserAttrbKey,vimOper
|
||||
syn match vimUserAttrb contained "-complete=" contains=vimUserAttrbKey,vimOper nextgroup=vimUserAttrbCmplt,vimUserCmdError
|
||||
syn match vimUserAttrb contained "-range\(=%\|=\d\+\)\=" contains=vimNumber,vimOper,vimUserAttrbKey
|
||||
syn match vimUserAttrb contained "-count\(=\d\+\)\=" contains=vimNumber,vimOper,vimUserAttrbKey
|
||||
syn match vimUserAttrb contained "-bang\>" contains=vimOper,vimUserAttrbKey
|
||||
syn match vimUserAttrb contained "-bar\>" contains=vimOper,vimUserAttrbKey
|
||||
syn match vimUserAttrb contained "-buffer\>" contains=vimOper,vimUserAttrbKey
|
||||
syn match vimUserAttrb contained "-register\>" contains=vimOper,vimUserAttrbKey
|
||||
syn keyword vimUserCmdKey contained com[mand]
|
||||
syn match vimUserCmdName contained "\<\u[[:alnum:]]*\>" skipwhite nextgroup=vimUserCmdBlock
|
||||
syn match vimUserCmd "\<com\%[mand]\>!\=.*$" contains=vimUserCmdKey,vimBang,vimUserCmdAttr,vimUserCmdAttrError,vimUserCmdName,@vimUserCmdList,vimComFilter
|
||||
syn match vimUserCmdAttrError contained "-\a\+\ze\%(\s\|=\)"
|
||||
syn match vimUserCmdAttr contained "-addr=" contains=vimUserCmdAttrKey nextgroup=vimUserCmdAttrAddr
|
||||
syn match vimUserCmdAttr contained "-bang\>" contains=vimUserCmdAttrKey
|
||||
syn match vimUserCmdAttr contained "-bar\>" contains=vimUserCmdAttrKey
|
||||
syn match vimUserCmdAttr contained "-buffer\>" contains=vimUserCmdAttrKey
|
||||
syn match vimUserCmdAttr contained "-complete=" contains=vimUserCmdAttrKey nextgroup=vimUserCmdAttrCmplt,vimUserCmdError
|
||||
syn match vimUserCmdAttr contained "-count\>" contains=vimUserCmdAttrKey
|
||||
syn match vimUserCmdAttr contained "-count=" contains=vimUserCmdAttrKey nextgroup=vimNumber
|
||||
syn match vimUserCmdAttr contained "-keepscript\>" contains=vimUserCmdAttrKey
|
||||
syn match vimUserCmdAttr contained "-nargs=" contains=vimUserCmdAttrKey nextgroup=vimUserCmdAttrNargs
|
||||
syn match vimUserCmdAttr contained "-range\>" contains=vimUserCmdAttrKey
|
||||
syn match vimUserCmdAttr contained "-range=" contains=vimUserCmdAttrKey nextgroup=vimNumber,vimUserCmdAttrRange
|
||||
syn match vimUserCmdAttr contained "-register\>" contains=vimUserCmdAttrKey
|
||||
|
||||
syn match vimUserCmdAttrNargs contained "[01*?+]"
|
||||
syn match vimUserCmdAttrRange contained "%"
|
||||
|
||||
if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_nousercmderror")
|
||||
syn match vimUserCmdError contained "\S\+\>"
|
||||
endif
|
||||
syn case ignore
|
||||
syn keyword vimUserAttrbKey contained bar ban[g] cou[nt] ra[nge] com[plete] n[args] re[gister]
|
||||
" GEN_SYN_VIM: vimUserAttrbCmplt, START_STR='syn keyword vimUserAttrbCmplt contained', END_STR=''
|
||||
syn keyword vimUserAttrbCmplt contained arglist augroup behave breakpoint buffer color command compiler cscope diff_buffer dir dir_in_path environment event expression file file_in_path filetype function help highlight history keymap locale mapclear mapping menu messages option packadd runtime scriptnames shellcmd sign syntax syntime tag tag_listfiles user var
|
||||
syn keyword vimUserAttrbCmplt contained custom customlist nextgroup=vimUserAttrbCmpltFunc,vimUserCmdError
|
||||
syn match vimUserAttrbCmpltFunc contained ",\%([sS]:\|<[sS][iI][dD]>\)\=\%(\h\w*\%([.#]\h\w*\)\+\|\h\w*\)"hs=s+1 nextgroup=vimUserCmdError
|
||||
|
||||
syn case ignore
|
||||
syn keyword vimUserCmdAttrKey contained a[ddr] ban[g] bar bu[ffer] com[plete] cou[nt] k[eepscript] n[args] ra[nge] re[gister]
|
||||
" GEN_SYN_VIM: vimUserCmdAttrCmplt, START_STR='syn keyword vimUserCmdAttrCmplt contained', END_STR=''
|
||||
syn keyword vimUserCmdAttrCmplt contained arglist augroup behave breakpoint buffer color command compiler cscope diff_buffer dir dir_in_path environment event expression file file_in_path filetype function help highlight history keymap locale mapclear mapping menu messages option packadd runtime scriptnames shellcmd sign syntax syntime tag tag_listfiles user var
|
||||
syn keyword vimUserCmdAttrCmplt contained custom customlist nextgroup=vimUserCmdAttrCmpltFunc,vimUserCmdError
|
||||
syn match vimUserCmdAttrCmpltFunc contained ",\%([sS]:\|<[sS][iI][dD]>\)\=\%(\h\w*\%([.#]\h\w*\)\+\|\h\w*\)"hs=s+1 nextgroup=vimUserCmdError
|
||||
" GEN_SYN_VIM: vimUserCmdAttrAddr, START_STR='syn keyword vimUserCmdAttrAddr contained', END_STR=''
|
||||
syn keyword vimUserCmdAttrAddr contained arguments arg buffers buf lines line loaded_buffers load other quickfix qf tabs tab windows win
|
||||
syn match vimUserCmdAttrAddr contained "?"
|
||||
syn case match
|
||||
syn match vimUserAttrbCmplt contained "custom,\u\w*"
|
||||
|
||||
syn region vimUserCmdBlock contained matchgroup=vimSep start="{" end="}" contains=@vimDefBodyList
|
||||
|
||||
syn match vimDelcommand "\<delc\%[ommand]\>" skipwhite nextgroup=vimDelcommandAttr
|
||||
syn match vimDelcommandAttr contained "-buffer\>"
|
||||
|
||||
" Lower Priority Comments: after some vim commands... {{{2
|
||||
" =======================
|
||||
if get(g:, "vimsyn_comment_strings", 1)
|
||||
@ -1162,6 +1176,8 @@ if !exists("skip_vim_syntax_inits")
|
||||
hi def link vimDefComment vim9Comment
|
||||
hi def link vimDefKey vimCommand
|
||||
hi def link vimDefParam vimVar
|
||||
hi def link vimDelcommand vimCommand
|
||||
hi def link vimDelcommandAttr vimUserCmdAttr
|
||||
hi def link vimEcho vimCommand
|
||||
hi def link vimEchohlNone vimGroup
|
||||
hi def link vimEchohl vimCommand
|
||||
@ -1319,13 +1335,15 @@ if !exists("skip_vim_syntax_inits")
|
||||
hi def link vimUnlet vimCommand
|
||||
hi def link vimUnletBang vimBang
|
||||
hi def link vimUnmap vimMap
|
||||
hi def link vimUserAttrbCmpltFunc Special
|
||||
hi def link vimUserAttrbCmplt vimSpecial
|
||||
hi def link vimUserAttrbKey vimOption
|
||||
hi def link vimUserAttrb vimSpecial
|
||||
hi def link vimUserAttrbError Error
|
||||
hi def link vimUserCmdAttrAddr vimSpecial
|
||||
hi def link vimUserCmdAttrCmplt vimSpecial
|
||||
hi def link vimUserCmdAttrNargs vimSpecial
|
||||
hi def link vimUserCmdAttrRange vimSpecial
|
||||
hi def link vimUserCmdAttrKey vimUserCmdAttr
|
||||
hi def link vimUserCmdAttr Special
|
||||
hi def link vimUserCmdAttrError Error
|
||||
hi def link vimUserCmdError Error
|
||||
hi def link vimUserCommand vimCommand
|
||||
hi def link vimUserCmdKey vimCommand
|
||||
hi def link vimUserFunc Normal
|
||||
hi def link vimVar Identifier
|
||||
hi def link vimWarn WarningMsg
|
||||
|
@ -373,8 +373,8 @@ local config = {
|
||||
section_fmt = function(_name)
|
||||
return 'Checkhealth'
|
||||
end,
|
||||
helptag_fmt = function(name)
|
||||
return name:lower()
|
||||
helptag_fmt = function()
|
||||
return 'vim.health* *health' -- HACK
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
@ -54,8 +54,6 @@ if(ENABLE_WASMTIME)
|
||||
target_compile_definitions(nvim_bin PRIVATE HAVE_WASMTIME)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(main_lib INTERFACE HAVE_UNIBILIUM)
|
||||
|
||||
# The unit test lib requires LuaJIT; it will be skipped if LuaJIT is missing.
|
||||
option(PREFER_LUA "Prefer Lua over LuaJIT in the nvim executable." OFF)
|
||||
if(PREFER_LUA)
|
||||
@ -153,7 +151,7 @@ if(UNIX)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
target_compile_definitions(main_lib INTERFACE _WIN32_WINNT=0x0602 MSWIN)
|
||||
target_compile_definitions(main_lib INTERFACE _WIN32_WINNT=0x0602 MSWIN WIN32_LEAN_AND_MEAN)
|
||||
target_link_libraries(main_lib INTERFACE netapi32)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
target_link_libraries(nvim_bin PRIVATE "-framework CoreServices")
|
||||
@ -366,8 +364,8 @@ file(MAKE_DIRECTORY ${TOUCHES_DIR} ${GENERATED_DIR} ${GENERATED_INCLUDES_DIR})
|
||||
|
||||
file(GLOB NVIM_SOURCES CONFIGURE_DEPENDS *.c)
|
||||
file(GLOB NVIM_HEADERS CONFIGURE_DEPENDS *.h)
|
||||
file(GLOB EXTERNAL_SOURCES CONFIGURE_DEPENDS ../xdiff/*.c ../mpack/*.c ../cjson/*.c ../klib/*.c ../termkey/*.c ../vterm/*.c)
|
||||
file(GLOB EXTERNAL_HEADERS CONFIGURE_DEPENDS ../xdiff/*.h ../mpack/*.h ../cjson/*.h ../klib/*.h ../termkey/*.h ../vterm/*.h)
|
||||
file(GLOB EXTERNAL_SOURCES CONFIGURE_DEPENDS ../xdiff/*.c ../mpack/*.c ../cjson/*.c ../klib/*.c ../vterm/*.c)
|
||||
file(GLOB EXTERNAL_HEADERS CONFIGURE_DEPENDS ../xdiff/*.h ../mpack/*.h ../cjson/*.h ../klib/*.h ../vterm/*.h)
|
||||
|
||||
file(GLOB NLUA0_SOURCES CONFIGURE_DEPENDS ../mpack/*.c)
|
||||
|
||||
@ -378,6 +376,15 @@ if(PREFER_LUA)
|
||||
target_compile_definitions(main_lib INTERFACE NVIM_VENDOR_BIT)
|
||||
endif()
|
||||
|
||||
# Inlined external projects, we don't maintain it. #9306
|
||||
if(MSVC)
|
||||
set_source_files_properties(
|
||||
${EXTERNAL_SOURCES} PROPERTIES COMPILE_OPTIONS "-wd4090;-wd4244;-wd4267")
|
||||
else()
|
||||
set_source_files_properties(
|
||||
${EXTERNAL_SOURCES} PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-missing-noreturn;-Wno-missing-format-attribute;-Wno-double-promotion;-Wno-strict-prototypes;-Wno-misleading-indentation;-Wno-sign-compare;-Wno-implicit-fallthrough;-Wno-missing-prototypes;-Wno-missing-field-initializers")
|
||||
endif()
|
||||
|
||||
list(APPEND NLUA0_SOURCES ${PROJECT_SOURCE_DIR}/src/nlua0.c)
|
||||
|
||||
foreach(subdir
|
||||
@ -386,6 +393,7 @@ foreach(subdir
|
||||
api/private
|
||||
msgpack_rpc
|
||||
tui
|
||||
tui/termkey
|
||||
event
|
||||
eval
|
||||
lua
|
||||
@ -407,49 +415,36 @@ endforeach()
|
||||
list(SORT NVIM_SOURCES)
|
||||
list(SORT NVIM_HEADERS)
|
||||
|
||||
list(APPEND LINT_NVIM_SOURCES ${NVIM_SOURCES} ${NVIM_HEADERS})
|
||||
|
||||
foreach(sfile ${NVIM_SOURCES})
|
||||
get_filename_component(f ${sfile} NAME)
|
||||
if(WIN32 AND ${f} MATCHES "^(pty_process_unix.c)$")
|
||||
list(APPEND to_remove ${sfile})
|
||||
list(REMOVE_ITEM NVIM_SOURCES ${sfile})
|
||||
endif()
|
||||
if(NOT WIN32 AND ${f} MATCHES "^(pty_process_win.c)$")
|
||||
list(APPEND to_remove ${sfile})
|
||||
list(REMOVE_ITEM NVIM_SOURCES ${sfile})
|
||||
endif()
|
||||
if(NOT WIN32 AND ${f} MATCHES "^(pty_conpty_win.c)$")
|
||||
list(APPEND to_remove ${sfile})
|
||||
list(REMOVE_ITEM NVIM_SOURCES ${sfile})
|
||||
endif()
|
||||
if(NOT WIN32 AND ${f} MATCHES "^(os_win_console.c)$")
|
||||
list(APPEND to_remove ${sfile})
|
||||
list(REMOVE_ITEM NVIM_SOURCES ${sfile})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
list(REMOVE_ITEM NVIM_SOURCES ${to_remove})
|
||||
|
||||
foreach(hfile ${NVIM_HEADERS})
|
||||
get_filename_component(f ${hfile} NAME)
|
||||
if(WIN32 AND ${f} MATCHES "^(unix_defs.h)$")
|
||||
list(APPEND to_remove_h ${hfile})
|
||||
list(REMOVE_ITEM NVIM_HEADERS ${hfile})
|
||||
endif()
|
||||
if(WIN32 AND ${f} MATCHES "^(pty_process_unix.h)$")
|
||||
list(APPEND to_remove_h ${hfile})
|
||||
list(REMOVE_ITEM NVIM_HEADERS ${hfile})
|
||||
endif()
|
||||
if(NOT WIN32 AND ${f} MATCHES "^(win_defs.h)$")
|
||||
list(APPEND to_remove_h ${hfile})
|
||||
list(REMOVE_ITEM NVIM_HEADERS ${hfile})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
list(REMOVE_ITEM NVIM_HEADERS ${to_remove_h})
|
||||
|
||||
# xdiff, mpack, lua-cjson, termkey: inlined external project, we don't maintain it. #9306
|
||||
if(MSVC)
|
||||
set_source_files_properties(
|
||||
${EXTERNAL_SOURCES} PROPERTIES COMPILE_OPTIONS "-wd4090;-wd4244;-wd4267")
|
||||
else()
|
||||
set_source_files_properties(
|
||||
${EXTERNAL_SOURCES} PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-missing-noreturn;-Wno-missing-format-attribute;-Wno-double-promotion;-Wno-strict-prototypes;-Wno-misleading-indentation;-Wno-sign-compare;-Wno-implicit-fallthrough;-Wno-missing-prototypes;-Wno-missing-field-initializers")
|
||||
endif()
|
||||
list(APPEND LINT_NVIM_SOURCES ${NVIM_SOURCES} ${NVIM_HEADERS})
|
||||
|
||||
# Log level (NVIM_LOG_DEBUG in log.h)
|
||||
if(CI_BUILD)
|
||||
@ -849,7 +844,7 @@ endif()
|
||||
add_glob_target(
|
||||
TARGET lintc-clang-tidy
|
||||
COMMAND ${CLANG_TIDY_PRG}
|
||||
FILES ${NVIM_SOURCES} ${NVIM_HEADERS}
|
||||
FILES ${LINT_NVIM_SOURCES}
|
||||
FLAGS --quiet
|
||||
EXCLUDE ${EXCLUDE_CLANG_TIDY})
|
||||
|
||||
@ -862,7 +857,7 @@ endif()
|
||||
add_glob_target(
|
||||
TARGET clang-analyzer
|
||||
COMMAND ${CLANG_TIDY_PRG}
|
||||
FILES ${NVIM_SOURCES} ${NVIM_HEADERS}
|
||||
FILES ${LINT_NVIM_SOURCES}
|
||||
FLAGS --quiet
|
||||
--checks='
|
||||
-*,
|
||||
@ -905,13 +900,13 @@ add_glob_target(
|
||||
TARGET lintc-uncrustify
|
||||
COMMAND ${UNCRUSTIFY_PRG}
|
||||
FLAGS -c ${UNCRUSTIFY_CONFIG} -q --check
|
||||
FILES ${LINT_NVIM_SOURCES})
|
||||
FILES ${NVIM_SOURCES} ${NVIM_HEADERS})
|
||||
|
||||
add_glob_target(
|
||||
TARGET formatc
|
||||
COMMAND ${UNCRUSTIFY_PRG}
|
||||
FLAGS -c ${UNCRUSTIFY_CONFIG} --replace --no-backup
|
||||
FILES ${LINT_NVIM_SOURCES})
|
||||
FILES ${NVIM_SOURCES} ${NVIM_HEADERS})
|
||||
|
||||
add_dependencies(lintc-uncrustify uncrustify_update_config)
|
||||
add_dependencies(formatc uncrustify_update_config)
|
||||
|
@ -528,21 +528,15 @@ String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col
|
||||
start_col = start_col < 0 ? line_length + start_col + 1 : start_col;
|
||||
end_col = end_col < 0 ? line_length + end_col + 1 : end_col;
|
||||
|
||||
if (start_col >= MAXCOL || end_col >= MAXCOL) {
|
||||
api_set_error(err, kErrorTypeValidation, "Column index is too high");
|
||||
return rv;
|
||||
}
|
||||
start_col = MIN(MAX(0, start_col), line_length);
|
||||
end_col = MIN(MAX(0, end_col), line_length);
|
||||
|
||||
if (start_col > end_col) {
|
||||
api_set_error(err, kErrorTypeValidation, "start_col must be less than end_col");
|
||||
api_set_error(err, kErrorTypeValidation, "start_col must be less than or equal to end_col");
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (start_col >= line_length) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return cstrn_as_string(&bufstr[start_col], (size_t)(end_col - start_col));
|
||||
return cbuf_as_string(bufstr + start_col, (size_t)(end_col - start_col));
|
||||
}
|
||||
|
||||
void api_free_string(String value)
|
||||
|
@ -93,15 +93,15 @@ void remote_ui_free_all_mem(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Wait until ui has connected on stdio channel if only_stdio
|
||||
/// is true, otherwise any channel.
|
||||
/// Wait until UI has connected.
|
||||
///
|
||||
/// @param only_stdio UI is expected to connect on stdio.
|
||||
void remote_ui_wait_for_attach(bool only_stdio)
|
||||
{
|
||||
if (only_stdio) {
|
||||
Channel *channel = find_channel(CHAN_STDIO);
|
||||
if (!channel) {
|
||||
// this function should only be called in --embed mode, stdio channel
|
||||
// can be assumed.
|
||||
// `only_stdio` implies --embed mode, thus stdio channel can be assumed.
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "nvim/cursor.h"
|
||||
#include "nvim/decoration.h"
|
||||
#include "nvim/drawscreen.h"
|
||||
#include "nvim/edit.h"
|
||||
#include "nvim/errors.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
|
@ -756,10 +756,8 @@ void ins_char_bytes(char *buf, size_t charlen)
|
||||
// put back when BS is used. The bytes of a multi-byte character are
|
||||
// done the other way around, so that the first byte is popped off
|
||||
// first (it tells the byte length of the character).
|
||||
replace_push(NUL);
|
||||
for (size_t i = 0; i < oldlen; i++) {
|
||||
i += (size_t)replace_push_mb(oldp + col + i) - 1;
|
||||
}
|
||||
replace_push_nul();
|
||||
replace_push(oldp + col, oldlen);
|
||||
}
|
||||
|
||||
char *newp = xmalloc(linelen + newlen - oldlen);
|
||||
@ -1137,12 +1135,10 @@ bool open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
|
||||
// on the line onto the replace stack. We'll push any other characters
|
||||
// that might be replaced at the start of the next line (due to
|
||||
// autoindent etc) a bit later.
|
||||
replace_push(NUL); // Call twice because BS over NL expects it
|
||||
replace_push(NUL);
|
||||
replace_push_nul(); // Call twice because BS over NL expects it
|
||||
replace_push_nul();
|
||||
p = saved_line + curwin->w_cursor.col;
|
||||
while (*p != NUL) {
|
||||
p += replace_push_mb(p);
|
||||
}
|
||||
replace_push(p, strlen(p));
|
||||
saved_line[curwin->w_cursor.col] = NUL;
|
||||
}
|
||||
|
||||
@ -1691,13 +1687,13 @@ bool open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
|
||||
// stack, preceded by a NUL, so they can be put back when a BS is
|
||||
// entered.
|
||||
if (REPLACE_NORMAL(State)) {
|
||||
replace_push(NUL); // end of extra blanks
|
||||
replace_push_nul(); // end of extra blanks
|
||||
}
|
||||
if (curbuf->b_p_ai || (flags & OPENLINE_DELSPACES)) {
|
||||
while ((*p_extra == ' ' || *p_extra == '\t')
|
||||
&& !utf_iscomposing_first(utf_ptr2char(p_extra + 1))) {
|
||||
if (REPLACE_NORMAL(State)) {
|
||||
replace_push(*p_extra);
|
||||
replace_push(p_extra, 1); // always ascii, len = 1
|
||||
}
|
||||
p_extra++;
|
||||
less_cols_off++;
|
||||
@ -1794,7 +1790,7 @@ bool open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
|
||||
// must be a NUL on the replace stack, for when it is deleted with BS
|
||||
if (REPLACE_NORMAL(State)) {
|
||||
for (colnr_T n = 0; n < curwin->w_cursor.col; n++) {
|
||||
replace_push(NUL);
|
||||
replace_push_nul();
|
||||
}
|
||||
}
|
||||
newcol += curwin->w_cursor.col;
|
||||
@ -1808,7 +1804,7 @@ bool open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
|
||||
// must be a NUL on the replace stack, for when it is deleted with BS.
|
||||
if (REPLACE_NORMAL(State)) {
|
||||
while (lead_len-- > 0) {
|
||||
replace_push(NUL);
|
||||
replace_push_nul();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2453,10 +2453,12 @@ redr_statuscol:
|
||||
recursive = true;
|
||||
curwin->w_valid &= ~VALID_TOPLINE;
|
||||
update_topline(curwin); // may invalidate w_botline again
|
||||
// New redraw either due to updated topline or reset skipcol.
|
||||
if (must_redraw != 0) {
|
||||
// Don't update for changes in buffer again.
|
||||
int mod_set = curbuf->b_mod_set;
|
||||
curbuf->b_mod_set = false;
|
||||
curs_columns(curwin, true);
|
||||
win_update(curwin);
|
||||
must_redraw = 0;
|
||||
curbuf->b_mod_set = mod_set;
|
||||
|
171
src/nvim/edit.c
171
src/nvim/edit.c
@ -136,6 +136,8 @@ static TriState dont_sync_undo = kFalse; // CTRL-G U prevents syncing undo
|
||||
|
||||
static linenr_T o_lnum = 0;
|
||||
|
||||
static kvec_t(char) replace_stack = KV_INITIAL_VALUE;
|
||||
|
||||
static void insert_enter(InsertState *s)
|
||||
{
|
||||
s->did_backspace = true;
|
||||
@ -1618,9 +1620,8 @@ void undisplay_dollar(void)
|
||||
/// type == INDENT_SET set indent to "amount"
|
||||
///
|
||||
/// @param round if true, round the indent to 'shiftwidth' (only with _INC and _Dec).
|
||||
/// @param replaced replaced character, put on replace stack
|
||||
/// @param call_changed_bytes call changed_bytes()
|
||||
void change_indent(int type, int amount, int round, int replaced, bool call_changed_bytes)
|
||||
void change_indent(int type, int amount, int round, bool call_changed_bytes)
|
||||
{
|
||||
int insstart_less; // reduction for Insstart.col
|
||||
colnr_T orig_col = 0; // init for GCC
|
||||
@ -1767,12 +1768,8 @@ void change_indent(int type, int amount, int round, int replaced, bool call_chan
|
||||
replace_join(0); // remove a NUL from the replace stack
|
||||
start_col--;
|
||||
}
|
||||
while (start_col < (int)curwin->w_cursor.col || replaced) {
|
||||
replace_push(NUL);
|
||||
if (replaced) {
|
||||
replace_push(replaced);
|
||||
replaced = NUL;
|
||||
}
|
||||
while (start_col < (int)curwin->w_cursor.col) {
|
||||
replace_push_nul();
|
||||
start_col++;
|
||||
}
|
||||
}
|
||||
@ -2325,7 +2322,7 @@ int stop_arrow(void)
|
||||
static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
|
||||
{
|
||||
stop_redo_ins();
|
||||
replace_flush(); // abandon replace stack
|
||||
kv_destroy(replace_stack); // abandon replace stack (reinitializes)
|
||||
|
||||
// Save the inserted text for later redo with ^@ and CTRL-A.
|
||||
// Don't do it when "restart_edit" was set and nothing was inserted,
|
||||
@ -2802,57 +2799,51 @@ static bool echeck_abbr(int c)
|
||||
// that the NL replaced. The extra one stores the characters after the cursor
|
||||
// that were deleted (always white space).
|
||||
|
||||
static uint8_t *replace_stack = NULL;
|
||||
static ssize_t replace_stack_nr = 0; // next entry in replace stack
|
||||
static ssize_t replace_stack_len = 0; // max. number of entries
|
||||
|
||||
/// Push character that is replaced onto the replace stack.
|
||||
///
|
||||
/// replace_offset is normally 0, in which case replace_push will add a new
|
||||
/// character at the end of the stack. If replace_offset is not 0, that many
|
||||
/// characters will be left on the stack above the newly inserted character.
|
||||
///
|
||||
/// @param c character that is replaced (NUL is none)
|
||||
void replace_push(int c)
|
||||
/// @param str character that is replaced (NUL is none)
|
||||
/// @param len length of character in bytes
|
||||
void replace_push(char *str, size_t len)
|
||||
{
|
||||
if (replace_stack_nr < replace_offset) { // nothing to do
|
||||
// TODO(bfredl): replace_offset is suss af, if we don't need it, this
|
||||
// function is just kv_concat() :p
|
||||
if (kv_size(replace_stack) < (size_t)replace_offset) { // nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
if (replace_stack_len <= replace_stack_nr) {
|
||||
replace_stack_len += 50;
|
||||
replace_stack = xrealloc(replace_stack, (size_t)replace_stack_len);
|
||||
}
|
||||
uint8_t *p = replace_stack + replace_stack_nr - replace_offset;
|
||||
kv_ensure_space(replace_stack, len);
|
||||
|
||||
char *p = replace_stack.items + kv_size(replace_stack) - replace_offset;
|
||||
if (replace_offset) {
|
||||
memmove(p + 1, p, (size_t)replace_offset);
|
||||
memmove(p + len, p, (size_t)replace_offset);
|
||||
}
|
||||
*p = (uint8_t)c;
|
||||
replace_stack_nr++;
|
||||
memcpy(p, str, len);
|
||||
kv_size(replace_stack) += len;
|
||||
}
|
||||
|
||||
/// Push a character onto the replace stack. Handles a multi-byte character in
|
||||
/// reverse byte order, so that the first byte is popped off first.
|
||||
///
|
||||
/// @return the number of bytes done (includes composing characters).
|
||||
int replace_push_mb(char *p)
|
||||
/// push NUL as separator between entries in the stack
|
||||
void replace_push_nul(void)
|
||||
{
|
||||
int l = utfc_ptr2len(p);
|
||||
|
||||
// TODO(bfredl): stop doing this insantity and instead use utf_head_off() when popping.
|
||||
// or just keep a secondary array with char byte lenghts
|
||||
for (int j = l - 1; j >= 0; j--) {
|
||||
replace_push(p[j]);
|
||||
}
|
||||
return l;
|
||||
replace_push("", 1);
|
||||
}
|
||||
|
||||
/// Pop one item from the replace stack.
|
||||
/// Check top of replace stack, pop it if it was NUL
|
||||
///
|
||||
/// @return -1 if stack is empty, replaced character or NUL otherwise
|
||||
static int replace_pop(void)
|
||||
/// when a non-NUL byte is found, use mb_replace_pop_ins() to
|
||||
/// pop one complete multibyte character.
|
||||
///
|
||||
/// @return -1 if stack is empty, last byte of char or NUL otherwise
|
||||
static int replace_pop_if_nul(void)
|
||||
{
|
||||
return (replace_stack_nr == 0) ? -1 : (int)replace_stack[--replace_stack_nr];
|
||||
int ch = (kv_size(replace_stack)) ? (uint8_t)kv_A(replace_stack, kv_size(replace_stack) - 1) : -1;
|
||||
if (ch == NUL) {
|
||||
kv_size(replace_stack)--;
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
/// Join the top two items on the replace stack. This removes to "off"'th NUL
|
||||
@ -2861,11 +2852,11 @@ static int replace_pop(void)
|
||||
/// @param off offset for which NUL to remove
|
||||
static void replace_join(int off)
|
||||
{
|
||||
for (ssize_t i = replace_stack_nr; --i >= 0;) {
|
||||
if (replace_stack[i] == NUL && off-- <= 0) {
|
||||
replace_stack_nr--;
|
||||
memmove(replace_stack + i, replace_stack + i + 1,
|
||||
(size_t)(replace_stack_nr - i));
|
||||
for (ssize_t i = (ssize_t)kv_size(replace_stack); --i >= 0;) {
|
||||
if (kv_A(replace_stack, i) == NUL && off-- <= 0) {
|
||||
kv_size(replace_stack)--;
|
||||
memmove(&kv_A(replace_stack, i), &kv_A(replace_stack, i + 1),
|
||||
(kv_size(replace_stack) - (size_t)i));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2875,72 +2866,25 @@ static void replace_join(int off)
|
||||
/// before the cursor. Can only be used in MODE_REPLACE or MODE_VREPLACE state.
|
||||
static void replace_pop_ins(void)
|
||||
{
|
||||
int cc;
|
||||
int oldState = State;
|
||||
|
||||
State = MODE_NORMAL; // don't want MODE_REPLACE here
|
||||
while ((cc = replace_pop()) > 0) {
|
||||
mb_replace_pop_ins(cc);
|
||||
while ((replace_pop_if_nul()) > 0) {
|
||||
mb_replace_pop_ins();
|
||||
dec_cursor();
|
||||
}
|
||||
State = oldState;
|
||||
}
|
||||
|
||||
// Insert bytes popped from the replace stack. "cc" is the first byte. If it
|
||||
// indicates a multi-byte char, pop the other bytes too.
|
||||
static void mb_replace_pop_ins(int cc)
|
||||
/// Insert multibyte char popped from the replace stack.
|
||||
///
|
||||
/// caller must already have checked the top of the stack is not NUL!!
|
||||
static void mb_replace_pop_ins(void)
|
||||
{
|
||||
int n;
|
||||
uint8_t buf[MB_MAXBYTES + 1];
|
||||
|
||||
if ((n = MB_BYTE2LEN(cc)) > 1) {
|
||||
buf[0] = (uint8_t)cc;
|
||||
for (int i = 1; i < n; i++) {
|
||||
buf[i] = (uint8_t)replace_pop();
|
||||
}
|
||||
ins_bytes_len((char *)buf, (size_t)n);
|
||||
} else {
|
||||
ins_char(cc);
|
||||
}
|
||||
|
||||
// Handle composing chars.
|
||||
while (true) {
|
||||
int c = replace_pop();
|
||||
if (c == -1) { // stack empty
|
||||
break;
|
||||
}
|
||||
if ((n = MB_BYTE2LEN(c)) == 1) {
|
||||
// Not a multi-byte char, put it back.
|
||||
replace_push(c);
|
||||
break;
|
||||
}
|
||||
|
||||
buf[0] = (uint8_t)c;
|
||||
assert(n > 1);
|
||||
for (int i = 1; i < n; i++) {
|
||||
buf[i] = (uint8_t)replace_pop();
|
||||
}
|
||||
// TODO(bfredl): by fixing replace_push_mb, upgrade to use
|
||||
// the new composing algorithm
|
||||
if (utf_iscomposing_legacy(utf_ptr2char((char *)buf))) {
|
||||
ins_bytes_len((char *)buf, (size_t)n);
|
||||
} else {
|
||||
// Not a composing char, put it back.
|
||||
for (int i = n - 1; i >= 0; i--) {
|
||||
replace_push(buf[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make the replace stack empty
|
||||
// (called when exiting replace mode)
|
||||
static void replace_flush(void)
|
||||
{
|
||||
XFREE_CLEAR(replace_stack);
|
||||
replace_stack_len = 0;
|
||||
replace_stack_nr = 0;
|
||||
int len = utf_head_off(&kv_A(replace_stack, 0),
|
||||
&kv_A(replace_stack, kv_size(replace_stack) - 1)) + 1;
|
||||
kv_size(replace_stack) -= (size_t)len;
|
||||
ins_bytes_len(&kv_A(replace_stack, kv_size(replace_stack)), (size_t)len);
|
||||
}
|
||||
|
||||
// Handle doing a BS for one character.
|
||||
@ -2955,7 +2899,7 @@ static void replace_do_bs(int limit_col)
|
||||
colnr_T start_vcol;
|
||||
const int l_State = State;
|
||||
|
||||
int cc = replace_pop();
|
||||
int cc = replace_pop_if_nul();
|
||||
if (cc > 0) {
|
||||
int orig_len = 0;
|
||||
int orig_vcols = 0;
|
||||
@ -2969,7 +2913,6 @@ static void replace_do_bs(int limit_col)
|
||||
if (l_State & VREPLACE_FLAG) {
|
||||
orig_len = get_cursor_pos_len();
|
||||
}
|
||||
replace_push(cc);
|
||||
replace_pop_ins();
|
||||
|
||||
if (l_State & VREPLACE_FLAG) {
|
||||
@ -3628,9 +3571,9 @@ static void ins_shift(int c, int lastc)
|
||||
if (lastc == '^') {
|
||||
old_indent = get_indent(); // remember curr. indent
|
||||
}
|
||||
change_indent(INDENT_SET, 0, true, 0, true);
|
||||
change_indent(INDENT_SET, 0, true, true);
|
||||
} else {
|
||||
change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, true, 0, true);
|
||||
change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, true, true);
|
||||
}
|
||||
|
||||
if (did_ai && *skipwhite(get_cursor_line_ptr()) != NUL) {
|
||||
@ -3749,7 +3692,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
|
||||
// cc >= 0: NL was replaced, put original characters back
|
||||
cc = -1;
|
||||
if (State & REPLACE_FLAG) {
|
||||
cc = replace_pop(); // returns -1 if NL was inserted
|
||||
cc = replace_pop_if_nul(); // returns -1 if NL was inserted
|
||||
}
|
||||
// In replace mode, in the line we started replacing, we only move the
|
||||
// cursor.
|
||||
@ -3795,9 +3738,9 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
|
||||
// restore characters (blanks) deleted after cursor
|
||||
while (cc > 0) {
|
||||
colnr_T save_col = curwin->w_cursor.col;
|
||||
mb_replace_pop_ins(cc);
|
||||
mb_replace_pop_ins();
|
||||
curwin->w_cursor.col = save_col;
|
||||
cc = replace_pop();
|
||||
cc = replace_pop_if_nul();
|
||||
}
|
||||
// restore the characters that NL replaced
|
||||
replace_pop_ins();
|
||||
@ -3906,7 +3849,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
|
||||
} else {
|
||||
ins_str(" ");
|
||||
if ((State & REPLACE_FLAG)) {
|
||||
replace_push(NUL);
|
||||
replace_push_nul();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4316,7 +4259,7 @@ static bool ins_tab(void)
|
||||
} else {
|
||||
ins_str(" ");
|
||||
if (State & REPLACE_FLAG) { // no char replaced
|
||||
replace_push(NUL);
|
||||
replace_push_nul();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4483,7 +4426,7 @@ bool ins_eol(int c)
|
||||
// character under the cursor. Only push a NUL on the replace stack,
|
||||
// nothing to put back when the NL is deleted.
|
||||
if ((State & REPLACE_FLAG) && !(State & VREPLACE_FLAG)) {
|
||||
replace_push(NUL);
|
||||
replace_push_nul();
|
||||
}
|
||||
|
||||
// In MODE_VREPLACE state, a NL replaces the rest of the line, and starts
|
||||
@ -4684,7 +4627,7 @@ static void ins_try_si(int c)
|
||||
i = get_indent();
|
||||
curwin->w_cursor = old_pos;
|
||||
if (State & VREPLACE_FLAG) {
|
||||
change_indent(INDENT_SET, i, false, NUL, true);
|
||||
change_indent(INDENT_SET, i, false, true);
|
||||
} else {
|
||||
set_indent(i, SIN_CHANGED);
|
||||
}
|
||||
|
@ -6442,6 +6442,7 @@ M.funcs = {
|
||||
"lhsrawalt" The {lhs} of the mapping as raw bytes, alternate
|
||||
form, only present when it differs from "lhsraw"
|
||||
"rhs" The {rhs} of the mapping as typed.
|
||||
"callback" Lua function, if RHS was defined as such.
|
||||
"silent" 1 for a |:map-silent| mapping, else 0.
|
||||
"noremap" 1 if the {rhs} of the mapping is not remappable.
|
||||
"script" 1 if mapping was defined with <script>.
|
||||
|
@ -7641,7 +7641,7 @@ static void get_xdg_var_list(const XDGVarType xdg, typval_T *rettv)
|
||||
return;
|
||||
}
|
||||
const void *iter = NULL;
|
||||
const char *appname = get_appname();
|
||||
const char *appname = get_appname(false);
|
||||
do {
|
||||
size_t dir_len;
|
||||
const char *dir;
|
||||
|
@ -16,15 +16,14 @@ struct loop {
|
||||
uv_loop_t uv;
|
||||
MultiQueue *events;
|
||||
MultiQueue *thread_events;
|
||||
// Immediate events:
|
||||
// "Processed after exiting uv_run() (to avoid recursion), but before
|
||||
// returning from loop_poll_events()." 502aee690c98
|
||||
// Practical consequence (for main_loop): these events are processed by
|
||||
// state_enter()..os_inchar()
|
||||
// whereas "regular" events (main_loop.events) are processed by
|
||||
// state_enter()..VimState.execute()
|
||||
// But state_enter()..os_inchar() can be "too early" if you want the event
|
||||
// to trigger UI updates and other user-activity-related side-effects.
|
||||
// Immediate events.
|
||||
// - "Processed after exiting `uv_run()` (to avoid recursion), but before returning from
|
||||
// `loop_poll_events()`." 502aee690c98
|
||||
// - Practical consequence (for `main_loop`):
|
||||
// - these are processed by `state_enter()..input_get()` whereas "regular" events
|
||||
// (`main_loop.events`) are processed by `state_enter()..VimState.execute()`
|
||||
// - `state_enter()..input_get()` can be "too early" if you want the event to trigger UI
|
||||
// updates and other user-activity-related side-effects.
|
||||
MultiQueue *fast_events;
|
||||
|
||||
// used by process/job-control subsystem
|
||||
|
@ -2499,6 +2499,15 @@ int parse_command_modifiers(exarg_T *eap, const char **errormsg, cmdmod_T *cmod,
|
||||
|
||||
// ignore comment and empty lines
|
||||
if (*eap->cmd == '"') {
|
||||
// a comment ends at a NL
|
||||
eap->nextcmd = vim_strchr(eap->cmd, '\n');
|
||||
if (eap->nextcmd != NULL) {
|
||||
eap->nextcmd++;
|
||||
}
|
||||
return FAIL;
|
||||
}
|
||||
if (*eap->cmd == '\n') {
|
||||
eap->nextcmd = eap->cmd + 1;
|
||||
return FAIL;
|
||||
}
|
||||
if (*eap->cmd == NUL) {
|
||||
|
@ -70,24 +70,19 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
|
||||
extmark_del_id(buf, ns_id, id);
|
||||
} else {
|
||||
assert(marktree_itr_valid(itr));
|
||||
bool invalid = mt_invalid(old_mark);
|
||||
if (old_mark.pos.row == row && old_mark.pos.col == col) {
|
||||
// not paired: we can revise in place
|
||||
if (!invalid && mt_decor_any(old_mark)) {
|
||||
// TODO(bfredl): conflict of concerns: buf_decor_remove() must process
|
||||
// the buffer as if MT_FLAG_DECOR_SIGNTEXT is already removed, however
|
||||
// marktree must precisely adjust the set of flags from the old set to the new
|
||||
uint16_t save_flags = mt_itr_rawkey(itr).flags;
|
||||
mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_DECOR_SIGNTEXT;
|
||||
if (!mt_invalid(old_mark) && mt_decor_any(old_mark)) {
|
||||
mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_EXTERNAL_MASK;
|
||||
buf_decor_remove(buf, row, row, col, mt_decor(old_mark), true);
|
||||
mt_itr_rawkey(itr).flags = save_flags;
|
||||
}
|
||||
marktree_revise_flags(buf->b_marktree, itr, flags);
|
||||
mt_itr_rawkey(itr).flags |= flags;
|
||||
mt_itr_rawkey(itr).decor_data = decor.data;
|
||||
marktree_revise_meta(buf->b_marktree, itr, old_mark);
|
||||
goto revised;
|
||||
}
|
||||
marktree_del_itr(buf->b_marktree, itr, false);
|
||||
if (!invalid) {
|
||||
if (!mt_invalid(old_mark)) {
|
||||
buf_decor_remove(buf, old_mark.pos.row, old_mark.pos.row, old_mark.pos.col,
|
||||
mt_decor(old_mark), true);
|
||||
}
|
||||
@ -131,6 +126,7 @@ static void extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col, bool
|
||||
int row2 = 0;
|
||||
if (invalid) {
|
||||
mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_INVALID;
|
||||
marktree_revise_meta(buf->b_marktree, itr, key);
|
||||
} else if (move && key.flags & MT_FLAG_DECOR_SIGNTEXT && buf->b_signcols.autom) {
|
||||
MTPos end = marktree_get_altpos(buf->b_marktree, key, NULL);
|
||||
row1 = MIN(end.row, MIN(key.pos.row, row));
|
||||
@ -394,6 +390,7 @@ void extmark_splice_delete(buf_T *buf, int l_row, colnr_T l_col, int u_row, coln
|
||||
} else {
|
||||
invalidated = true;
|
||||
mt_itr_rawkey(itr).flags |= MT_FLAG_INVALID;
|
||||
marktree_revise_meta(buf->b_marktree, itr, mark);
|
||||
buf_decor_remove(buf, mark.pos.row, endpos.row, mark.pos.col, mt_decor(mark), false);
|
||||
}
|
||||
}
|
||||
|
@ -3264,18 +3264,12 @@ static void vim_mktempdir(void)
|
||||
char tmp[TEMP_FILE_PATH_MAXLEN];
|
||||
char path[TEMP_FILE_PATH_MAXLEN];
|
||||
char user[40] = { 0 };
|
||||
char appname[40] = { 0 };
|
||||
|
||||
os_get_username(user, sizeof(user));
|
||||
// Usernames may contain slashes! #19240
|
||||
memchrsub(user, '/', '_', sizeof(user));
|
||||
memchrsub(user, '\\', '_', sizeof(user));
|
||||
|
||||
// Appname may be a relative path, replace slashes to make it name-like.
|
||||
xstrlcpy(appname, get_appname(), sizeof(appname));
|
||||
memchrsub(appname, '/', '%', sizeof(appname));
|
||||
memchrsub(appname, '\\', '%', sizeof(appname));
|
||||
|
||||
// Make sure the umask doesn't remove the executable bit.
|
||||
// "repl" has been reported to use "0177".
|
||||
mode_t umask_save = umask(0077);
|
||||
@ -3283,14 +3277,15 @@ static void vim_mktempdir(void)
|
||||
// Expand environment variables, leave room for "/tmp/nvim.<user>/XXXXXX/999999999".
|
||||
expand_env((char *)temp_dirs[i], tmp, TEMP_FILE_PATH_MAXLEN - 64);
|
||||
if (!os_isdir(tmp)) {
|
||||
if (strequal("$TMPDIR", temp_dirs[i])) {
|
||||
WLOG("$TMPDIR tempdir not a directory (or does not exist): %s", tmp);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// "/tmp/" exists, now try to create "/tmp/nvim.<user>/".
|
||||
add_pathsep(tmp);
|
||||
|
||||
xstrlcat(tmp, appname, sizeof(tmp));
|
||||
xstrlcat(tmp, ".", sizeof(tmp));
|
||||
xstrlcat(tmp, "nvim.", sizeof(tmp));
|
||||
xstrlcat(tmp, user, sizeof(tmp));
|
||||
os_mkdir(tmp, 0700); // Always create, to avoid a race.
|
||||
bool owned = os_file_owned(tmp);
|
||||
|
@ -1858,7 +1858,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
|
||||
if (!char_avail()) {
|
||||
// Flush screen updates before blocking.
|
||||
ui_flush();
|
||||
os_inchar(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
|
||||
input_get(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
|
||||
if (!multiqueue_empty(main_loop.events)) {
|
||||
state_handle_k_event();
|
||||
continue;
|
||||
@ -2981,7 +2981,7 @@ int inchar(uint8_t *buf, int maxlen, long wait_time)
|
||||
uint8_t dum[DUM_LEN + 1];
|
||||
|
||||
while (true) {
|
||||
len = os_inchar(dum, DUM_LEN, 0, 0, NULL);
|
||||
len = input_get(dum, DUM_LEN, 0, 0, NULL);
|
||||
if (len == 0 || (len == 1 && dum[0] == Ctrl_C)) {
|
||||
break;
|
||||
}
|
||||
@ -2997,7 +2997,7 @@ int inchar(uint8_t *buf, int maxlen, long wait_time)
|
||||
|
||||
// Fill up to a third of the buffer, because each character may be
|
||||
// tripled below.
|
||||
len = os_inchar(buf, maxlen / 3, (int)wait_time, tb_change_cnt, NULL);
|
||||
len = input_get(buf, maxlen / 3, (int)wait_time, tb_change_cnt, NULL);
|
||||
}
|
||||
|
||||
// If the typebuf was changed further down, it is like nothing was added by
|
||||
|
@ -370,12 +370,15 @@ void update_window_hl(win_T *wp, bool invalid)
|
||||
|
||||
// determine window specific background set in 'winhighlight'
|
||||
bool float_win = wp->w_floating && !wp->w_config.external;
|
||||
if (float_win && hl_def[HLF_NFLOAT] != 0) {
|
||||
if (float_win && hl_def[HLF_NFLOAT] != 0 && ns_id > 0) {
|
||||
wp->w_hl_attr_normal = hl_def[HLF_NFLOAT];
|
||||
} else if (hl_def[HLF_COUNT] > 0) {
|
||||
wp->w_hl_attr_normal = hl_def[HLF_COUNT];
|
||||
} else if (float_win) {
|
||||
wp->w_hl_attr_normal = HL_ATTR(HLF_NFLOAT) > 0
|
||||
? HL_ATTR(HLF_NFLOAT) : highlight_attr[HLF_NFLOAT];
|
||||
} else {
|
||||
wp->w_hl_attr_normal = float_win ? HL_ATTR(HLF_NFLOAT) : 0;
|
||||
wp->w_hl_attr_normal = 0;
|
||||
}
|
||||
|
||||
if (wp->w_floating) {
|
||||
|
@ -891,7 +891,17 @@ int get_breakindent_win(win_T *wp, char *line)
|
||||
if (wp->w_briopt_list > 0) {
|
||||
prev_list += wp->w_briopt_list;
|
||||
} else {
|
||||
prev_indent = (int)(*regmatch.endp - *regmatch.startp);
|
||||
char *ptr = *regmatch.startp;
|
||||
char *end_ptr = *regmatch.endp;
|
||||
int indent = 0;
|
||||
// Compute the width of the matched text.
|
||||
// Use win_chartabsize() so that TAB size is correct,
|
||||
// while wrapping is ignored.
|
||||
while (ptr < end_ptr) {
|
||||
indent += win_chartabsize(wp, ptr, indent);
|
||||
MB_PTR_ADV(ptr);
|
||||
}
|
||||
prev_indent = indent;
|
||||
}
|
||||
}
|
||||
vim_regfree(regmatch.regprog);
|
||||
@ -1407,7 +1417,7 @@ void fixthisline(IndentGetter get_the_indent)
|
||||
return;
|
||||
}
|
||||
|
||||
change_indent(INDENT_SET, amount, false, 0, true);
|
||||
change_indent(INDENT_SET, amount, false, true);
|
||||
if (linewhite(curwin->w_cursor.lnum)) {
|
||||
did_ai = true; // delete the indent if the line stays empty
|
||||
}
|
||||
|
@ -37,7 +37,7 @@
|
||||
/// @param[in] str Prompt: question to ask user. Is always followed by
|
||||
/// " (y/n)?".
|
||||
/// @param[in] direct Determines what function to use to get user input. If
|
||||
/// true then os_inchar() will be used, otherwise vgetc().
|
||||
/// true then input_get() will be used, otherwise vgetc().
|
||||
/// I.e. when direct is true then characters are obtained
|
||||
/// directly from the user without buffers involved.
|
||||
///
|
||||
@ -111,7 +111,7 @@ int get_keystroke(MultiQueue *events)
|
||||
|
||||
// First time: blocking wait. Second time: wait up to 100ms for a
|
||||
// terminal code to complete.
|
||||
n = os_inchar(buf + len, maxlen, len == 0 ? -1 : 100, 0, events);
|
||||
n = input_get(buf + len, maxlen, len == 0 ? -1 : 100, 0, events);
|
||||
if (n > 0) {
|
||||
// Replace zero and K_SPECIAL by a special key code.
|
||||
n = fix_input_buffer(buf + len, n);
|
||||
|
@ -266,7 +266,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (argc > 1 && STRICMP(argv[1], "-ll") == 0) {
|
||||
if (argc == 2) {
|
||||
print_mainerr(err_arg_missing, argv[1]);
|
||||
print_mainerr(err_arg_missing, argv[1], NULL);
|
||||
exit(1);
|
||||
}
|
||||
nlua_run_script(argv, argc, 3);
|
||||
@ -332,12 +332,6 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
bool use_builtin_ui = (has_term && !headless_mode && !embedded_mode && !silent_mode);
|
||||
|
||||
// don't bind the server yet, if we are using builtin ui.
|
||||
// This will be done when nvim server has been forked from the ui process
|
||||
if (!use_builtin_ui) {
|
||||
server_init(params.listen_addr);
|
||||
}
|
||||
|
||||
if (params.remote) {
|
||||
remote_request(¶ms, params.remote, params.server_addr, argc, argv,
|
||||
use_builtin_ui);
|
||||
@ -355,11 +349,17 @@ int main(int argc, char **argv)
|
||||
ui_client_channel_id = rv;
|
||||
}
|
||||
|
||||
// NORETURN: Start builtin UI client.
|
||||
if (ui_client_channel_id) {
|
||||
time_finish();
|
||||
ui_client_run(remote_ui); // NORETURN
|
||||
}
|
||||
assert(!ui_client_channel_id && !use_builtin_ui);
|
||||
// Nvim server...
|
||||
|
||||
if (!server_init(params.listen_addr)) {
|
||||
mainerr(IObuff, NULL, NULL);
|
||||
}
|
||||
|
||||
TIME_MSG("expanding arguments");
|
||||
|
||||
@ -1051,7 +1051,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
// "+" or "+{number}" or "+/{pat}" or "+{command}" argument.
|
||||
if (argv[0][0] == '+' && !had_minmin) {
|
||||
if (parmp->n_commands >= MAX_ARG_CMDS) {
|
||||
mainerr(err_extra_cmd, NULL);
|
||||
mainerr(err_extra_cmd, NULL, NULL);
|
||||
}
|
||||
argv_idx = -1; // skip to next argument
|
||||
if (argv[0][1] == NUL) {
|
||||
@ -1072,7 +1072,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
parmp->no_swap_file = true;
|
||||
} else {
|
||||
if (parmp->edit_type > EDIT_STDIN) {
|
||||
mainerr(err_too_many_args, argv[0]);
|
||||
mainerr(err_too_many_args, argv[0], NULL);
|
||||
}
|
||||
parmp->had_stdin_file = true;
|
||||
parmp->edit_type = EDIT_STDIN;
|
||||
@ -1135,7 +1135,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
nlua_disable_preload = true;
|
||||
} else {
|
||||
if (argv[0][argv_idx]) {
|
||||
mainerr(err_opt_unknown, argv[0]);
|
||||
mainerr(err_opt_unknown, argv[0], NULL);
|
||||
}
|
||||
had_minmin = true;
|
||||
}
|
||||
@ -1209,7 +1209,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
break;
|
||||
case 'q': // "-q" QuickFix mode
|
||||
if (parmp->edit_type != EDIT_NONE) {
|
||||
mainerr(err_too_many_args, argv[0]);
|
||||
mainerr(err_too_many_args, argv[0], NULL);
|
||||
}
|
||||
parmp->edit_type = EDIT_QF;
|
||||
if (argv[0][argv_idx]) { // "-q{errorfile}"
|
||||
@ -1238,7 +1238,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
break;
|
||||
case 't': // "-t {tag}" or "-t{tag}" jump to tag
|
||||
if (parmp->edit_type != EDIT_NONE) {
|
||||
mainerr(err_too_many_args, argv[0]);
|
||||
mainerr(err_too_many_args, argv[0], NULL);
|
||||
}
|
||||
parmp->edit_type = EDIT_TAG;
|
||||
if (argv[0][argv_idx]) { // "-t{tag}"
|
||||
@ -1272,7 +1272,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
case 'c': // "-c{command}" or "-c {command}" exec command
|
||||
if (argv[0][argv_idx] != NUL) {
|
||||
if (parmp->n_commands >= MAX_ARG_CMDS) {
|
||||
mainerr(err_extra_cmd, NULL);
|
||||
mainerr(err_extra_cmd, NULL, NULL);
|
||||
}
|
||||
parmp->commands[parmp->n_commands++] = argv[0] + argv_idx;
|
||||
argv_idx = -1;
|
||||
@ -1289,19 +1289,19 @@ static void command_line_scan(mparm_T *parmp)
|
||||
break;
|
||||
|
||||
default:
|
||||
mainerr(err_opt_unknown, argv[0]);
|
||||
mainerr(err_opt_unknown, argv[0], NULL);
|
||||
}
|
||||
|
||||
// Handle option arguments with argument.
|
||||
if (want_argument) {
|
||||
// Check for garbage immediately after the option letter.
|
||||
if (argv[0][argv_idx] != NUL) {
|
||||
mainerr(err_opt_garbage, argv[0]);
|
||||
mainerr(err_opt_garbage, argv[0], NULL);
|
||||
}
|
||||
|
||||
argc--;
|
||||
if (argc < 1 && c != 'S') { // -S has an optional argument
|
||||
mainerr(err_arg_missing, argv[0]);
|
||||
mainerr(err_arg_missing, argv[0], NULL);
|
||||
}
|
||||
argv++;
|
||||
argv_idx = -1;
|
||||
@ -1310,7 +1310,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
case 'c': // "-c {command}" execute command
|
||||
case 'S': // "-S {file}" execute Vim script
|
||||
if (parmp->n_commands >= MAX_ARG_CMDS) {
|
||||
mainerr(err_extra_cmd, NULL);
|
||||
mainerr(err_extra_cmd, NULL, NULL);
|
||||
}
|
||||
if (c == 'S') {
|
||||
char *a;
|
||||
@ -1341,7 +1341,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
if (strequal(argv[-1], "--cmd")) {
|
||||
// "--cmd {command}" execute command
|
||||
if (parmp->n_pre_commands >= MAX_ARG_CMDS) {
|
||||
mainerr(err_extra_cmd, NULL);
|
||||
mainerr(err_extra_cmd, NULL, NULL);
|
||||
}
|
||||
parmp->pre_commands[parmp->n_pre_commands++] = argv[0];
|
||||
} else if (strequal(argv[-1], "--listen")) {
|
||||
@ -1423,7 +1423,7 @@ scripterror:
|
||||
|
||||
// Check for only one type of editing.
|
||||
if (parmp->edit_type > EDIT_STDIN) {
|
||||
mainerr(err_too_many_args, argv[0]);
|
||||
mainerr(err_too_many_args, argv[0], NULL);
|
||||
}
|
||||
parmp->edit_type = EDIT_FILE;
|
||||
|
||||
@ -1434,9 +1434,9 @@ scripterror:
|
||||
// On Windows expand "~\" or "~/" prefix in file names to profile directory.
|
||||
#ifdef MSWIN
|
||||
if (*p == '~' && (p[1] == '\\' || p[1] == '/')) {
|
||||
size_t size = strlen(os_get_homedir()) + strlen(p);
|
||||
size_t size = strlen(os_homedir()) + strlen(p);
|
||||
char *tilde_expanded = xmalloc(size);
|
||||
snprintf(tilde_expanded, size, "%s%s", os_get_homedir(), p + 1);
|
||||
snprintf(tilde_expanded, size, "%s%s", os_homedir(), p + 1);
|
||||
xfree(p);
|
||||
p = tilde_expanded;
|
||||
}
|
||||
@ -1470,7 +1470,7 @@ scripterror:
|
||||
}
|
||||
|
||||
if (embedded_mode && (silent_mode || parmp->luaf)) {
|
||||
mainerr(_("--embed conflicts with -es/-Es/-l"), NULL);
|
||||
mainerr(_("--embed conflicts with -es/-Es/-l"), NULL, NULL);
|
||||
}
|
||||
|
||||
// If there is a "+123" or "-c" command, set v:swapcommand to the first one.
|
||||
@ -2133,28 +2133,30 @@ static int execute_env(char *env)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/// Prints the following then exits:
|
||||
/// - An error message `errstr`
|
||||
/// - A string `str` if not null
|
||||
/// Prints a message of the form "{msg1}: {msg2}: {msg3}", then exits with code 1.
|
||||
///
|
||||
/// @param errstr string containing an error message
|
||||
/// @param str string to append to the primary error message, or NULL
|
||||
static void mainerr(const char *errstr, const char *str)
|
||||
/// @param msg1 error message
|
||||
/// @param msg2 extra message, or NULL
|
||||
/// @param msg3 extra message, or NULL
|
||||
static void mainerr(const char *msg1, const char *msg2, const char *msg3)
|
||||
FUNC_ATTR_NORETURN
|
||||
{
|
||||
print_mainerr(errstr, str);
|
||||
print_mainerr(msg1, msg2, msg3);
|
||||
os_exit(1);
|
||||
}
|
||||
|
||||
static void print_mainerr(const char *errstr, const char *str)
|
||||
static void print_mainerr(const char *msg1, const char *msg2, const char *msg3)
|
||||
{
|
||||
char *prgname = path_tail(argv0);
|
||||
|
||||
signal_stop(); // kill us with CTRL-C here, if you like
|
||||
|
||||
fprintf(stderr, "%s: %s", prgname, _(errstr));
|
||||
if (str != NULL) {
|
||||
fprintf(stderr, ": \"%s\"", str);
|
||||
fprintf(stderr, "%s: %s", prgname, _(msg1));
|
||||
if (msg2 != NULL) {
|
||||
fprintf(stderr, ": \"%s\"", msg2);
|
||||
}
|
||||
if (msg3 != NULL) {
|
||||
fprintf(stderr, ": \"%s\"", msg3);
|
||||
}
|
||||
fprintf(stderr, _("\nMore info with \""));
|
||||
fprintf(stderr, "%s -h\"\n", prgname);
|
||||
|
@ -446,7 +446,7 @@ static MTNode *marktree_alloc_node(MarkTree *b, bool internal)
|
||||
// really meta_inc[kMTMetaCount]
|
||||
static void meta_describe_key_inc(uint32_t *meta_inc, MTKey *k)
|
||||
{
|
||||
if (!mt_end(*k)) {
|
||||
if (!mt_end(*k) && !mt_invalid(*k)) {
|
||||
meta_inc[kMTMetaInline] += (k->flags & MT_FLAG_DECOR_VIRT_TEXT_INLINE) ? 1 : 0;
|
||||
meta_inc[kMTMetaLines] += (k->flags & MT_FLAG_DECOR_VIRT_LINES) ? 1 : 0;
|
||||
meta_inc[kMTMetaSignHL] += (k->flags & MT_FLAG_DECOR_SIGNHL) ? 1 : 0;
|
||||
@ -774,14 +774,10 @@ uint64_t marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
|
||||
return other;
|
||||
}
|
||||
|
||||
void marktree_revise_flags(MarkTree *b, MarkTreeIter *itr, uint16_t new_flags)
|
||||
void marktree_revise_meta(MarkTree *b, MarkTreeIter *itr, MTKey old_key)
|
||||
{
|
||||
uint32_t meta_old[4];
|
||||
meta_describe_key(meta_old, rawkey(itr));
|
||||
rawkey(itr).flags &= (uint16_t) ~MT_FLAG_EXTERNAL_MASK;
|
||||
rawkey(itr).flags |= new_flags;
|
||||
|
||||
uint32_t meta_new[4];
|
||||
uint32_t meta_old[4], meta_new[4];
|
||||
meta_describe_key(meta_old, old_key);
|
||||
meta_describe_key(meta_new, rawkey(itr));
|
||||
|
||||
if (!memcmp(meta_old, meta_new, sizeof(meta_old))) {
|
||||
|
@ -523,12 +523,14 @@ int utf_ptr2cells(const char *p_in)
|
||||
}
|
||||
|
||||
/// Convert a UTF-8 byte sequence to a character number.
|
||||
/// Doesn't handle ascii! only multibyte and illegal sequences.
|
||||
/// Doesn't handle ascii! only multibyte and illegal sequences. ASCII (including NUL)
|
||||
/// are treated like illegal sequences.
|
||||
///
|
||||
/// @param[in] p String to convert.
|
||||
/// @param[in] len Length of the character in bytes, 0 or 1 if illegal.
|
||||
///
|
||||
/// @return Unicode codepoint. A negative value when the sequence is illegal.
|
||||
/// @return Unicode codepoint. A negative value when the sequence is illegal (or
|
||||
/// ASCII, including NUL).
|
||||
int32_t utf_ptr2CharInfo_impl(uint8_t const *p, uintptr_t const len)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
@ -1339,13 +1341,22 @@ int utf_class_tab(const int c, const uint64_t *const chartab)
|
||||
|
||||
bool utf_ambiguous_width(const char *p)
|
||||
{
|
||||
int c = utf_ptr2char(p);
|
||||
if (c < 0x80) {
|
||||
// be quick if there is nothing to print or ASCII-only
|
||||
if (p[0] == NUL || p[1] == NUL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const utf8proc_property_t *prop = utf8proc_get_property(c);
|
||||
return prop->ambiguous_width || prop_is_emojilike(prop);
|
||||
CharInfo info = utf_ptr2CharInfo(p);
|
||||
if (info.value >= 0x80) {
|
||||
const utf8proc_property_t *prop = utf8proc_get_property(info.value);
|
||||
if (prop->ambiguous_width || prop_is_emojilike(prop)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// check if second sequence is 0xFE0F VS-16 which can turn things into emoji,
|
||||
// safe with NUL (no second sequence)
|
||||
return memcmp(p + info.len, "\xef\xb8\x8f", 3) == 0;
|
||||
}
|
||||
|
||||
// Return the folded-case equivalent of "a", which is a UCS-4 character. Uses
|
||||
@ -1771,15 +1782,15 @@ int utf_head_off(const char *base_in, const char *p_in)
|
||||
start--;
|
||||
}
|
||||
|
||||
uint8_t cur_len = utf8len_tab[*start];
|
||||
int32_t cur_code = utf_ptr2CharInfo_impl(start, (uintptr_t)cur_len);
|
||||
if (cur_code < 0) {
|
||||
const uint8_t last_len = utf8len_tab[*start];
|
||||
int32_t cur_code = utf_ptr2CharInfo_impl(start, (uintptr_t)last_len);
|
||||
if (cur_code < 0 || p - start >= last_len) {
|
||||
return 0; // p must be part of an illegal sequence
|
||||
}
|
||||
const uint8_t * const safe_end = start + cur_len;
|
||||
const uint8_t * const safe_end = start + last_len;
|
||||
|
||||
int cur_bc = utf8proc_get_property(cur_code)->boundclass;
|
||||
if (always_break(cur_bc)) {
|
||||
if (always_break(cur_bc) || start == base) {
|
||||
return (int)(p - start);
|
||||
}
|
||||
|
||||
@ -1787,18 +1798,23 @@ int utf_head_off(const char *base_in, const char *p_in)
|
||||
const uint8_t *cur_pos = start;
|
||||
const uint8_t *const p_start = start;
|
||||
|
||||
if (start == base) {
|
||||
return (int)(p - start);
|
||||
}
|
||||
while (true) {
|
||||
if (start[-1] == NUL) {
|
||||
break;
|
||||
}
|
||||
|
||||
start--;
|
||||
if (*start < 0x80) { // stop on ascii, we are done
|
||||
break;
|
||||
}
|
||||
|
||||
start--;
|
||||
while (*start >= 0x80) { // stop on ascii, we are done
|
||||
while (start > base && (*start & 0xc0) == 0x80 && (cur_pos - start) < 6) {
|
||||
start--;
|
||||
}
|
||||
|
||||
int32_t prev_code = utf_ptr2CharInfo_impl(start, (uintptr_t)utf8len_tab[*start]);
|
||||
if (prev_code < 0) {
|
||||
int prev_len = utf8len_tab[*start];
|
||||
int32_t prev_code = utf_ptr2CharInfo_impl(start, (uintptr_t)prev_len);
|
||||
if (prev_code < 0 || prev_len < cur_pos - start) {
|
||||
start = cur_pos; // start at valid sequence after invalid bytes
|
||||
break;
|
||||
}
|
||||
@ -1813,12 +1829,10 @@ int utf_head_off(const char *base_in, const char *p_in)
|
||||
cur_pos = start;
|
||||
cur_bc = prev_bc;
|
||||
cur_code = prev_code;
|
||||
|
||||
start--;
|
||||
}
|
||||
|
||||
// hot path: we are already on the first codepoint of a sequence
|
||||
if (start == p_start) {
|
||||
if (start == p_start && last_len > p - start) {
|
||||
return (int)(p - start);
|
||||
}
|
||||
|
||||
@ -2911,17 +2925,17 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
emsg(_(e_listreq));
|
||||
return;
|
||||
}
|
||||
|
||||
const list_T *const l = argvars[0].vval.v_list;
|
||||
if (tv_list_len(l) == 0) {
|
||||
cw_interval_T *table = NULL;
|
||||
const size_t table_size = (size_t)tv_list_len(l);
|
||||
if (table_size == 0) {
|
||||
// Clearing the table.
|
||||
xfree(cw_table);
|
||||
cw_table = NULL;
|
||||
cw_table_size = 0;
|
||||
return;
|
||||
goto update;
|
||||
}
|
||||
|
||||
// Note: use list_T instead of listitem_T so that TV_LIST_ITEM_NEXT can be used properly below.
|
||||
const list_T **ptrs = xmalloc(sizeof(const list_T *) * (size_t)tv_list_len(l));
|
||||
const list_T **ptrs = xmalloc(sizeof(const list_T *) * table_size);
|
||||
|
||||
// Check that all entries are a list with three numbers, the range is
|
||||
// valid and the cell width is valid.
|
||||
@ -2973,12 +2987,12 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
});
|
||||
|
||||
// Sort the list on the first number.
|
||||
qsort((void *)ptrs, (size_t)tv_list_len(l), sizeof(const list_T *), tv_nr_compare);
|
||||
qsort((void *)ptrs, table_size, sizeof(const list_T *), tv_nr_compare);
|
||||
|
||||
cw_interval_T *table = xmalloc(sizeof(cw_interval_T) * (size_t)tv_list_len(l));
|
||||
table = xmalloc(sizeof(cw_interval_T) * table_size);
|
||||
|
||||
// Store the items in the new table.
|
||||
for (item = 0; item < tv_list_len(l); item++) {
|
||||
for (item = 0; (size_t)item < table_size; item++) {
|
||||
const list_T *const li_l = ptrs[item];
|
||||
const listitem_T *lili = tv_list_first(li_l);
|
||||
const varnumber_T n1 = TV_LIST_ITEM_TV(lili)->vval.v_number;
|
||||
@ -2997,10 +3011,12 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
|
||||
xfree((void *)ptrs);
|
||||
|
||||
update:
|
||||
;
|
||||
cw_interval_T *const cw_table_save = cw_table;
|
||||
const size_t cw_table_size_save = cw_table_size;
|
||||
cw_table = table;
|
||||
cw_table_size = (size_t)tv_list_len(l);
|
||||
cw_table_size = table_size;
|
||||
|
||||
// Check that the new value does not conflict with 'listchars' or
|
||||
// 'fillchars'.
|
||||
|
@ -1250,7 +1250,7 @@ theend:
|
||||
/// with the 'directory' option.
|
||||
///
|
||||
/// Used to:
|
||||
/// - list the swapfiles for "vim -r"
|
||||
/// - list the swapfiles for "nvim -r"
|
||||
/// - count the number of swapfiles when recovering
|
||||
/// - list the swapfiles when recovering
|
||||
/// - list the swapfiles for swapfilelist()
|
||||
@ -3280,7 +3280,7 @@ static void attention_message(buf_T *buf, char *fname)
|
||||
" instances of the same\n file when making changes."
|
||||
" Quit, or continue with caution.\n"));
|
||||
msg_puts(_("(2) An edit session for this file crashed.\n"));
|
||||
msg_puts(_(" If this is the case, use \":recover\" or \"vim -r "));
|
||||
msg_puts(_(" If this is the case, use \":recover\" or \"nvim -r "));
|
||||
msg_outtrans(buf->b_fname, 0);
|
||||
msg_puts(_("\"\n to recover the changes (see \":help recovery\").\n"));
|
||||
msg_puts(_(" If you did this already, delete the swap file \""));
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
/// HACK: os/input.c drains this queue immediately before blocking for input.
|
||||
/// Events on this queue are async-safe, but they need the resolved state
|
||||
/// of os_inchar(), so they are processed "just-in-time".
|
||||
/// of input_get(), so they are processed "just-in-time".
|
||||
EXTERN MultiQueue *ch_before_blocking_events INIT( = NULL);
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
|
@ -11,12 +11,14 @@
|
||||
#include "nvim/event/socket.h"
|
||||
#include "nvim/garray.h"
|
||||
#include "nvim/garray_defs.h"
|
||||
#include "nvim/globals.h"
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/main.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/msgpack_rpc/server.h"
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/os/stdpaths_defs.h"
|
||||
#include "nvim/types_defs.h"
|
||||
|
||||
#define MAX_CONNECTIONS 32
|
||||
#define ENV_LISTEN "NVIM_LISTEN_ADDRESS" // deprecated
|
||||
@ -27,37 +29,61 @@ static garray_T watchers = GA_EMPTY_INIT_VALUE;
|
||||
# include "msgpack_rpc/server.c.generated.h"
|
||||
#endif
|
||||
|
||||
/// Initializes the module
|
||||
/// Initializes resources, handles `--listen`, starts the primary server at v:servername.
|
||||
///
|
||||
/// @returns true on success, false on fatal error (message stored in IObuff)
|
||||
bool server_init(const char *listen_addr)
|
||||
{
|
||||
bool ok = true;
|
||||
bool must_free = false;
|
||||
TriState user_arg = kTrue; // User-provided --listen arg.
|
||||
ga_init(&watchers, sizeof(SocketWatcher *), 1);
|
||||
|
||||
// $NVIM_LISTEN_ADDRESS (deprecated)
|
||||
if (!listen_addr && os_env_exists(ENV_LISTEN)) {
|
||||
if ((!listen_addr || listen_addr[0] == '\0') && os_env_exists(ENV_LISTEN)) {
|
||||
user_arg = kFalse; // User-provided env var.
|
||||
listen_addr = os_getenv(ENV_LISTEN);
|
||||
}
|
||||
|
||||
int rv = listen_addr ? server_start(listen_addr) : 1;
|
||||
if (0 != rv) {
|
||||
if (!listen_addr || listen_addr[0] == '\0') {
|
||||
user_arg = kNone; // Autogenerated server address.
|
||||
listen_addr = server_address_new(NULL);
|
||||
if (!listen_addr) {
|
||||
return false;
|
||||
}
|
||||
rv = server_start(listen_addr);
|
||||
xfree((char *)listen_addr);
|
||||
must_free = true;
|
||||
}
|
||||
|
||||
if (os_env_exists(ENV_LISTEN)) {
|
||||
// Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter.
|
||||
os_unsetenv(ENV_LISTEN);
|
||||
}
|
||||
int rv = server_start(listen_addr);
|
||||
|
||||
// TODO(justinmk): this is for logging_spec. Can remove this after nvim_log #7062 is merged.
|
||||
if (os_env_exists("__NVIM_TEST_LOG")) {
|
||||
ELOG("test log message");
|
||||
}
|
||||
|
||||
return rv == 0;
|
||||
if (must_free) {
|
||||
xfree((char *)listen_addr);
|
||||
}
|
||||
|
||||
if (rv == 0 || user_arg == kNone) {
|
||||
// The autogenerated servername can fail if the user has a broken $XDG_RUNTIME_DIR. #30282
|
||||
// But that is not fatal (startup will continue, logged in $NVIM_LOGFILE, empty v:servername).
|
||||
goto end;
|
||||
}
|
||||
|
||||
(void)snprintf(IObuff, IOSIZE,
|
||||
user_arg ==
|
||||
kTrue ? "Failed to --listen: %s: \"%s\""
|
||||
: "Failed $NVIM_LISTEN_ADDRESS: %s: \"%s\"",
|
||||
rv < 0 ? os_strerror(rv) : (rv == 1 ? "empty address" : "?"),
|
||||
listen_addr);
|
||||
ok = false;
|
||||
|
||||
end:
|
||||
if (os_env_exists(ENV_LISTEN)) {
|
||||
// Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter. It is "input only", it must not be
|
||||
// leaked to child jobs or :terminal.
|
||||
os_unsetenv(ENV_LISTEN);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/// Teardown a single server
|
||||
@ -88,17 +114,19 @@ void server_teardown(void)
|
||||
/// - Windows: "\\.\pipe\<name>.<pid>.<counter>"
|
||||
/// - Other: "/tmp/nvim.user/xxx/<name>.<pid>.<counter>"
|
||||
char *server_address_new(const char *name)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
static uint32_t count = 0;
|
||||
char fmt[ADDRESS_MAX_SIZE];
|
||||
const char *appname = get_appname();
|
||||
#ifdef MSWIN
|
||||
(void)get_appname(true);
|
||||
int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32,
|
||||
name ? name : appname, os_get_pid(), count++);
|
||||
name ? name : NameBuff, os_get_pid(), count++);
|
||||
#else
|
||||
char *dir = stdpaths_get_xdg_var(kXDGRuntimeDir);
|
||||
(void)get_appname(true);
|
||||
int r = snprintf(fmt, sizeof(fmt), "%s/%s.%" PRIu64 ".%" PRIu32,
|
||||
dir, name ? name : appname, os_get_pid(), count++);
|
||||
dir, name ? name : NameBuff, os_get_pid(), count++);
|
||||
xfree(dir);
|
||||
#endif
|
||||
if ((size_t)r >= sizeof(fmt)) {
|
||||
|
@ -6597,11 +6597,11 @@ static void nv_open(cmdarg_T *cap)
|
||||
static void nv_event(cmdarg_T *cap)
|
||||
{
|
||||
// Garbage collection should have been executed before blocking for events in
|
||||
// the `os_inchar` in `state_enter`, but we also disable it here in case the
|
||||
// `os_inchar` branch was not executed (!multiqueue_empty(loop.events), which
|
||||
// the `input_get` in `state_enter`, but we also disable it here in case the
|
||||
// `input_get` branch was not executed (!multiqueue_empty(loop.events), which
|
||||
// could have `may_garbage_collect` set to true in `normal_check`).
|
||||
//
|
||||
// That is because here we may run code that calls `os_inchar`
|
||||
// That is because here we may run code that calls `input_get`
|
||||
// later(`f_confirm` or `get_keystroke` for example), but in these cases it is
|
||||
// not safe to perform garbage collection because there could be unreferenced
|
||||
// lists or dicts being used.
|
||||
|
@ -306,7 +306,7 @@ void shift_line(bool left, bool round, int amount, int call_changed_bytes)
|
||||
|
||||
// Set new indent
|
||||
if (State & VREPLACE_FLAG) {
|
||||
change_indent(INDENT_SET, count, false, NUL, call_changed_bytes);
|
||||
change_indent(INDENT_SET, count, false, call_changed_bytes);
|
||||
} else {
|
||||
set_indent(count, call_changed_bytes ? SIN_CHANGED : 0);
|
||||
}
|
||||
|
@ -761,9 +761,9 @@ return {
|
||||
list:{n} Adds an additional indent for lines that match a
|
||||
numbered or bulleted list (using the
|
||||
'formatlistpat' setting).
|
||||
list:-1 Uses the length of a match with 'formatlistpat'
|
||||
for indentation.
|
||||
(default: 0)
|
||||
list:-1 Uses the width of a match with 'formatlistpat' for
|
||||
indentation.
|
||||
column:{n} Indent at column {n}. Will overrule the other
|
||||
sub-options. Note: an additional indent may be
|
||||
added for the 'showbreak' setting.
|
||||
|
@ -395,7 +395,21 @@ void os_get_hostname(char *hostname, size_t size)
|
||||
#endif
|
||||
}
|
||||
|
||||
/// To get the "real" home directory:
|
||||
/// The "real" home directory as determined by `init_homedir`.
|
||||
static char *homedir = NULL;
|
||||
static char *os_uv_homedir(void);
|
||||
|
||||
/// Gets the "real", resolved user home directory as determined by `init_homedir`.
|
||||
const char *os_homedir(void)
|
||||
{
|
||||
if (!homedir) {
|
||||
emsg("os_homedir failed: homedir not initialized");
|
||||
return NULL;
|
||||
}
|
||||
return homedir;
|
||||
}
|
||||
|
||||
/// Sets `homedir` to the "real", resolved user home directory, as follows:
|
||||
/// 1. get value of $HOME
|
||||
/// 2. if $HOME is not set, try the following
|
||||
/// For Windows:
|
||||
@ -409,20 +423,6 @@ void os_get_hostname(char *hostname, size_t size)
|
||||
/// This also works with mounts and links.
|
||||
/// Don't do this for Windows, it will change the "current dir" for a drive.
|
||||
/// 3. fall back to current working directory as a last resort
|
||||
static char *homedir = NULL;
|
||||
static char *os_uv_homedir(void);
|
||||
|
||||
/// Public accessor for the cached "real", resolved user home directory. See
|
||||
/// comment on `homedir`.
|
||||
const char *os_get_homedir(void)
|
||||
{
|
||||
if (!homedir) {
|
||||
emsg("os_get_homedir failed: homedir not initialized");
|
||||
return NULL;
|
||||
}
|
||||
return homedir;
|
||||
}
|
||||
|
||||
void init_homedir(void)
|
||||
{
|
||||
// In case we are called a second time.
|
||||
|
@ -33,12 +33,6 @@
|
||||
#define READ_BUFFER_SIZE 0xfff
|
||||
#define INPUT_BUFFER_SIZE ((READ_BUFFER_SIZE * 4) + MAX_KEY_CODE_LEN)
|
||||
|
||||
typedef enum {
|
||||
kInputNone,
|
||||
kInputAvail,
|
||||
kInputEof,
|
||||
} InbufPollResult;
|
||||
|
||||
static RStream read_stream = { .s.closed = true }; // Input before UI starts.
|
||||
static char input_buffer[INPUT_BUFFER_SIZE];
|
||||
static char *input_read_pos = input_buffer;
|
||||
@ -84,57 +78,76 @@ static void cursorhold_event(void **argv)
|
||||
static void create_cursorhold_event(bool events_enabled)
|
||||
{
|
||||
// If events are enabled and the queue has any items, this function should not
|
||||
// have been called (inbuf_poll would return kInputAvail).
|
||||
// have been called (`inbuf_poll` would return `kTrue`).
|
||||
// TODO(tarruda): Cursorhold should be implemented as a timer set during the
|
||||
// `state_check` callback for the states where it can be triggered.
|
||||
assert(!events_enabled || multiqueue_empty(main_loop.events));
|
||||
multiqueue_put(main_loop.events, cursorhold_event, NULL);
|
||||
}
|
||||
|
||||
static void restart_cursorhold_wait(int tb_change_cnt)
|
||||
static void reset_cursorhold_wait(int tb_change_cnt)
|
||||
{
|
||||
cursorhold_time = 0;
|
||||
cursorhold_tb_change_cnt = tb_change_cnt;
|
||||
}
|
||||
|
||||
/// Low level input function
|
||||
/// Reads OS input into `buf`, and consumes pending events while waiting (if `ms != 0`).
|
||||
///
|
||||
/// Wait until either the input buffer is non-empty or, if `events` is not NULL
|
||||
/// until `events` is non-empty.
|
||||
int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *events)
|
||||
/// - Consumes available input received from the OS.
|
||||
/// - Consumes pending events.
|
||||
/// - Manages CursorHold events.
|
||||
/// - Handles EOF conditions.
|
||||
///
|
||||
/// Originally based on the Vim `mch_inchar` function.
|
||||
///
|
||||
/// @param buf Buffer to store read 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.
|
||||
/// @param events (optional) Events to process.
|
||||
/// @return Bytes read into buf, or 0 if no input was read
|
||||
int input_get(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *events)
|
||||
{
|
||||
// This check is needed so that feeding typeahead from RPC can prevent CursorHold.
|
||||
if (tb_change_cnt != cursorhold_tb_change_cnt) {
|
||||
restart_cursorhold_wait(tb_change_cnt);
|
||||
reset_cursorhold_wait(tb_change_cnt);
|
||||
}
|
||||
|
||||
if (maxlen && input_available()) {
|
||||
restart_cursorhold_wait(tb_change_cnt);
|
||||
size_t to_read = MIN((size_t)maxlen, input_available());
|
||||
memcpy(buf, input_read_pos, to_read);
|
||||
input_read_pos += to_read;
|
||||
return (int)to_read;
|
||||
}
|
||||
#define TRY_READ() \
|
||||
do { \
|
||||
if (maxlen && input_available()) { \
|
||||
reset_cursorhold_wait(tb_change_cnt); \
|
||||
assert(maxlen >= 0); \
|
||||
size_t to_read = MIN((size_t)maxlen, input_available()); \
|
||||
memcpy(buf, input_read_pos, to_read); \
|
||||
input_read_pos += to_read; \
|
||||
/* This is safe because INPUT_BUFFER_SIZE fits in an int. */ \
|
||||
assert(to_read <= INT_MAX); \
|
||||
return (int)to_read; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
TRY_READ();
|
||||
|
||||
// No risk of a UI flood, so disable CTRL-C "interrupt" behavior if it's mapped.
|
||||
if ((mapped_ctrl_c | curbuf->b_mapped_ctrl_c) & get_real_state()) {
|
||||
ctrl_c_interrupts = false;
|
||||
}
|
||||
|
||||
InbufPollResult result;
|
||||
TriState result; ///< inbuf_poll result.
|
||||
if (ms >= 0) {
|
||||
if ((result = inbuf_poll(ms, events)) == kInputNone) {
|
||||
if ((result = inbuf_poll(ms, events)) == kFalse) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
uint64_t wait_start = os_hrtime();
|
||||
cursorhold_time = MIN(cursorhold_time, (int)p_ut);
|
||||
if ((result = inbuf_poll((int)p_ut - cursorhold_time, events)) == kInputNone) {
|
||||
if ((result = inbuf_poll((int)p_ut - cursorhold_time, events)) == kFalse) {
|
||||
if (read_stream.s.closed && silent_mode) {
|
||||
// Drained eventloop & initial input; exit silent/batch-mode (-es/-Es).
|
||||
read_error_exit();
|
||||
}
|
||||
restart_cursorhold_wait(tb_change_cnt);
|
||||
reset_cursorhold_wait(tb_change_cnt);
|
||||
if (trigger_cursorhold() && !typebuf_changed(tb_change_cnt)) {
|
||||
create_cursorhold_event(events == main_loop.events);
|
||||
} else {
|
||||
@ -153,32 +166,26 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *e
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (maxlen && input_available()) {
|
||||
restart_cursorhold_wait(tb_change_cnt);
|
||||
// Safe to convert `to_read` to int, it will never overflow since
|
||||
// INPUT_BUFFER_SIZE fits in an int
|
||||
size_t to_read = MIN((size_t)maxlen, input_available());
|
||||
memcpy(buf, input_read_pos, to_read);
|
||||
input_read_pos += to_read;
|
||||
return (int)to_read;
|
||||
}
|
||||
TRY_READ();
|
||||
|
||||
// If there are events, return the keys directly
|
||||
if (maxlen && pending_events(events)) {
|
||||
return push_event_key(buf, maxlen);
|
||||
}
|
||||
|
||||
if (result == kInputEof) {
|
||||
if (result == kNone) {
|
||||
read_error_exit();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
#undef TRY_READ
|
||||
}
|
||||
|
||||
// Check if a character is available for reading
|
||||
bool os_char_avail(void)
|
||||
{
|
||||
return inbuf_poll(0, NULL) == kInputAvail;
|
||||
return inbuf_poll(0, NULL) == kTrue;
|
||||
}
|
||||
|
||||
/// Poll for fast events. `got_int` will be set to `true` if CTRL-C was typed.
|
||||
@ -463,15 +470,22 @@ bool input_blocking(void)
|
||||
return blocking;
|
||||
}
|
||||
|
||||
// This is a replacement for the old `WaitForChar` function in os_unix.c
|
||||
static InbufPollResult inbuf_poll(int ms, MultiQueue *events)
|
||||
/// Checks for (but does not read) available input, and consumes `main_loop.events` while waiting.
|
||||
///
|
||||
/// @param ms Timeout in milliseconds. -1 for indefinite wait, 0 for no wait.
|
||||
/// @param events (optional) Queue to check for pending events.
|
||||
/// @return TriState:
|
||||
/// - kTrue: Input/events available
|
||||
/// - kFalse: No input/events
|
||||
/// - kNone: EOF reached on the input stream
|
||||
static TriState inbuf_poll(int ms, MultiQueue *events)
|
||||
{
|
||||
if (os_input_ready(events)) {
|
||||
return kInputAvail;
|
||||
return kTrue;
|
||||
}
|
||||
|
||||
if (do_profiling == PROF_YES && ms) {
|
||||
prof_inchar_enter();
|
||||
prof_input_start();
|
||||
}
|
||||
|
||||
if ((ms == -1 || ms > 0) && events != main_loop.events && !input_eof) {
|
||||
@ -479,20 +493,18 @@ static InbufPollResult inbuf_poll(int ms, MultiQueue *events)
|
||||
blocking = true;
|
||||
multiqueue_process_events(ch_before_blocking_events);
|
||||
}
|
||||
DLOG("blocking... events_enabled=%d events_pending=%d", events != NULL,
|
||||
events && !multiqueue_empty(events));
|
||||
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, ms,
|
||||
os_input_ready(events) || input_eof);
|
||||
DLOG("blocking... events=%d pending=%d", !!events, pending_events(events));
|
||||
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, ms, os_input_ready(events) || input_eof);
|
||||
blocking = false;
|
||||
|
||||
if (do_profiling == PROF_YES && ms) {
|
||||
prof_inchar_exit();
|
||||
prof_input_end();
|
||||
}
|
||||
|
||||
if (os_input_ready(events)) {
|
||||
return kInputAvail;
|
||||
return kTrue;
|
||||
}
|
||||
return input_eof ? kInputEof : kInputNone;
|
||||
return input_eof ? kNone : kFalse;
|
||||
}
|
||||
|
||||
static size_t input_read_cb(RStream *stream, const char *buf, size_t c, void *data, bool at_eof)
|
||||
@ -514,7 +526,7 @@ static void process_ctrl_c(void)
|
||||
|
||||
size_t available = input_available();
|
||||
ssize_t i;
|
||||
for (i = (ssize_t)available - 1; i >= 0; i--) {
|
||||
for (i = (ssize_t)available - 1; i >= 0; i--) { // Reverse-search input for Ctrl_C.
|
||||
uint8_t c = (uint8_t)input_read_pos[i];
|
||||
if (c == Ctrl_C
|
||||
|| (c == 'C' && i >= 3
|
||||
@ -533,8 +545,8 @@ static void process_ctrl_c(void)
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function used to push bytes from the 'event' key sequence partially
|
||||
// between calls to os_inchar when maxlen < 3
|
||||
/// Pushes bytes from the "event" key sequence (KE_EVENT) partially between calls to input_get when
|
||||
/// `maxlen < 3`.
|
||||
static int push_event_key(uint8_t *buf, int maxlen)
|
||||
{
|
||||
static const uint8_t key[3] = { K_SPECIAL, KS_EXTRA, KE_EVENT };
|
||||
|
@ -63,22 +63,32 @@ static const char *const xdg_defaults[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Get the value of $NVIM_APPNAME or "nvim" if not set.
|
||||
/// Gets the value of $NVIM_APPNAME, or "nvim" if not set.
|
||||
///
|
||||
/// @param namelike Write "name-like" value (no path separators) in `NameBuff`.
|
||||
///
|
||||
/// @return $NVIM_APPNAME value
|
||||
const char *get_appname(void)
|
||||
const char *get_appname(bool namelike)
|
||||
{
|
||||
const char *env_val = os_getenv("NVIM_APPNAME");
|
||||
if (env_val == NULL || *env_val == NUL) {
|
||||
env_val = "nvim";
|
||||
}
|
||||
|
||||
if (namelike) {
|
||||
// Appname may be a relative path, replace slashes to make it name-like.
|
||||
xstrlcpy(NameBuff, env_val, sizeof(NameBuff));
|
||||
memchrsub(NameBuff, '/', '-', sizeof(NameBuff));
|
||||
memchrsub(NameBuff, '\\', '-', sizeof(NameBuff));
|
||||
}
|
||||
|
||||
return env_val;
|
||||
}
|
||||
|
||||
/// Ensure that APPNAME is valid. Must be a name or relative path.
|
||||
bool appname_is_valid(void)
|
||||
{
|
||||
const char *appname = get_appname();
|
||||
const char *appname = get_appname(false);
|
||||
if (path_is_absolute(appname)
|
||||
// TODO(justinmk): on Windows, path_is_absolute says "/" is NOT absolute. Should it?
|
||||
|| strequal(appname, "/")
|
||||
@ -193,7 +203,7 @@ char *get_xdg_home(const XDGVarType idx)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
char *dir = stdpaths_get_xdg_var(idx);
|
||||
const char *appname = get_appname();
|
||||
const char *appname = get_appname(false);
|
||||
size_t appname_len = strlen(appname);
|
||||
assert(appname_len < (IOSIZE - sizeof("-data")));
|
||||
|
||||
|
@ -16,9 +16,6 @@
|
||||
#include <sys/stat.h>
|
||||
#include <windows.h>
|
||||
|
||||
// vterm.h defines an `unsigned int small` in a struct, triggering error C2632
|
||||
#undef small
|
||||
|
||||
// Windows does not have S_IFLNK but libuv defines it
|
||||
// and sets the flag for us when calling uv_fs_stat.
|
||||
#include <uv.h>
|
||||
|
@ -3608,8 +3608,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "(2) 'n Bewerkingsessie van hierdie lêer het ineengestort.\n"
|
||||
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " Indien wel, gebruik \":recover\" of \"vim -r"
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " Indien wel, gebruik \":recover\" of \"nvim -r"
|
||||
|
||||
msgid ""
|
||||
"\"\n"
|
||||
|
@ -4015,8 +4015,8 @@ msgstr ""
|
||||
"(2) El Vim s'ha estrellat mentre s'editava aquest fitxer.\n"
|
||||
|
||||
#: ../memline.c:3247
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " En aquest cas, useu \":recover\" o bé \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " En aquest cas, useu \":recover\" o bé \"nvim -r "
|
||||
|
||||
#: ../memline.c:3249
|
||||
msgid ""
|
||||
|
@ -4077,8 +4077,8 @@ msgstr ""
|
||||
"(2) Editace tohoto souboru byla přerušena nečekaným ukončením programu.\n"
|
||||
|
||||
#: ../memline.c:3247
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " Je-li tomu tak, pak použijte \":recover\" èi \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " Je-li tomu tak, pak použijte \":recover\" èi \"nvim -r "
|
||||
|
||||
#: ../memline.c:3249
|
||||
msgid ""
|
||||
|
@ -4077,8 +4077,8 @@ msgstr ""
|
||||
"(2) Editace tohoto souboru byla přerušena nečekaným ukončením programu.\n"
|
||||
|
||||
#: ../memline.c:3247
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " Je-li tomu tak, pak pou¾ijte \":recover\" èi \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " Je-li tomu tak, pak pou¾ijte \":recover\" èi \"nvim -r "
|
||||
|
||||
#: ../memline.c:3249
|
||||
msgid ""
|
||||
|
@ -3663,8 +3663,8 @@ msgstr ""
|
||||
msgid "(2) An edit session for this file crashed.\n"
|
||||
msgstr "(2) En redigeringssession for filen holdt op med at virke.\n"
|
||||
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " Hvis det er tilfældet, så brug \":recover\" eller \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " Hvis det er tilfældet, så brug \":recover\" eller \"nvim -r "
|
||||
|
||||
msgid ""
|
||||
"\"\n"
|
||||
|
@ -3436,9 +3436,9 @@ msgid "(2) An edit session for this file crashed.\n"
|
||||
msgstr "(2) Eine Sitzung für diese Datei ist abgestürzt.\n"
|
||||
|
||||
#: ../memline.c:3204
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr ""
|
||||
" Wenn dies der Fall ist, so verwenden Sie \":recover\" oder \"vim -r "
|
||||
" Wenn dies der Fall ist, so verwenden Sie \":recover\" oder \"nvim -r "
|
||||
|
||||
#: ../memline.c:3206
|
||||
msgid ""
|
||||
|
@ -3847,7 +3847,7 @@ msgid "(2) An edit session for this file crashed.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../memline.c:3247
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr ""
|
||||
|
||||
#: ../memline.c:3249
|
||||
|
@ -3531,8 +3531,8 @@ msgstr ""
|
||||
msgid "(2) An edit session for this file crashed.\n"
|
||||
msgstr "(2) Redakta seanco de tiu dosiero kolapsis.\n"
|
||||
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " Se veras, uzu \":recover\" aŭ \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " Se veras, uzu \":recover\" aŭ \"nvim -r "
|
||||
|
||||
msgid ""
|
||||
"\"\n"
|
||||
|
@ -4078,8 +4078,8 @@ msgstr ""
|
||||
"(2) Falló una sesión de edición de este archivo.\n"
|
||||
|
||||
#: ../memline.c:3247
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " Si es así, use \":recover\" o \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " Si es así, use \":recover\" o \"nvim -r "
|
||||
|
||||
#: ../memline.c:3249
|
||||
msgid ""
|
||||
|
@ -3660,8 +3660,8 @@ msgstr ""
|
||||
msgid "(2) An edit session for this file crashed.\n"
|
||||
msgstr "(2) Tiedostonmuokkausistunto on kaatunut.\n"
|
||||
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " Jos näin on, käytä komentoa :recover tai vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " Jos näin on, käytä komentoa :recover tai nvim -r "
|
||||
|
||||
msgid ""
|
||||
"\"\n"
|
||||
|
@ -3241,8 +3241,8 @@ msgstr ""
|
||||
msgid "(2) An edit session for this file crashed.\n"
|
||||
msgstr "(2) Une session d'édition de ce fichier a planté.\n"
|
||||
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " Si c'est le cas, utilisez \":recover\" ou \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " Si c'est le cas, utilisez \":recover\" ou \"nvim -r "
|
||||
|
||||
msgid ""
|
||||
"\"\n"
|
||||
|
@ -3696,8 +3696,8 @@ msgstr ""
|
||||
msgid "(2) An edit session for this file crashed.\n"
|
||||
msgstr "(2) Thuairteáil seisiún eagarthóireachta.\n"
|
||||
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " Más amhlaidh, bain úsáid as \":recover\" nó \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " Más amhlaidh, bain úsáid as \":recover\" nó \"nvim -r "
|
||||
|
||||
msgid ""
|
||||
"\"\n"
|
||||
|
@ -4037,8 +4037,8 @@ msgid "(2) An edit session for this file crashed.\n"
|
||||
msgstr "(2) Una sessione di edit per questo file è finita male.\n"
|
||||
|
||||
#: ../memline.c:3247
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " Se è così, usa \":recover\" oppure \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " Se è così, usa \":recover\" oppure \"nvim -r "
|
||||
|
||||
#: ../memline.c:3249
|
||||
msgid ""
|
||||
|
@ -3466,8 +3466,8 @@ msgstr ""
|
||||
msgid "(2) An edit session for this file crashed.\n"
|
||||
msgstr "(2) このファイルの編集セッションがクラッシュした.\n"
|
||||
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " この場合には \":recover\" か \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " この場合には \":recover\" か \"nvim -r "
|
||||
|
||||
msgid ""
|
||||
"\"\n"
|
||||
|
@ -5092,8 +5092,8 @@ msgstr ""
|
||||
msgid "(2) An edit session for this file crashed.\n"
|
||||
msgstr "(2) このファイルの編集セッションがクラッシュした.\n"
|
||||
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " この場合には \":recover\" か \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " この場合には \":recover\" か \"nvim -r "
|
||||
|
||||
msgid ""
|
||||
"\"\n"
|
||||
|
@ -3957,8 +3957,8 @@ msgstr ""
|
||||
"(2) 파일을 고치다가 죽었었습니다.\n"
|
||||
|
||||
#: ../memline.c:3247
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " 만약 그렇다면 \":recover\" 혹은 \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " 만약 그렇다면 \":recover\" 혹은 \"nvim -r "
|
||||
|
||||
#: ../memline.c:3249
|
||||
msgid ""
|
||||
|
@ -3978,8 +3978,8 @@ msgstr ""
|
||||
"(2) En økt for denne filen kræsjet.\n"
|
||||
|
||||
#: ../memline.c:3247
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " Hvis det er tilfelle, bruk \":recover\" eller \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " Hvis det er tilfelle, bruk \":recover\" eller \"nvim -r "
|
||||
|
||||
#: ../memline.c:3249
|
||||
msgid ""
|
||||
|
@ -3984,8 +3984,8 @@ msgstr ""
|
||||
"(2) Een sessie waarin dit bestand werd bewerkt is onverhoeds gestopt.\n"
|
||||
|
||||
#: ../memline.c:3247
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " Als dit het geval is, gebruikt dan \":recover\" of \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " Als dit het geval is, gebruikt dan \":recover\" of \"nvim -r "
|
||||
|
||||
#: ../memline.c:3249
|
||||
msgid ""
|
||||
|
@ -3978,8 +3978,8 @@ msgstr ""
|
||||
"(2) En økt for denne filen kræsjet.\n"
|
||||
|
||||
#: ../memline.c:3247
|
||||
msgid " If this is the case, use \":recover\" or \"vim -r "
|
||||
msgstr " Hvis det er tilfelle, bruk \":recover\" eller \"vim -r "
|
||||
msgid " If this is the case, use \":recover\" or \"nvim -r "
|
||||
msgstr " Hvis det er tilfelle, bruk \":recover\" eller \"nvim -r "
|
||||
|
||||
#: ../memline.c:3249
|
||||
msgid ""
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user