mirror of
https://github.com/neovim/neovim.git
synced 2025-09-05 19:08:15 +00:00
Compare commits
95 Commits
v0.11.1
...
release-0.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
be368a6f74 | ||
![]() |
c624f260d3 | ||
![]() |
6e31a3a51e | ||
![]() |
57180fcb39 | ||
![]() |
bacc0b9c0b | ||
![]() |
b535db77d8 | ||
![]() |
74a949b859 | ||
![]() |
0986b8be4f | ||
![]() |
332cc6424a | ||
![]() |
3a826ceed3 | ||
![]() |
d8561c078c | ||
![]() |
bee7b6167d | ||
![]() |
786272d00b | ||
![]() |
71294e6430 | ||
![]() |
a375053492 | ||
![]() |
0ad89969e1 | ||
![]() |
c91c6381ee | ||
![]() |
6d2e0ab621 | ||
![]() |
145dd051c3 | ||
![]() |
ba9b424154 | ||
![]() |
8f3621c4b7 | ||
![]() |
37b78620db | ||
![]() |
74cbddf6e1 | ||
![]() |
ca73525485 | ||
![]() |
1af25791d5 | ||
![]() |
6c6ce6894a | ||
![]() |
40caaeb041 | ||
![]() |
a92baa095a | ||
![]() |
cee2de23ab | ||
![]() |
b25b41997a | ||
![]() |
d89523ba62 | ||
![]() |
cc2e16f4e0 | ||
![]() |
33284615fe | ||
![]() |
239e549d23 | ||
![]() |
f0101d696c | ||
![]() |
315f8b92d0 | ||
![]() |
f1ab73cf6c | ||
![]() |
a6a6f7ba16 | ||
![]() |
f365e68293 | ||
![]() |
11dafcaf05 | ||
![]() |
dd0d4fc666 | ||
![]() |
e44f88bbe7 | ||
![]() |
5901b4c624 | ||
![]() |
01cb4d8846 | ||
![]() |
bdd92e46b3 | ||
![]() |
11f18a8adf | ||
![]() |
ede410ae3d | ||
![]() |
cebda91abb | ||
![]() |
6177030e4a | ||
![]() |
5b839ced69 | ||
![]() |
844872cc0a | ||
![]() |
0e96f7d04c | ||
![]() |
1cc63abf4a | ||
![]() |
9f51da3442 | ||
![]() |
857678c2ec | ||
![]() |
03bd9147f0 | ||
![]() |
ee9e3420fd | ||
![]() |
7b60ec79ea | ||
![]() |
14357c83c5 | ||
![]() |
571609fb89 | ||
![]() |
37a00be7c0 | ||
![]() |
09306f07c4 | ||
![]() |
ec101b9fd9 | ||
![]() |
222d1414dc | ||
![]() |
7f4fa077cd | ||
![]() |
00889948dd | ||
![]() |
1bb861c7a1 | ||
![]() |
d547d874af | ||
![]() |
060eeaa14c | ||
![]() |
9dae939b1f | ||
![]() |
8c6a4fab66 | ||
![]() |
1b54344c11 | ||
![]() |
8f68548384 | ||
![]() |
25da2430f9 | ||
![]() |
93f1ec0a59 | ||
![]() |
5c8e5432c0 | ||
![]() |
e86997a812 | ||
![]() |
a0ebba7052 | ||
![]() |
ae249d81fb | ||
![]() |
785baceaee | ||
![]() |
aa0ddc6690 | ||
![]() |
2cd272decb | ||
![]() |
08ddfa9851 | ||
![]() |
beac24d6f3 | ||
![]() |
5dcf2c77a9 | ||
![]() |
ce4c8010cc | ||
![]() |
270f71b571 | ||
![]() |
3c0f239c3e | ||
![]() |
1d32521135 | ||
![]() |
bd057d4b40 | ||
![]() |
096f8418c5 | ||
![]() |
84784a8391 | ||
![]() |
fb11ef0aad | ||
![]() |
faf3159ab0 | ||
![]() |
a4699892af |
4
.github/workflows/api-docs.yml
vendored
4
.github/workflows/api-docs.yml
vendored
@@ -26,7 +26,9 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y doxygen python3 python3-msgpack luajit
|
||||
sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y python3 luajit
|
||||
conda install -c conda-forge doxygen=1.9.2 msgpack-python
|
||||
echo "$CONDA/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Setup git config
|
||||
run: |
|
||||
|
43
.github/workflows/ci.yml
vendored
43
.github/workflows/ci.yml
vendored
@@ -11,6 +11,45 @@ on:
|
||||
- 'release-[0-9]+.[0-9]+'
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
if: (github.event_name == 'pull_request' && github.base_ref == 'master' && !github.event.pull_request.draft) || (github.event_name == 'push' && github.ref == 'refs/heads/master')
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
CC: gcc
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup common environment variables
|
||||
run: ./.github/workflows/env.sh lint
|
||||
|
||||
- name: Install apt packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y autoconf automake build-essential ccache cmake cpanminus gettext gperf language-pack-tr libtool-bin locales ninja-build pkg-config python3 python3-pip python3-setuptools unzip
|
||||
|
||||
- name: Setup interpreter packages
|
||||
run: |
|
||||
./ci/before_install.sh
|
||||
./ci/install.sh
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
${{ env.CACHE_NVIM_DEPS_DIR }}
|
||||
~/.ccache
|
||||
key: ${{ matrix.runner }}-lint-${{ matrix.cc }}-${{ hashFiles('cmake/*', 'third-party/**', '**/CMakeLists.txt') }}-${{ github.base_ref }}
|
||||
|
||||
- name: Build third-party
|
||||
run: ./ci/before_script.sh
|
||||
|
||||
- name: Run lint
|
||||
run: ./ci/script.sh
|
||||
|
||||
- name: Cache dependencies
|
||||
if: ${{ success() }}
|
||||
run: ./ci/before_cache.sh
|
||||
|
||||
unixish:
|
||||
name: ${{ matrix.runner }} ${{ matrix.flavor }} (cc=${{ matrix.cc }})
|
||||
strategy:
|
||||
@@ -21,10 +60,6 @@ jobs:
|
||||
cc: clang-12
|
||||
runner: ubuntu-20.04
|
||||
os: linux
|
||||
- flavor: lint
|
||||
cc: gcc
|
||||
runner: ubuntu-20.04
|
||||
os: linux
|
||||
- flavor: tsan
|
||||
cc: clang-12
|
||||
runner: ubuntu-20.04
|
||||
|
4
.github/workflows/commitlint.yml
vendored
4
.github/workflows/commitlint.yml
vendored
@@ -13,7 +13,9 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
path: pr_nvim
|
||||
- uses: rhysd/action-setup-vim@v1
|
||||
with:
|
||||
neovim: true
|
||||
- run: nvim --clean -es +"lua require('scripts.lintcommit').main({trace=true})"
|
||||
- run: wget https://raw.githubusercontent.com/neovim/neovim/master/scripts/lintcommit.lua
|
||||
- run: nvim --clean -es +"cd pr_nvim" +"lua dofile('../lintcommit.lua').main({trace=true})"
|
||||
|
33
.github/workflows/squash-typos.yml
vendored
33
.github/workflows/squash-typos.yml
vendored
@@ -1,33 +0,0 @@
|
||||
name: Squash Typo Pull Requests
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: labeled
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
jobs:
|
||||
build:
|
||||
if: github.event.label.name == 'typo'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@v2
|
||||
|
||||
- name: Setup git config
|
||||
run: |
|
||||
git config --global user.name 'marvim'
|
||||
git config --global user.email 'marvim@users.noreply.github.com'
|
||||
|
||||
- run: python scripts/squash_typos.py
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.number }}
|
@@ -137,8 +137,8 @@ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
|
||||
# version string, else they are combined with the result of `git describe`.
|
||||
set(NVIM_VERSION_MAJOR 0)
|
||||
set(NVIM_VERSION_MINOR 6)
|
||||
set(NVIM_VERSION_PATCH 0)
|
||||
set(NVIM_VERSION_PRERELEASE "") # for package maintainers
|
||||
set(NVIM_VERSION_PATCH 2)
|
||||
set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
|
||||
|
||||
# API level
|
||||
set(NVIM_API_LEVEL 8) # Bump this after any API change.
|
||||
|
11
ci/build.ps1
11
ci/build.ps1
@@ -86,19 +86,10 @@ elseif ($compiler -eq 'MSVC') {
|
||||
}
|
||||
|
||||
if (-not $NoTests) {
|
||||
# Setup python (use AppVeyor system python)
|
||||
|
||||
# Disambiguate python3, if needed
|
||||
if (-not (Test-Path -Path C:\hostedtoolcache\windows\Python\3.5.4\x64\python3.exe) ) {
|
||||
move C:\hostedtoolcache\windows\Python\3.5.4\x64\python.exe C:\hostedtoolcache\windows\Python\3.5.4\x64\python3.exe
|
||||
}
|
||||
$env:PATH = "C:\hostedtoolcache\windows\Python\2.7.18\x64;C:\hostedtoolcache\windows\Python\3.5.4\x64;$env:PATH"
|
||||
|
||||
python -m ensurepip
|
||||
python -m pip install pynvim ; exitIfFailed
|
||||
python3 -m pip install pynvim ; exitIfFailed
|
||||
# Sanity check
|
||||
python -c "import pynvim; print(str(pynvim))" ; exitIfFailed
|
||||
python3 -c "import pynvim; print(str(pynvim))" ; exitIfFailed
|
||||
|
||||
gem.cmd install --pre neovim
|
||||
Get-Command -CommandType Application neovim-ruby-host.bat
|
||||
|
@@ -46,6 +46,10 @@ if(DEFINED ENV{TEST_FILTER} AND NOT "$ENV{TEST_FILTER}" STREQUAL "")
|
||||
list(APPEND BUSTED_ARGS --filter $ENV{TEST_FILTER})
|
||||
endif()
|
||||
|
||||
if(DEFINED ENV{TEST_FILTER_OUT} AND NOT "$ENV{TEST_FILTER_OUT}" STREQUAL "")
|
||||
list(APPEND BUSTED_ARGS --filter-out $ENV{TEST_FILTER_OUT})
|
||||
endif()
|
||||
|
||||
# TMPDIR: use relative test path (for parallel test runs / isolation).
|
||||
set(ENV{TMPDIR} "${BUILD_DIR}/Xtest_tmpdir/${TEST_PATH}")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory $ENV{TMPDIR})
|
||||
|
@@ -1,27 +1,3 @@
|
||||
function! s:enhance_syntax() abort
|
||||
syntax case match
|
||||
|
||||
syntax keyword healthError ERROR[:]
|
||||
\ containedin=markdownCodeBlock,mkdListItemLine
|
||||
highlight default link healthError Error
|
||||
|
||||
syntax keyword healthWarning WARNING[:]
|
||||
\ containedin=markdownCodeBlock,mkdListItemLine
|
||||
highlight default link healthWarning WarningMsg
|
||||
|
||||
syntax keyword healthSuccess OK[:]
|
||||
\ containedin=markdownCodeBlock,mkdListItemLine
|
||||
highlight default healthSuccess guibg=#5fff00 guifg=#080808 ctermbg=82 ctermfg=232
|
||||
|
||||
syntax match healthHelp "|.\{-}|" contains=healthBar
|
||||
\ containedin=markdownCodeBlock,mkdListItemLine
|
||||
syntax match healthBar "|" contained conceal
|
||||
highlight default link healthHelp Identifier
|
||||
|
||||
" We do not care about markdown syntax errors in :checkhealth output.
|
||||
highlight! link markdownError Normal
|
||||
endfunction
|
||||
|
||||
" Runs the specified healthchecks.
|
||||
" Runs all discovered healthchecks if a:plugin_names is empty.
|
||||
function! health#check(plugin_names) abort
|
||||
@@ -29,13 +5,9 @@ function! health#check(plugin_names) abort
|
||||
\ ? s:discover_healthchecks()
|
||||
\ : s:get_healthcheck(a:plugin_names)
|
||||
|
||||
tabnew
|
||||
setlocal wrap breakindent linebreak
|
||||
setlocal filetype=markdown
|
||||
setlocal conceallevel=2 concealcursor=nc
|
||||
setlocal keywordprg=:help
|
||||
let &l:iskeyword='!-~,^*,^|,^",192-255'
|
||||
call s:enhance_syntax()
|
||||
" create scratch-buffer
|
||||
execute 'tab sbuffer' nvim_create_buf(v:true, v:true)
|
||||
setfiletype checkhealth
|
||||
|
||||
if empty(healthchecks)
|
||||
call setline(1, 'ERROR: No healthchecks found.')
|
||||
@@ -70,8 +42,6 @@ function! health#check(plugin_names) abort
|
||||
|
||||
" needed for plasticboy/vim-markdown, because it uses fdm=expr
|
||||
normal! zR
|
||||
setlocal nomodified
|
||||
setlocal bufhidden=hide
|
||||
redraw|echo ''
|
||||
endfunction
|
||||
|
||||
|
@@ -523,7 +523,7 @@ function! s:check_virtualenv() abort
|
||||
let hint = '$PATH ambiguities in subshells typically are '
|
||||
\.'caused by your shell config overriding the $PATH previously set by the '
|
||||
\.'virtualenv. Either prevent them from doing so, or use this workaround: '
|
||||
\.'https://vi.stackexchange.com/a/7654'
|
||||
\.'https://vi.stackexchange.com/a/34996'
|
||||
let hints[hint] = v:true
|
||||
endif
|
||||
endfor
|
||||
|
@@ -56,6 +56,7 @@ function s:msgpack_init_python() abort
|
||||
\. " time = datetime.datetime.fromtimestamp(timestamp)\n"
|
||||
\. " return time.strftime(fmt)\n"
|
||||
\. "def shada_dict_strptime():\n"
|
||||
\. " import calendar\n"
|
||||
\. " import datetime\n"
|
||||
\. " import vim\n"
|
||||
\. " fmt = vim.eval('a:format')\n"
|
||||
@@ -64,7 +65,10 @@ function s:msgpack_init_python() abort
|
||||
\. " try:\n"
|
||||
\. " timestamp = int(timestamp.timestamp())\n"
|
||||
\. " except:\n"
|
||||
\. " timestamp = int(timestamp.strftime('%s'))\n"
|
||||
\. " try:\n"
|
||||
\. " timestamp = int(timestamp.strftime('%s'))\n"
|
||||
\. " except:\n"
|
||||
\. " timestamp = calendar.timegm(timestamp.utctimetuple())\n"
|
||||
\. " if timestamp > 2 ** 31:\n"
|
||||
\. " tsabs = abs(timestamp)\n"
|
||||
\. " return ('{\"_TYPE\": v:msgpack_types.integer,'\n"
|
||||
|
@@ -361,7 +361,7 @@ UTF-32 and UTF-16 sizes of the deleted region is also passed as additional
|
||||
arguments {old_utf32_size} and {old_utf16_size}.
|
||||
|
||||
"on_changedtick" is invoked when |b:changedtick| was incremented but no text
|
||||
was changed. The parameters recieved are ("changedtick", {buf}, {changedtick}).
|
||||
was changed. The parameters received are ("changedtick", {buf}, {changedtick}).
|
||||
|
||||
*api-lua-detach*
|
||||
In-process Lua callbacks can detach by returning `true`. This will detach all
|
||||
@@ -2353,7 +2353,7 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
|
||||
|api-indexing|
|
||||
{opts} Optional parameters.
|
||||
• id : id of the extmark to edit.
|
||||
• end_line : ending line of the mark, 0-based
|
||||
• end_row : ending line of the mark, 0-based
|
||||
inclusive.
|
||||
• end_col : ending col of the mark, 0-based
|
||||
exclusive.
|
||||
|
@@ -130,7 +130,7 @@ with |vim.notify()|: >
|
||||
In this example, there is nothing to do when diagnostics are hidden, so we
|
||||
omit the "hide" function.
|
||||
|
||||
Existing handlers can be overriden. For example, use the following to only
|
||||
Existing handlers can be overridden. For example, use the following to only
|
||||
show a sign for the highest severity diagnostic on a given line: >
|
||||
|
||||
-- Create a custom namespace. This will aggregate signs from all other
|
||||
@@ -175,8 +175,9 @@ All highlights defined for diagnostics begin with `Diagnostic` followed by
|
||||
the type of highlight (e.g., `Sign`, `Underline`, etc.) and the severity (e.g.
|
||||
`Error`, `Warn`, etc.)
|
||||
|
||||
Sign, underline and virtual text highlights (by default) are linked to their
|
||||
corresponding default highlight.
|
||||
By default, highlights for signs, floating windows, and virtual text are linked to the
|
||||
corresponding default highlight. Underline highlights are not linked and use their
|
||||
own default highlight groups.
|
||||
|
||||
For example, the default highlighting for |hl-DiagnosticSignError| is linked
|
||||
to |hl-DiagnosticError|. To change the default (and therefore the linked
|
||||
@@ -296,7 +297,6 @@ Example: >
|
||||
autocmd DiagnosticChanged * lua vim.diagnostic.setqflist({open = false })
|
||||
<
|
||||
==============================================================================
|
||||
==============================================================================
|
||||
Lua module: vim.diagnostic *diagnostic-api*
|
||||
|
||||
config({opts}, {namespace}) *vim.diagnostic.config()*
|
||||
@@ -341,13 +341,24 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
|
||||
|diagnostic-severity|
|
||||
|
||||
• virtual_text: (default true) Use virtual
|
||||
text for diagnostics. Options:
|
||||
text for diagnostics. If multiple
|
||||
diagnostics are set for a namespace, one
|
||||
prefix per diagnostic + the last diagnostic
|
||||
message are shown. Options:
|
||||
• severity: Only show virtual text for
|
||||
diagnostics matching the given severity
|
||||
|diagnostic-severity|
|
||||
• source: (string) Include the diagnostic
|
||||
source in virtual text. One of "always"
|
||||
or "if_many".
|
||||
• source: (boolean or string) Include the
|
||||
diagnostic source in virtual text. Use
|
||||
"if_many" to only show sources if there
|
||||
is more than one diagnostic source in the
|
||||
buffer. Otherwise, any truthy value means
|
||||
to always show the diagnostic source.
|
||||
• spacing: (number) Amount of empty spaces
|
||||
inserted at the beginning of the virtual
|
||||
text.
|
||||
• prefix: (string) Prepend diagnostic
|
||||
message with prefix.
|
||||
• format: (function) A function that takes
|
||||
a diagnostic as input and returns a
|
||||
string. The return value is the text used
|
||||
@@ -574,61 +585,67 @@ match({str}, {pat}, {groups}, {severity_map}, {defaults})
|
||||
diagnostic |diagnostic-structure| or `nil` if {pat} fails
|
||||
to match {str}.
|
||||
|
||||
open_float({bufnr}, {opts}) *vim.diagnostic.open_float()*
|
||||
open_float({opts}, {...}) *vim.diagnostic.open_float()*
|
||||
Show diagnostics in a floating window.
|
||||
|
||||
Parameters: ~
|
||||
{bufnr} number|nil Buffer number. Defaults to the current
|
||||
buffer.
|
||||
{opts} table|nil Configuration table with the same keys
|
||||
as |vim.lsp.util.open_floating_preview()| in
|
||||
addition to the following:
|
||||
• namespace: (number) Limit diagnostics to the
|
||||
given namespace
|
||||
• scope: (string, default "line") Show
|
||||
diagnostics from the whole buffer ("buffer"),
|
||||
the current cursor line ("line"), or the
|
||||
current cursor position ("cursor").
|
||||
• pos: (number or table) If {scope} is "line" or
|
||||
"cursor", use this position rather than the
|
||||
cursor position. If a number, interpreted as a
|
||||
line number; otherwise, a (row, col) tuple.
|
||||
• severity_sort: (default false) Sort diagnostics
|
||||
by severity. Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
• severity: See |diagnostic-severity|. Overrides
|
||||
the setting from |vim.diagnostic.config()|.
|
||||
• header: (string or table) String to use as the
|
||||
header for the floating window. If a table, it
|
||||
is interpreted as a [text, hl_group] tuple.
|
||||
Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
• source: (string) Include the diagnostic source
|
||||
in the message. One of "always" or "if_many".
|
||||
Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
• format: (function) A function that takes a
|
||||
diagnostic as input and returns a string. The
|
||||
return value is the text used to display the
|
||||
diagnostic. Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
• prefix: (function, string, or table) Prefix
|
||||
each diagnostic in the floating window. If a
|
||||
function, it must have the signature
|
||||
(diagnostic, i, total) -> (string, string),
|
||||
where {i} is the index of the diagnostic being
|
||||
evaluated and {total} is the total number of
|
||||
diagnostics displayed in the window. The
|
||||
function should return a string which is
|
||||
prepended to each diagnostic in the window as
|
||||
well as an (optional) highlight group which
|
||||
will be used to highlight the prefix. If
|
||||
{prefix} is a table, it is interpreted as a
|
||||
[text, hl_group] tuple as in |nvim_echo()|;
|
||||
otherwise, if {prefix} is a string, it is
|
||||
prepended to each diagnostic in the window with
|
||||
no highlight. Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
{opts} table|nil Configuration table with the same keys
|
||||
as |vim.lsp.util.open_floating_preview()| in
|
||||
addition to the following:
|
||||
• bufnr: (number) Buffer number to show
|
||||
diagnostics from. Defaults to the current
|
||||
buffer.
|
||||
• namespace: (number) Limit diagnostics to the
|
||||
given namespace
|
||||
• scope: (string, default "line") Show diagnostics
|
||||
from the whole buffer ("buffer"), the current
|
||||
cursor line ("line"), or the current cursor
|
||||
position ("cursor"). Shorthand versions are also
|
||||
accepted ("c" for "cursor", "l" for "line", "b"
|
||||
for "buffer").
|
||||
• pos: (number or table) If {scope} is "line" or
|
||||
"cursor", use this position rather than the
|
||||
cursor position. If a number, interpreted as a
|
||||
line number; otherwise, a (row, col) tuple.
|
||||
• severity_sort: (default false) Sort diagnostics
|
||||
by severity. Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
• severity: See |diagnostic-severity|. Overrides
|
||||
the setting from |vim.diagnostic.config()|.
|
||||
• header: (string or table) String to use as the
|
||||
header for the floating window. If a table, it
|
||||
is interpreted as a [text, hl_group] tuple.
|
||||
Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
• source: (boolean or string) Include the
|
||||
diagnostic source in the message. Use "if_many"
|
||||
to only show sources if there is more than one
|
||||
source of diagnostics in the buffer. Otherwise,
|
||||
any truthy value means to always show the
|
||||
diagnostic source. Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
• format: (function) A function that takes a
|
||||
diagnostic as input and returns a string. The
|
||||
return value is the text used to display the
|
||||
diagnostic. Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
• prefix: (function, string, or table) Prefix each
|
||||
diagnostic in the floating window. If a
|
||||
function, it must have the signature
|
||||
(diagnostic, i, total) -> (string, string),
|
||||
where {i} is the index of the diagnostic being
|
||||
evaluated and {total} is the total number of
|
||||
diagnostics displayed in the window. The
|
||||
function should return a string which is
|
||||
prepended to each diagnostic in the window as
|
||||
well as an (optional) highlight group which will
|
||||
be used to highlight the prefix. If {prefix} is
|
||||
a table, it is interpreted as a [text, hl_group]
|
||||
tuple as in |nvim_echo()|; otherwise, if
|
||||
{prefix} is a string, it is prepended to each
|
||||
diagnostic in the window with no highlight.
|
||||
Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
|
||||
Return: ~
|
||||
tuple ({float_bufnr}, {win_id})
|
||||
|
@@ -2259,7 +2259,7 @@ USAGE RESULT DESCRIPTION ~
|
||||
abs({expr}) Float or Number absolute value of {expr}
|
||||
acos({expr}) Float arc cosine of {expr}
|
||||
add({object}, {item}) List/Blob append {item} to {object}
|
||||
and({expr}, {expr}) Number bitwise AND
|
||||
and({expr}, {expr}) Number bitwise AND
|
||||
api_info() Dict api metadata
|
||||
append({lnum}, {string}) Number append {string} below line {lnum}
|
||||
append({lnum}, {list}) Number append lines {list} below line {lnum}
|
||||
@@ -2291,7 +2291,7 @@ assert_notmatch({pat}, {text} [, {msg}])
|
||||
assert_report({msg}) Number report a test failure
|
||||
assert_true({actual} [, {msg}]) Number assert {actual} is true
|
||||
atan({expr}) Float arc tangent of {expr}
|
||||
atan2({expr}, {expr}) Float arc tangent of {expr1} / {expr2}
|
||||
atan2({expr}, {expr}) Float arc tangent of {expr1} / {expr2}
|
||||
browse({save}, {title}, {initdir}, {default})
|
||||
String put up a file requester
|
||||
browsedir({title}, {initdir}) String put up a directory requester
|
||||
@@ -2317,7 +2317,7 @@ char2nr({expr}[, {utf8}]) Number ASCII/UTF-8 value of first char in {expr}
|
||||
charidx({string}, {idx} [, {countcc}])
|
||||
Number char index of byte {idx} in {string}
|
||||
chdir({dir}) String change current working directory
|
||||
cindent({lnum}) Number C indent for line {lnum}
|
||||
cindent({lnum}) Number C indent for line {lnum}
|
||||
clearmatches([{win}]) none clear all matches
|
||||
col({expr}) Number column nr of cursor or mark
|
||||
complete({startcol}, {matches}) none set Insert mode completion
|
||||
@@ -2330,7 +2330,7 @@ copy({expr}) any make a shallow copy of {expr}
|
||||
cos({expr}) Float cosine of {expr}
|
||||
cosh({expr}) Float hyperbolic cosine of {expr}
|
||||
count({list}, {expr} [, {ic} [, {start}]])
|
||||
Number count how many {expr} are in {list}
|
||||
Number count how many {expr} are in {list}
|
||||
cscope_connection([{num}, {dbpath} [, {prepend}]])
|
||||
Number checks existence of cscope connection
|
||||
ctxget([{index}]) Dict return the |context| dict at {index}
|
||||
@@ -2343,7 +2343,7 @@ ctxsize() Number return |context-stack| size
|
||||
cursor({lnum}, {col} [, {off}])
|
||||
Number move cursor to {lnum}, {col}, {off}
|
||||
cursor({list}) Number move cursor to position in {list}
|
||||
debugbreak({pid}) Number interrupt process being debugged
|
||||
debugbreak({pid}) Number interrupt process being debugged
|
||||
deepcopy({expr} [, {noref}]) any make a full copy of {expr}
|
||||
delete({fname} [, {flags}]) Number delete the file or directory {fname}
|
||||
deletebufline({buf}, {first}[, {last}])
|
||||
@@ -2362,7 +2362,7 @@ eval({string}) any evaluate {string} into its value
|
||||
eventhandler() Number |TRUE| if inside an event handler
|
||||
executable({expr}) Number 1 if executable {expr} exists
|
||||
execute({command}) String execute and capture output of {command}
|
||||
exepath({expr}) String full path of the command {expr}
|
||||
exepath({expr}) String full path of the command {expr}
|
||||
exists({expr}) Number |TRUE| if {expr} exists
|
||||
extend({expr1}, {expr2} [, {expr3}])
|
||||
List/Dict insert items of {expr2} into {expr1}
|
||||
@@ -2482,11 +2482,11 @@ inputlist({textlist}) Number let the user pick from a choice list
|
||||
inputrestore() Number restore typeahead
|
||||
inputsave() Number save and clear typeahead
|
||||
inputsecret({prompt} [, {text}])
|
||||
String like input() but hiding the text
|
||||
String like input() but hiding the text
|
||||
insert({object}, {item} [, {idx}])
|
||||
List insert {item} in {object} [before {idx}]
|
||||
interrupt() none interrupt script execution
|
||||
invert({expr}) Number bitwise invert
|
||||
invert({expr}) Number bitwise invert
|
||||
isdirectory({directory}) Number |TRUE| if {directory} is a directory
|
||||
isinf({expr}) Number determine if {expr} is infinity value
|
||||
(positive or negative)
|
||||
@@ -2506,7 +2506,7 @@ json_encode({expr}) String Convert {expr} to JSON
|
||||
keys({dict}) List keys in {dict}
|
||||
len({expr}) Number the length of {expr}
|
||||
libcall({lib}, {func}, {arg}) String call {func} in library {lib} with {arg}
|
||||
libcallnr({lib}, {func}, {arg}) Number idem, but return a Number
|
||||
libcallnr({lib}, {func}, {arg}) Number idem, but return a Number
|
||||
line({expr} [, {winid}]) Number line nr of cursor, last line or mark
|
||||
line2byte({lnum}) Number byte count of line {lnum}
|
||||
lispindent({lnum}) Number Lisp indent for line {lnum}
|
||||
@@ -2548,7 +2548,7 @@ msgpackparse({data}) List parse msgpack to a list of objects
|
||||
nextnonblank({lnum}) Number line nr of non-blank line >= {lnum}
|
||||
nr2char({expr}[, {utf8}]) String single char with ASCII/UTF-8 value {expr}
|
||||
nvim_...({args}...) any call nvim |api| functions
|
||||
or({expr}, {expr}) Number bitwise OR
|
||||
or({expr}, {expr}) Number bitwise OR
|
||||
pathshorten({expr}) String shorten directory names in a path
|
||||
perleval({expr}) any evaluate |perl| expression
|
||||
pow({x}, {y}) Float {x} to the power of {y}
|
||||
@@ -2607,7 +2607,7 @@ screenrow() Number current cursor row
|
||||
screenstring({row}, {col}) String characters at screen position
|
||||
search({pattern} [, {flags} [, {stopline} [, {timeout}]]])
|
||||
Number search for {pattern}
|
||||
searchcount([{options}]) Dict Get or update the last search count
|
||||
searchcount([{options}]) Dict Get or update the last search count
|
||||
searchdecl({name} [, {global} [, {thisblock}]])
|
||||
Number search for variable declaration
|
||||
searchpair({start}, {middle}, {end} [, {flags} [, {skip} [...]]])
|
||||
@@ -2679,7 +2679,7 @@ split({expr} [, {pat} [, {keepempty}]])
|
||||
List make |List| from {pat} separated {expr}
|
||||
sqrt({expr}) Float square root of {expr}
|
||||
stdioopen({dict}) Number open stdio in a headless instance.
|
||||
stdpath({what}) String/List returns the standard path(s) for {what}
|
||||
stdpath({what}) String/List returns the standard path(s) for {what}
|
||||
str2float({expr} [, {quoted}]) Float convert String to Float
|
||||
str2list({expr} [, {utf8}]) List convert each character of {expr} to
|
||||
ASCII/UTF-8 value
|
||||
@@ -2715,7 +2715,7 @@ synID({lnum}, {col}, {trans}) Number syntax ID at {lnum} and {col}
|
||||
synIDattr({synID}, {what} [, {mode}])
|
||||
String attribute {what} of syntax ID {synID}
|
||||
synIDtrans({synID}) Number translated syntax ID of {synID}
|
||||
synconcealed({lnum}, {col}) List info about concealing
|
||||
synconcealed({lnum}, {col}) List info about concealing
|
||||
synstack({lnum}, {col}) List stack of syntax IDs at {lnum} and {col}
|
||||
system({cmd} [, {input}]) String output of shell command/filter {cmd}
|
||||
systemlist({cmd} [, {input}]) List output of shell command/filter {cmd}
|
||||
@@ -2751,7 +2751,7 @@ values({dict}) List values in {dict}
|
||||
virtcol({expr}) Number screen column of cursor or mark
|
||||
visualmode([expr]) String last visual mode used
|
||||
wait({timeout}, {condition}[, {interval}])
|
||||
Number Wait until {condition} is satisfied
|
||||
Number Wait until {condition} is satisfied
|
||||
wildmenumode() Number whether 'wildmenu' mode is active
|
||||
win_execute({id}, {command} [, {silent}])
|
||||
String execute {command} in window {id}
|
||||
|
@@ -93,6 +93,7 @@ REFERENCE MANUAL: These files explain every detail of Vim. *reference_toc*
|
||||
|
||||
General subjects ~
|
||||
|intro.txt| general introduction to Vim; notation used in help files
|
||||
|nvim.txt| Transitioning from Vim
|
||||
|help.txt| overview and quick reference (this file)
|
||||
|helphelp.txt| about using the help files
|
||||
|index.txt| alphabetical index of all commands
|
||||
@@ -133,17 +134,19 @@ Advanced editing ~
|
||||
|api.txt| Nvim API via RPC, Lua and VimL
|
||||
|
||||
Special issues ~
|
||||
|testing.txt| testing Vim and Vim scripts
|
||||
|print.txt| printing
|
||||
|remote.txt| using Vim as a server or client
|
||||
|testing.txt| testing Vim and Vim scripts
|
||||
|print.txt| printing
|
||||
|remote_plugin.txt| Nvim support for remote plugins
|
||||
|
||||
Programming language support ~
|
||||
|indent.txt| automatic indenting for C and other languages
|
||||
|lsp.txt| Language Server Protocol (LSP)
|
||||
|treesitter.txt| tree-sitter library for incremental parsing of buffers
|
||||
|diagnostic.txt| Diagnostic framework
|
||||
|syntax.txt| syntax highlighting
|
||||
|filetype.txt| settings done specifically for a type of file
|
||||
|quickfix.txt| commands for a quick edit-compile-fix cycle
|
||||
|provider.txt| Built-in remote plugin hosts
|
||||
|ft_ada.txt| Ada (the programming language) support
|
||||
|ft_ps1.txt| Filetype plugin for Windows PowerShell
|
||||
|ft_raku.txt| Filetype plugin for Raku
|
||||
@@ -164,6 +167,7 @@ GUI ~
|
||||
|
||||
Interfaces ~
|
||||
|if_cscop.txt| using Cscope with Vim
|
||||
|if_perl.txt| Perl interface
|
||||
|if_pyth.txt| Python interface
|
||||
|if_ruby.txt| Ruby interface
|
||||
|sign.txt| debugging signs
|
||||
@@ -171,6 +175,16 @@ Interfaces ~
|
||||
Versions ~
|
||||
|vim_diff.txt| Main differences between Nvim and Vim
|
||||
|vi_diff.txt| Main differences between Vim and Vi
|
||||
|deprecated.txt| Deprecated items that have been or will be removed
|
||||
|
||||
Other ~
|
||||
|terminal_emulator.txt| Terminal buffers
|
||||
|term.txt| Terminal UI
|
||||
|ui.txt| Nvim UI protocol
|
||||
|channel.txt| Nvim asynchronous IO
|
||||
|dev_style.txt| Nvim style guide
|
||||
|job_control.txt| Spawn and control multiple processes
|
||||
|
||||
*standard-plugin-list*
|
||||
Standard plugins ~
|
||||
|matchit.txt| Extended |%| matching
|
||||
|
@@ -354,6 +354,7 @@ tag char note action in Normal mode ~
|
||||
register x]
|
||||
|Y| ["x]Y yank N lines [into register x]; synonym for
|
||||
"yy"
|
||||
Note: Mapped to "y$" by default. |default-mappings|
|
||||
|ZZ| ZZ write if buffer changed and close window
|
||||
|ZQ| ZQ close window without writing
|
||||
|[| [{char} square bracket command (see |[| below)
|
||||
|
@@ -214,7 +214,7 @@ For |lsp-request|, each |lsp-handler| has this signature: >
|
||||
request, a table with information about the error
|
||||
is sent. Otherwise, it is `nil`. See |lsp-response|.
|
||||
{result} (Result | Params | nil)
|
||||
When the language server is able to succesfully
|
||||
When the language server is able to successfully
|
||||
complete a request, this contains the `result` key
|
||||
of the response. See |lsp-response|.
|
||||
{ctx} (table)
|
||||
@@ -236,7 +236,7 @@ For |lsp-request|, each |lsp-handler| has this signature: >
|
||||
{config} (table)
|
||||
Configuration for the handler.
|
||||
|
||||
Each handler can define it's own configuration
|
||||
Each handler can define its own configuration
|
||||
table that allows users to customize the behavior
|
||||
of a particular handler.
|
||||
|
||||
@@ -274,7 +274,7 @@ For |lsp-notification|, each |lsp-handler| has this signature: >
|
||||
{config} (table)
|
||||
Configuration for the handler.
|
||||
|
||||
Each handler can define it's own configuration
|
||||
Each handler can define its own configuration
|
||||
table that allows users to customize the behavior
|
||||
of a particular handler.
|
||||
|
||||
@@ -369,7 +369,7 @@ Handlers can be set by:
|
||||
For example: >
|
||||
|
||||
vim.lsp.start_client {
|
||||
..., -- Other configuration ommitted.
|
||||
..., -- Other configuration omitted.
|
||||
handlers = {
|
||||
["textDocument/definition"] = my_custom_server_definition
|
||||
},
|
||||
@@ -394,6 +394,9 @@ in the following order:
|
||||
2. Handler defined in |vim.lsp.start_client()|, if any.
|
||||
3. Handler defined in |vim.lsp.handlers|, if any.
|
||||
|
||||
*vim.lsp.log_levels*
|
||||
Log levels are defined in |vim.log.levels|
|
||||
|
||||
|
||||
VIM.LSP.PROTOCOL *vim.lsp.protocol*
|
||||
|
||||
@@ -444,7 +447,7 @@ LspCodeLens
|
||||
|nvim_buf_set_extmark()|.
|
||||
|
||||
LspCodeLensSeparator *hl-LspCodeLensSeparator*
|
||||
Used to color the seperator between two or more code lens.
|
||||
Used to color the separator between two or more code lens.
|
||||
|
||||
*lsp-highlight-signature*
|
||||
|
||||
@@ -485,6 +488,16 @@ buf_attach_client({bufnr}, {client_id}) *vim.lsp.buf_attach_client()*
|
||||
{bufnr} (number) Buffer handle, or 0 for current
|
||||
{client_id} (number) Client id
|
||||
|
||||
buf_detach_client({bufnr}, {client_id}) *vim.lsp.buf_detach_client()*
|
||||
Detaches client from the specified buffer. Note: While the
|
||||
server is notified that the text document (buffer) was closed,
|
||||
it is still able to send notifications should it ignore this
|
||||
notification.
|
||||
|
||||
Parameters: ~
|
||||
{bufnr} number Buffer handle, or 0 for current
|
||||
{client_id} number Client id
|
||||
|
||||
buf_get_clients({bufnr}) *vim.lsp.buf_get_clients()*
|
||||
Gets a map of client_id:client pairs for the given buffer,
|
||||
where each value is a |vim.lsp.client| object.
|
||||
@@ -630,6 +643,12 @@ client() *vim.lsp.client*
|
||||
server.
|
||||
• {handlers} (table): The handlers used by the client as
|
||||
described in |lsp-handler|.
|
||||
• {requests} (table): The current pending requests in flight
|
||||
to the server. Entries are key-value pairs with the key
|
||||
being the request ID while the value is a table with
|
||||
`type` , `bufnr` , and `method` key-value pairs. `type` is
|
||||
either "pending" for an active request, or "cancel" for a
|
||||
cancel request.
|
||||
• {config} (table): copy of the table that was passed by the
|
||||
user to |vim.lsp.start_client()|.
|
||||
• {server_capabilities} (table): Response from the server
|
||||
@@ -730,8 +749,8 @@ omnifunc({findstart}, {base}) *vim.lsp.omnifunc()*
|
||||
set_log_level({level}) *vim.lsp.set_log_level()*
|
||||
Sets the global log level for LSP logging.
|
||||
|
||||
Levels by name: "trace", "debug", "info", "warn", "error"
|
||||
Level numbers begin with "trace" at 0
|
||||
Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR"
|
||||
Level numbers begin with "TRACE" at 0
|
||||
|
||||
Use `lsp.log_levels` for reverse lookup.
|
||||
|
||||
@@ -819,10 +838,10 @@ start_client({config}) *vim.lsp.start_client()*
|
||||
throws an error. `code` is a number
|
||||
describing the error. Other arguments
|
||||
may be passed depending on the error
|
||||
kind. See |vim.lsp.client_errors| for
|
||||
possible errors. Use
|
||||
`vim.lsp.client_errors[code]` to get
|
||||
human-friendly name.
|
||||
kind. See |vim.lsp.rpc.client_errors|
|
||||
for possible errors. Use
|
||||
`vim.lsp.rpc.client_errors[code]` to
|
||||
get human-friendly name.
|
||||
{before_init} Callback with parameters
|
||||
(initialize_params, config) invoked
|
||||
before the LSP "initialize" phase,
|
||||
@@ -1005,11 +1024,12 @@ document_symbol() *vim.lsp.buf.document_symbol()*
|
||||
Lists all symbols in the current buffer in the quickfix
|
||||
window.
|
||||
|
||||
execute_command({command}) *vim.lsp.buf.execute_command()*
|
||||
execute_command({command_params}) *vim.lsp.buf.execute_command()*
|
||||
Executes an LSP server command.
|
||||
|
||||
Parameters: ~
|
||||
{command} A valid `ExecuteCommandParams` object
|
||||
{command_params} table A valid `ExecuteCommandParams`
|
||||
object
|
||||
|
||||
See also: ~
|
||||
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
|
||||
@@ -1285,7 +1305,7 @@ hover({_}, {result}, {ctx}, {config}) *vim.lsp.handlers.hover()*
|
||||
{config} table Configuration table.
|
||||
• border: (default=nil)
|
||||
• Add borders to the floating window
|
||||
• See |vim.api.nvim_open_win()|
|
||||
• See |nvim_open_win()|
|
||||
|
||||
*vim.lsp.handlers.signature_help()*
|
||||
signature_help({_}, {result}, {ctx}, {config})
|
||||
@@ -1326,12 +1346,14 @@ apply_text_document_edit({text_document_edit}, {index})
|
||||
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit
|
||||
|
||||
*vim.lsp.util.apply_text_edits()*
|
||||
apply_text_edits({text_edits}, {bufnr})
|
||||
apply_text_edits({text_edits}, {bufnr}, {offset_encoding})
|
||||
Applies a list of text edits to a buffer.
|
||||
|
||||
Parameters: ~
|
||||
{text_edits} table list of `TextEdit` objects
|
||||
{bufnr} number Buffer id
|
||||
{text_edits} table list of `TextEdit` objects
|
||||
{bufnr} number Buffer id
|
||||
{offset_encoding} string utf-8|utf-16|utf-32|nil defaults
|
||||
to encoding of first client of `bufnr`
|
||||
|
||||
See also: ~
|
||||
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit
|
||||
@@ -1358,37 +1380,30 @@ buf_highlight_references({bufnr}, {references}, {offset_encoding})
|
||||
{references} table List of `DocumentHighlight`
|
||||
objects to highlight
|
||||
{offset_encoding} string One of "utf-8", "utf-16",
|
||||
"utf-32", or nil. Defaults to utf-16
|
||||
"utf-32", or nil. Defaults to
|
||||
`offset_encoding` of first client of
|
||||
`bufnr`
|
||||
|
||||
See also: ~
|
||||
https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight
|
||||
|
||||
*vim.lsp.util.character_offset()*
|
||||
character_offset({bufnr}, {row}, {col})
|
||||
character_offset({buf}, {row}, {col}, {offset_encoding})
|
||||
Returns the UTF-32 and UTF-16 offsets for a position in a
|
||||
certain buffer.
|
||||
|
||||
Parameters: ~
|
||||
{buf} buffer id (0 for current)
|
||||
{row} 0-indexed line
|
||||
{col} 0-indexed byte offset in line
|
||||
{buf} buffer id (0 for current)
|
||||
{row} 0-indexed line
|
||||
{col} 0-indexed byte offset in line
|
||||
{offset_encoding} string utf-8|utf-16|utf-32|nil defaults
|
||||
to `offset_encoding` of first client of
|
||||
`buf`
|
||||
|
||||
Return: ~
|
||||
(number, number) UTF-32 and UTF-16 index of the character
|
||||
(number, number) `offset_encoding` index of the character
|
||||
in line {row} column {col} in buffer {buf}
|
||||
|
||||
*vim.lsp.util.close_preview_autocmd()*
|
||||
close_preview_autocmd({events}, {winnr})
|
||||
Creates autocommands to close a preview window when events
|
||||
happen.
|
||||
|
||||
Parameters: ~
|
||||
{events} (table) list of events
|
||||
{winnr} (number) window id of preview window
|
||||
|
||||
See also: ~
|
||||
|autocmd-events|
|
||||
|
||||
*vim.lsp.util.convert_input_to_markdown_lines()*
|
||||
convert_input_to_markdown_lines({input}, {contents})
|
||||
Converts any of `MarkedString` | `MarkedString[]` |
|
||||
@@ -1528,47 +1543,73 @@ make_formatting_params({options})
|
||||
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting
|
||||
|
||||
*vim.lsp.util.make_given_range_params()*
|
||||
make_given_range_params({start_pos}, {end_pos})
|
||||
make_given_range_params({start_pos}, {end_pos}, {bufnr}, {offset_encoding})
|
||||
Using the given range in the current buffer, creates an object
|
||||
that is similar to |vim.lsp.util.make_range_params()|.
|
||||
|
||||
Parameters: ~
|
||||
{start_pos} ({number, number}, optional) mark-indexed
|
||||
position. Defaults to the start of the last
|
||||
visual selection.
|
||||
{end_pos} ({number, number}, optional) mark-indexed
|
||||
position. Defaults to the end of the last
|
||||
visual selection.
|
||||
{start_pos} ({number, number}, optional)
|
||||
mark-indexed position. Defaults to the
|
||||
start of the last visual selection.
|
||||
{end_pos} ({number, number}, optional)
|
||||
mark-indexed position. Defaults to the
|
||||
end of the last visual selection.
|
||||
{bufnr} (optional, number): buffer handle or 0
|
||||
for current, defaults to current
|
||||
{offset_encoding} string utf-8|utf-16|utf-32|nil defaults
|
||||
to `offset_encoding` of first client of
|
||||
`bufnr`
|
||||
|
||||
Return: ~
|
||||
{ textDocument = { uri = `current_file_uri` }, range = {
|
||||
start = `start_position` , end = `end_position` } }
|
||||
|
||||
make_position_params() *vim.lsp.util.make_position_params()*
|
||||
*vim.lsp.util.make_position_params()*
|
||||
make_position_params({window}, {offset_encoding})
|
||||
Creates a `TextDocumentPositionParams` object for the current
|
||||
buffer and cursor position.
|
||||
|
||||
Parameters: ~
|
||||
{window} (optional, number): window handle or 0
|
||||
for current, defaults to current
|
||||
{offset_encoding} string utf-8|utf-16|utf-32|nil defaults
|
||||
to `offset_encoding` of first client of
|
||||
buffer of `window`
|
||||
|
||||
Return: ~
|
||||
`TextDocumentPositionParams` object
|
||||
|
||||
See also: ~
|
||||
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentPositionParams
|
||||
|
||||
make_range_params() *vim.lsp.util.make_range_params()*
|
||||
*vim.lsp.util.make_range_params()*
|
||||
make_range_params({window}, {offset_encoding})
|
||||
Using the current position in the current buffer, creates an
|
||||
object that can be used as a building block for several LSP
|
||||
requests, such as `textDocument/codeAction` ,
|
||||
`textDocument/colorPresentation` ,
|
||||
`textDocument/rangeFormatting` .
|
||||
|
||||
Parameters: ~
|
||||
{window} (optional, number): window handle or 0
|
||||
for current, defaults to current
|
||||
{offset_encoding} string utf-8|utf-16|utf-32|nil defaults
|
||||
to `offset_encoding` of first client of
|
||||
buffer of `window`
|
||||
|
||||
Return: ~
|
||||
{ textDocument = { uri = `current_file_uri` }, range = {
|
||||
start = `current_position` , end = `current_position` } }
|
||||
|
||||
make_text_document_params() *vim.lsp.util.make_text_document_params()*
|
||||
*vim.lsp.util.make_text_document_params()*
|
||||
make_text_document_params({bufnr})
|
||||
Creates a `TextDocumentIdentifier` object for the current
|
||||
buffer.
|
||||
|
||||
Parameters: ~
|
||||
{bufnr} (optional, number): Buffer handle, defaults to
|
||||
current
|
||||
|
||||
Return: ~
|
||||
`TextDocumentIdentifier`
|
||||
|
||||
@@ -1909,14 +1950,14 @@ make_client_capabilities()
|
||||
|
||||
*vim.lsp.protocol.resolve_capabilities()*
|
||||
resolve_capabilities({server_capabilities})
|
||||
`*` to match one or more characters in a path segment `?` to
|
||||
match on one character in a path segment `**` to match any
|
||||
number of path segments, including none `{}` to group
|
||||
conditions (e.g. `**/*.{ts,js}` matches all TypeScript and
|
||||
JavaScript files) `[]` to declare a range of characters to
|
||||
match in a path segment (e.g., `example.[0-9]` to match on
|
||||
`example.0` , `example.1` , …) `[!...]` to negate a range of
|
||||
characters to match in a path segment (e.g., `example.[!0-9]`
|
||||
to match on `example.a` , `example.b` , but not `example.0` )
|
||||
Creates a normalized object describing LSP server
|
||||
capabilities.
|
||||
|
||||
Parameters: ~
|
||||
{server_capabilities} table Table of capabilities
|
||||
supported by the server
|
||||
|
||||
Return: ~
|
||||
table Normalized table of capabilities
|
||||
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
||||
|
@@ -759,9 +759,9 @@ vim.stricmp({a}, {b}) *vim.stricmp()*
|
||||
respectively.
|
||||
|
||||
vim.str_utfindex({str}[, {index}]) *vim.str_utfindex()*
|
||||
Convert byte index to UTF-32 and UTF-16 indicies. If {index} is not
|
||||
supplied, the length of the string is used. All indicies are zero-based.
|
||||
Returns two values: the UTF-32 and UTF-16 indicies respectively.
|
||||
Convert byte index to UTF-32 and UTF-16 indices. If {index} is not
|
||||
supplied, the length of the string is used. All indices are zero-based.
|
||||
Returns two values: the UTF-32 and UTF-16 indices respectively.
|
||||
|
||||
Embedded NUL bytes are treated as terminating the string. Invalid
|
||||
UTF-8 bytes, and embedded surrogates are counted as one code
|
||||
@@ -881,6 +881,15 @@ vim.types *vim.types*
|
||||
`vim.types.dictionary` will not change or that `vim.types` table will
|
||||
only contain values for these three types.
|
||||
|
||||
*log_levels* *vim.log.levels*
|
||||
Log levels are one of the values defined in `vim.log.levels`:
|
||||
|
||||
vim.log.levels.DEBUG
|
||||
vim.log.levels.ERROR
|
||||
vim.log.levels.INFO
|
||||
vim.log.levels.TRACE
|
||||
vim.log.levels.WARN
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
LUA-VIMSCRIPT BRIDGE *lua-vimscript*
|
||||
|
||||
@@ -1197,19 +1206,32 @@ inspect({object}, {options}) *vim.inspect()*
|
||||
https://github.com/kikito/inspect.lua
|
||||
https://github.com/mpeterv/vinspect
|
||||
|
||||
notify({msg}, {log_level}, {opts}) *vim.notify()*
|
||||
Notification provider
|
||||
notify({msg}, {level}, {opts}) *vim.notify()*
|
||||
Display a notification to the user.
|
||||
|
||||
Without a runtime, writes to :Messages
|
||||
This function can be overridden by plugins to display
|
||||
notifications using a custom provider (such as the system
|
||||
notification provider). By default, writes to |:messages|.
|
||||
|
||||
Parameters: ~
|
||||
{msg} string Content of the notification to show to
|
||||
the user
|
||||
{log_level} number|nil enum from vim.log.levels
|
||||
{opts} table|nil additional options (timeout, etc)
|
||||
{msg} string Content of the notification to show to the
|
||||
user.
|
||||
{level} number|nil One of the values from
|
||||
|vim.log.levels|.
|
||||
{opts} table|nil Optional parameters. Unused by default.
|
||||
|
||||
See also: ~
|
||||
:help nvim_notify
|
||||
notify_once({msg}, {level}, {opts}) *vim.notify_once()*
|
||||
Display a notification only one time.
|
||||
|
||||
Like |vim.notify()|, but subsequent calls with the same
|
||||
message will not display a notification.
|
||||
|
||||
Parameters: ~
|
||||
{msg} string Content of the notification to show to the
|
||||
user.
|
||||
{level} number|nil One of the values from
|
||||
|vim.log.levels|.
|
||||
{opts} table|nil Optional parameters. Unused by default.
|
||||
|
||||
on_key({fn}, {ns_id}) *vim.on_key()*
|
||||
Adds Lua function {fn} with namespace id {ns_id} as a listener
|
||||
|
@@ -90,7 +90,7 @@ Mouse input has the following behavior:
|
||||
- If another window is clicked, terminal focus will be lost and nvim will jump
|
||||
to the clicked window
|
||||
- If the mouse wheel is used while the mouse is positioned in another window,
|
||||
the terminal wont lose focus and the hovered window will be scrolled.
|
||||
the terminal won't lose focus and the hovered window will be scrolled.
|
||||
|
||||
==============================================================================
|
||||
Configuration *terminal-config*
|
||||
@@ -426,7 +426,7 @@ When 'background' is "dark":
|
||||
hi debugBreakpoint term=reverse ctermbg=red guibg=red
|
||||
|
||||
|
||||
Shorcuts *termdebug_shortcuts*
|
||||
Shortcuts *termdebug_shortcuts*
|
||||
|
||||
You can define your own shortcuts (mappings) to control gdb, that can work in
|
||||
any window, using the TermDebugSendCommand() function. Example: >
|
||||
|
@@ -3226,10 +3226,14 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
'inccommand' 'icm' string (default "nosplit")
|
||||
global
|
||||
|
||||
"nosplit": Shows the effects of a command incrementally, as you type.
|
||||
"split" : Also shows partial off-screen results in a preview window.
|
||||
When nonempty, shows the effects of |:substitute|, |:smagic|, and
|
||||
|:snomagic| as you type.
|
||||
|
||||
Works for |:substitute|, |:smagic|, |:snomagic|. |hl-Substitute|
|
||||
Possible values:
|
||||
nosplit Shows the effects of a command incrementally in the
|
||||
buffer.
|
||||
split Like "nosplit", but also shows partial off-screen
|
||||
results in a preview window.
|
||||
|
||||
If the preview is too slow (exceeds 'redrawtime') then 'inccommand' is
|
||||
automatically disabled until |Command-line-mode| is done.
|
||||
|
@@ -356,6 +356,7 @@ In Insert or Command-line mode:
|
||||
|v_y| {visual}y yank the highlighted text into a register
|
||||
|yy| N yy yank N lines into a register
|
||||
|Y| N Y yank N lines into a register
|
||||
Note: Mapped to "y$" by default. |default-mappings|
|
||||
|p| N p put a register after the cursor position (N times)
|
||||
|P| N P put a register before the cursor position (N times)
|
||||
|]p| N ]p like p, but adjust indent to current line
|
||||
|
@@ -100,7 +100,7 @@ tsnode:prev_named_sibling() *tsnode:prev_named_sibling()*
|
||||
|
||||
tsnode:iter_children() *tsnode:iter_children()*
|
||||
Iterates over all the direct children of {tsnode}, regardless of
|
||||
wether they are named or not.
|
||||
whether they are named or not.
|
||||
Returns the child node plus the eventual field name corresponding to
|
||||
this child node.
|
||||
|
||||
@@ -155,9 +155,9 @@ tsnode:sexpr() *tsnode:sexpr()*
|
||||
Get an S-expression representing the node as a string.
|
||||
|
||||
tsnode:id() *tsnode:id()*
|
||||
Get an unique identier for the node inside its own tree.
|
||||
Get an unique identifier for the node inside its own tree.
|
||||
|
||||
No guarantees are made about this identifer's internal representation,
|
||||
No guarantees are made about this identifier's internal representation,
|
||||
except for being a primitive lua type with value equality (so not a table).
|
||||
Presently it is a (non-printable) string.
|
||||
|
||||
@@ -195,7 +195,7 @@ to a match.
|
||||
Treesitter Query Predicates *lua-treesitter-predicates*
|
||||
|
||||
When writing queries for treesitter, one might use `predicates`, that is,
|
||||
special scheme nodes that are evaluted to verify things on a captured node for
|
||||
special scheme nodes that are evaluated to verify things on a captured node for
|
||||
example, the |eq?| predicate : >
|
||||
((identifier) @foo (#eq? @foo "foo"))
|
||||
|
||||
@@ -203,7 +203,7 @@ This will only match identifier corresponding to the `"foo"` text.
|
||||
Here is a list of built-in predicates :
|
||||
|
||||
`eq?` *ts-predicate-eq?*
|
||||
This predicate will check text correspondance between nodes or
|
||||
This predicate will check text correspondence between nodes or
|
||||
strings : >
|
||||
((identifier) @foo (#eq? @foo "foo"))
|
||||
((node1) @left (node2) @right (#eq? @left @right))
|
||||
@@ -212,7 +212,7 @@ Here is a list of built-in predicates :
|
||||
`vim-match?` *ts-predicate-vim-match?*
|
||||
This will match if the provived vim regex matches the text
|
||||
corresponding to a node : >
|
||||
((idenfitier) @constant (#match? @constant "^[A-Z_]+$"))
|
||||
((identifier) @constant (#match? @constant "^[A-Z_]+$"))
|
||||
< Note: the `^` and `$` anchors will respectively match the
|
||||
start and end of the node's text.
|
||||
|
||||
@@ -267,7 +267,7 @@ Here is a list of built-in directives:
|
||||
`offset!` *ts-predicate-offset!*
|
||||
Takes the range of the captured node and applies the offsets
|
||||
to it's range : >
|
||||
((idenfitier) @constant (#offset! @constant 0 1 0 -1))
|
||||
((identifier) @constant (#offset! @constant 0 1 0 -1))
|
||||
< This will generate a range object for the captured node with the
|
||||
offsets applied. The arguments are
|
||||
`({capture_id}, {start_row}, {start_col}, {end_row}, {end_col}, {key?})`
|
||||
@@ -530,11 +530,9 @@ Query:iter_matches({self}, {node}, {source}, {start}, {stop})
|
||||
for id, node in pairs(match) do
|
||||
local name = query.captures[id]
|
||||
-- `node` was captured by the `name` capture in the match
|
||||
<
|
||||
>
|
||||
local node_data = metadata[id] -- Node level metadata
|
||||
<
|
||||
>
|
||||
|
||||
local node_data = metadata[id] -- Node level metadata
|
||||
|
||||
... use the info here ...
|
||||
end
|
||||
end
|
||||
|
@@ -349,15 +349,17 @@ Notice that "yw" includes the white space after a word. If you don't want
|
||||
this, use "ye".
|
||||
|
||||
The "yy" command yanks a whole line, just like "dd" deletes a whole line.
|
||||
Unexpectedly, while "D" deletes from the cursor to the end of the line, "Y"
|
||||
works like "yy", it yanks the whole line. Watch out for this inconsistency!
|
||||
Use "y$" to yank to the end of the line.
|
||||
|
||||
a text line yy a text line a text line
|
||||
line 2 line 2 p line 2
|
||||
last line last line a text line
|
||||
last line
|
||||
|
||||
"Y" was originally equivalent to "yank the entire line", as opposed to "D"
|
||||
which is "delete to end of the line". "Y" has thus been remapped to mean
|
||||
"yank to end of the line" to make it consistent with the behavior of "D".
|
||||
Mappings will be covered in later chapters.
|
||||
|
||||
==============================================================================
|
||||
*04.7* Using the clipboard
|
||||
|
||||
|
@@ -11,13 +11,12 @@ Vim's capabilities. Or define your own macros.
|
||||
|
||||
|05.1| The vimrc file
|
||||
|05.2| The example vimrc file explained
|
||||
|05.3| The defaults.vim file explained
|
||||
|05.4| Simple mappings
|
||||
|05.5| Adding a package
|
||||
|05.6| Adding a plugin
|
||||
|05.7| Adding a help file
|
||||
|05.8| The option window
|
||||
|05.9| Often used options
|
||||
|05.3| Simple mappings
|
||||
|05.4| Adding a package
|
||||
|05.5| Adding a plugin
|
||||
|05.6| Adding a help file
|
||||
|05.7| The option window
|
||||
|05.8| Often used options
|
||||
|
||||
Next chapter: |usr_06.txt| Using syntax highlighting
|
||||
Previous chapter: |usr_04.txt| Making small changes
|
||||
@@ -200,7 +199,7 @@ mapping. If set (default), this may break plugins (but it's backward
|
||||
compatible). See 'langremap'.
|
||||
|
||||
==============================================================================
|
||||
*05.4* Simple mappings
|
||||
*05.3* Simple mappings
|
||||
|
||||
A mapping enables you to bind a set of Vim commands to a single key. Suppose,
|
||||
for example, that you need to surround certain words with curly braces. In
|
||||
@@ -247,7 +246,7 @@ The ":map" command (with no arguments) lists your current mappings. At
|
||||
least the ones for Normal mode. More about mappings in section |40.1|.
|
||||
|
||||
==============================================================================
|
||||
*05.5* Adding a package *add-package* *vimball-install*
|
||||
*05.4* Adding a package *add-package* *vimball-install*
|
||||
|
||||
A package is a set of files that you can add to Vim. There are two kinds of
|
||||
packages: optional and automatically loaded on startup.
|
||||
@@ -287,7 +286,7 @@ an archive or as a repository. For an archive you can follow these steps:
|
||||
More information about packages can be found here: |packages|.
|
||||
|
||||
==============================================================================
|
||||
*05.6* Adding a plugin *add-plugin* *plugin*
|
||||
*05.5* Adding a plugin *add-plugin* *plugin*
|
||||
|
||||
Vim's functionality can be extended by adding plugins. A plugin is nothing
|
||||
more than a Vim script file that is loaded automatically when Vim starts. You
|
||||
@@ -423,7 +422,7 @@ Further reading:
|
||||
|new-filetype| How to detect a new file type.
|
||||
|
||||
==============================================================================
|
||||
*05.7* Adding a help file *add-local-help*
|
||||
*05.6* Adding a help file *add-local-help*
|
||||
|
||||
If you are lucky, the plugin you installed also comes with a help file. We
|
||||
will explain how to install the help file, so that you can easily find help
|
||||
@@ -456,7 +455,7 @@ them through the tag.
|
||||
For writing a local help file, see |write-local-help|.
|
||||
|
||||
==============================================================================
|
||||
*05.8* The option window
|
||||
*05.7* The option window
|
||||
|
||||
If you are looking for an option that does what you want, you can search in
|
||||
the help files here: |options|. Another way is by using this command: >
|
||||
@@ -495,7 +494,7 @@ border. This is what the 'scrolloff' option does, it specifies an offset
|
||||
from the window border where scrolling starts.
|
||||
|
||||
==============================================================================
|
||||
*05.9* Often used options
|
||||
*05.8* Often used options
|
||||
|
||||
There are an awful lot of options. Most of them you will hardly ever use.
|
||||
Some of the more useful ones will be mentioned here. Don't forget you can
|
||||
|
@@ -336,7 +336,7 @@ there. >
|
||||
|
||||
Of course you can use many other commands to yank the text. For example, to
|
||||
select whole lines start Visual mode with "V". Or use CTRL-V to select a
|
||||
rectangular block. Or use "Y" to yank a single line, "yaw" to yank-a-word,
|
||||
rectangular block. Or use "yy" to yank a single line, "yaw" to yank-a-word,
|
||||
etc.
|
||||
The "p" command puts the text after the cursor. Use "P" to put the text
|
||||
before the cursor. Notice that Vim remembers if you yanked a whole line or a
|
||||
@@ -359,7 +359,7 @@ the text should be placed in the f register. This must come just before the
|
||||
yank command.
|
||||
Now yank three whole lines to the l register (l for line): >
|
||||
|
||||
"l3Y
|
||||
"l3yy
|
||||
|
||||
The count could be before the "l just as well. To yank a block of text to the
|
||||
b (for block) register: >
|
||||
|
@@ -132,11 +132,11 @@ This works both with recording and with yank and delete commands. For
|
||||
example, you want to collect a sequence of lines into the a register. Yank
|
||||
the first line with: >
|
||||
|
||||
"aY
|
||||
"ayy
|
||||
|
||||
Now move to the second line, and type: >
|
||||
|
||||
"AY
|
||||
"Ayy
|
||||
|
||||
Repeat this command for all lines. The a register now contains all those
|
||||
lines, in the order you yanked them.
|
||||
|
@@ -99,13 +99,12 @@ Read this from start to end to learn the essential commands.
|
||||
|usr_05.txt| Set your settings
|
||||
|05.1| The vimrc file
|
||||
|05.2| The example vimrc file explained
|
||||
|05.3| The defaults.vim file explained
|
||||
|05.4| Simple mappings
|
||||
|05.5| Adding a package
|
||||
|05.6| Adding a plugin
|
||||
|05.7| Adding a help file
|
||||
|05.8| The option window
|
||||
|05.9| Often used options
|
||||
|05.3| Simple mappings
|
||||
|05.4| Adding a package
|
||||
|05.5| Adding a plugin
|
||||
|05.6| Adding a help file
|
||||
|05.7| The option window
|
||||
|05.8| Often used options
|
||||
|
||||
|usr_06.txt| Using syntax highlighting
|
||||
|06.1| Switching it on
|
||||
|
@@ -1080,7 +1080,9 @@ au BufNewFile,BufRead *.mmp setf mmp
|
||||
|
||||
" Modsim III (or LambdaProlog)
|
||||
au BufNewFile,BufRead *.mod
|
||||
\ if getline(1) =~ '\<module\>' |
|
||||
\ if expand("<afile>") =~ '\<go.mod$' |
|
||||
\ setf gomod |
|
||||
\ elseif getline(1) =~ '\<module\>' |
|
||||
\ setf lprolog |
|
||||
\ else |
|
||||
\ setf modsim3 |
|
||||
|
20
runtime/ftplugin/checkhealth.vim
Normal file
20
runtime/ftplugin/checkhealth.vim
Normal file
@@ -0,0 +1,20 @@
|
||||
" Vim filetype plugin
|
||||
" Language: Neovim checkhealth buffer
|
||||
" Last Change: 2021 Dec 15
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
endif
|
||||
|
||||
runtime! ftplugin/markdown.vim ftplugin/markdown_*.vim ftplugin/markdown/*.vim
|
||||
|
||||
setlocal wrap breakindent linebreak
|
||||
setlocal conceallevel=2 concealcursor=nc
|
||||
setlocal keywordprg=:help
|
||||
let &l:iskeyword='!-~,^*,^|,^",192-255'
|
||||
|
||||
if exists("b:undo_ftplugin")
|
||||
let b:undo_ftplugin .= "|setl wrap< bri< lbr< cole< cocu< kp< isk<"
|
||||
else
|
||||
let b:undo_ftplugin = "setl wrap< bri< lbr< cole< cocu< kp< isk<"
|
||||
endif
|
@@ -91,23 +91,22 @@ local function filter_by_severity(severity, diagnostics)
|
||||
end
|
||||
|
||||
---@private
|
||||
local function prefix_source(source, diagnostics)
|
||||
vim.validate { source = {source, function(v)
|
||||
return v == "always" or v == "if_many"
|
||||
end, "'always' or 'if_many'" } }
|
||||
|
||||
if source == "if_many" then
|
||||
local sources = {}
|
||||
for _, d in pairs(diagnostics) do
|
||||
if d.source then
|
||||
sources[d.source] = true
|
||||
local function count_sources(bufnr)
|
||||
local seen = {}
|
||||
local count = 0
|
||||
for _, namespace_diagnostics in pairs(diagnostic_cache[bufnr]) do
|
||||
for _, diagnostic in ipairs(namespace_diagnostics) do
|
||||
if diagnostic.source and not seen[diagnostic.source] then
|
||||
seen[diagnostic.source] = true
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
if #vim.tbl_keys(sources) <= 1 then
|
||||
return diagnostics
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
---@private
|
||||
local function prefix_source(diagnostics)
|
||||
return vim.tbl_map(function(d)
|
||||
if not d.source then
|
||||
return d
|
||||
@@ -272,6 +271,8 @@ end
|
||||
---@private
|
||||
local function set_diagnostic_cache(namespace, bufnr, diagnostics)
|
||||
for _, diagnostic in ipairs(diagnostics) do
|
||||
assert(diagnostic.lnum, "Diagnostic line number is required")
|
||||
assert(diagnostic.col, "Diagnostic column is required")
|
||||
diagnostic.severity = diagnostic.severity and to_severity(diagnostic.severity) or M.severity.ERROR
|
||||
diagnostic.end_lnum = diagnostic.end_lnum or diagnostic.lnum
|
||||
diagnostic.end_col = diagnostic.end_col or diagnostic.col
|
||||
@@ -297,11 +298,6 @@ local function restore_extmarks(bufnr, last)
|
||||
if not found[extmark[1]] then
|
||||
local opts = extmark[4]
|
||||
opts.id = extmark[1]
|
||||
-- HACK: end_row should be end_line
|
||||
if opts.end_row then
|
||||
opts.end_line = opts.end_row
|
||||
opts.end_row = nil
|
||||
end
|
||||
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, extmark[2], extmark[3], opts)
|
||||
end
|
||||
end
|
||||
@@ -386,7 +382,7 @@ local function get_diagnostics(bufnr, opts, clamp)
|
||||
if not opts.lnum or d.lnum == opts.lnum then
|
||||
if clamp and vim.api.nvim_buf_is_loaded(b) then
|
||||
local line_count = buf_line_count[b] - 1
|
||||
if (d.lnum > line_count or d.end_lnum > line_count) then
|
||||
if (d.lnum > line_count or d.end_lnum > line_count or d.lnum < 0 or d.end_lnum < 0) then
|
||||
d = vim.deepcopy(d)
|
||||
d.lnum = math.max(math.min(d.lnum, line_count), 0)
|
||||
d.end_lnum = math.max(math.min(d.end_lnum, line_count), 0)
|
||||
@@ -508,17 +504,20 @@ local function diagnostic_move_pos(opts, pos)
|
||||
return
|
||||
end
|
||||
|
||||
-- Save position in the window's jumplist
|
||||
vim.api.nvim_win_call(win_id, function() vim.cmd("normal! m'") end)
|
||||
|
||||
vim.api.nvim_win_set_cursor(win_id, {pos[1] + 1, pos[2]})
|
||||
vim.api.nvim_win_call(win_id, function()
|
||||
-- Save position in the window's jumplist
|
||||
vim.cmd("normal! m'")
|
||||
vim.api.nvim_win_set_cursor(win_id, {pos[1] + 1, pos[2]})
|
||||
-- Open folds under the cursor
|
||||
vim.cmd("normal! zv")
|
||||
end)
|
||||
|
||||
if float then
|
||||
local float_opts = type(float) == "table" and float or {}
|
||||
vim.schedule(function()
|
||||
M.open_float(
|
||||
vim.api.nvim_win_get_buf(win_id),
|
||||
vim.tbl_extend("keep", float_opts, {
|
||||
bufnr = vim.api.nvim_win_get_buf(win_id),
|
||||
scope = "cursor",
|
||||
focus = false,
|
||||
})
|
||||
@@ -557,11 +556,19 @@ end
|
||||
--- - underline: (default true) Use underline for diagnostics. Options:
|
||||
--- * severity: Only underline diagnostics matching the given severity
|
||||
--- |diagnostic-severity|
|
||||
--- - virtual_text: (default true) Use virtual text for diagnostics. Options:
|
||||
--- - virtual_text: (default true) Use virtual text for diagnostics. If multiple diagnostics
|
||||
--- are set for a namespace, one prefix per diagnostic + the last diagnostic
|
||||
--- message are shown.
|
||||
--- Options:
|
||||
--- * severity: Only show virtual text for diagnostics matching the given
|
||||
--- severity |diagnostic-severity|
|
||||
--- * source: (string) Include the diagnostic source in virtual
|
||||
--- text. One of "always" or "if_many".
|
||||
--- * source: (boolean or string) Include the diagnostic source in virtual
|
||||
--- text. Use "if_many" to only show sources if there is more than
|
||||
--- one diagnostic source in the buffer. Otherwise, any truthy value
|
||||
--- means to always show the diagnostic source.
|
||||
--- * spacing: (number) Amount of empty spaces inserted at the beginning
|
||||
--- of the virtual text.
|
||||
--- * prefix: (string) Prepend diagnostic message with prefix.
|
||||
--- * format: (function) A function that takes a diagnostic as input and
|
||||
--- returns a string. The return value is the text used to display
|
||||
--- the diagnostic. Example:
|
||||
@@ -653,9 +660,14 @@ function M.set(namespace, bufnr, diagnostics, opts)
|
||||
M.show(namespace, bufnr, nil, opts)
|
||||
end
|
||||
|
||||
vim.api.nvim_command(
|
||||
string.format("doautocmd <nomodeline> DiagnosticChanged %s", vim.api.nvim_buf_get_name(bufnr))
|
||||
)
|
||||
vim.api.nvim_buf_call(bufnr, function()
|
||||
vim.api.nvim_command(
|
||||
string.format(
|
||||
"doautocmd <nomodeline> DiagnosticChanged %s",
|
||||
vim.fn.fnameescape(vim.api.nvim_buf_get_name(bufnr))
|
||||
)
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
--- Get namespace metadata.
|
||||
@@ -920,8 +932,11 @@ M.handlers.virtual_text = {
|
||||
if opts.virtual_text.format then
|
||||
diagnostics = reformat_diagnostics(opts.virtual_text.format, diagnostics)
|
||||
end
|
||||
if opts.virtual_text.source then
|
||||
diagnostics = prefix_source(opts.virtual_text.source, diagnostics)
|
||||
if
|
||||
opts.virtual_text.source
|
||||
and (opts.virtual_text.source ~= "if_many" or count_sources(bufnr) > 1)
|
||||
then
|
||||
diagnostics = prefix_source(diagnostics)
|
||||
end
|
||||
if opts.virtual_text.severity then
|
||||
severity = opts.virtual_text.severity
|
||||
@@ -1127,12 +1142,15 @@ end
|
||||
|
||||
--- Show diagnostics in a floating window.
|
||||
---
|
||||
---@param bufnr number|nil Buffer number. Defaults to the current buffer.
|
||||
---@param opts table|nil Configuration table with the same keys as
|
||||
--- |vim.lsp.util.open_floating_preview()| in addition to the following:
|
||||
--- - bufnr: (number) Buffer number to show diagnostics from.
|
||||
--- Defaults to the current buffer.
|
||||
--- - namespace: (number) Limit diagnostics to the given namespace
|
||||
--- - scope: (string, default "line") Show diagnostics from the whole buffer ("buffer"),
|
||||
--- the current cursor line ("line"), or the current cursor position ("cursor").
|
||||
--- Shorthand versions are also accepted ("c" for "cursor", "l" for "line", "b"
|
||||
--- for "buffer").
|
||||
--- - pos: (number or table) If {scope} is "line" or "cursor", use this position rather
|
||||
--- than the cursor position. If a number, interpreted as a line number;
|
||||
--- otherwise, a (row, col) tuple.
|
||||
@@ -1143,8 +1161,11 @@ end
|
||||
--- - header: (string or table) String to use as the header for the floating window. If a
|
||||
--- table, it is interpreted as a [text, hl_group] tuple. Overrides the setting
|
||||
--- from |vim.diagnostic.config()|.
|
||||
--- - source: (string) Include the diagnostic source in the message. One of "always" or
|
||||
--- "if_many". Overrides the setting from |vim.diagnostic.config()|.
|
||||
--- - source: (boolean or string) Include the diagnostic source in the message.
|
||||
--- Use "if_many" to only show sources if there is more than one source of
|
||||
--- diagnostics in the buffer. Otherwise, any truthy value means to always show
|
||||
--- the diagnostic source. Overrides the setting from
|
||||
--- |vim.diagnostic.config()|.
|
||||
--- - format: (function) A function that takes a diagnostic as input and returns a
|
||||
--- string. The return value is the text used to display the diagnostic.
|
||||
--- Overrides the setting from |vim.diagnostic.config()|.
|
||||
@@ -1161,15 +1182,21 @@ end
|
||||
--- highlight.
|
||||
--- Overrides the setting from |vim.diagnostic.config()|.
|
||||
---@return tuple ({float_bufnr}, {win_id})
|
||||
function M.open_float(bufnr, opts)
|
||||
vim.validate {
|
||||
bufnr = { bufnr, 'n', true },
|
||||
opts = { opts, 't', true },
|
||||
}
|
||||
function M.open_float(opts, ...)
|
||||
-- Support old (bufnr, opts) signature
|
||||
local bufnr
|
||||
if opts == nil or type(opts) == "number" then
|
||||
bufnr = opts
|
||||
opts = ...
|
||||
else
|
||||
vim.validate {
|
||||
opts = { opts, 't', true },
|
||||
}
|
||||
end
|
||||
|
||||
opts = opts or {}
|
||||
bufnr = get_bufnr(bufnr)
|
||||
local scope = opts.scope or "line"
|
||||
bufnr = get_bufnr(bufnr or opts.bufnr)
|
||||
local scope = ({l = "line", c = "cursor", b = "buffer"})[opts.scope] or opts.scope or "line"
|
||||
local lnum, col
|
||||
if scope == "line" or scope == "cursor" then
|
||||
if not opts.pos then
|
||||
@@ -1250,8 +1277,8 @@ function M.open_float(bufnr, opts)
|
||||
diagnostics = reformat_diagnostics(opts.format, diagnostics)
|
||||
end
|
||||
|
||||
if opts.source then
|
||||
diagnostics = prefix_source(opts.source, diagnostics)
|
||||
if opts.source and (opts.source ~= "if_many" or count_sources(bufnr) > 1) then
|
||||
diagnostics = prefix_source(diagnostics)
|
||||
end
|
||||
|
||||
local prefix_opt = if_nil(opts.prefix, (scope == "cursor" and #diagnostics <= 1) and "" or function(_, i)
|
||||
@@ -1327,9 +1354,14 @@ function M.reset(namespace, bufnr)
|
||||
end
|
||||
end
|
||||
|
||||
vim.api.nvim_command(
|
||||
string.format("doautocmd <nomodeline> DiagnosticChanged %s", vim.api.nvim_buf_get_name(bufnr))
|
||||
)
|
||||
vim.api.nvim_buf_call(bufnr, function()
|
||||
vim.api.nvim_command(
|
||||
string.format(
|
||||
"doautocmd <nomodeline> DiagnosticChanged %s",
|
||||
vim.fn.fnameescape(vim.api.nvim_buf_get_name(bufnr))
|
||||
)
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
--- Add all diagnostics to the quickfix list.
|
||||
|
@@ -290,7 +290,7 @@ end
|
||||
--- Memoizes a function. On first run, the function return value is saved and
|
||||
--- immediately returned on subsequent runs. If the function returns a multival,
|
||||
--- only the first returned value will be memoized and returned. The function will only be run once,
|
||||
--- even if it has side-effects.
|
||||
--- even if it has side effects.
|
||||
---
|
||||
---@param fn (function) Function to run
|
||||
---@returns (function) Memoized function
|
||||
@@ -489,7 +489,8 @@ local function text_document_did_open_handler(bufnr, client)
|
||||
-- Protect against a race where the buffer disappears
|
||||
-- between `did_open_handler` and the scheduled function firing.
|
||||
if vim.api.nvim_buf_is_valid(bufnr) then
|
||||
vim.lsp.diagnostic.redraw(bufnr, client.id)
|
||||
local namespace = vim.lsp.diagnostic.get_namespace(client.id)
|
||||
vim.diagnostic.show(namespace, bufnr)
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -559,6 +560,12 @@ end
|
||||
---
|
||||
--- - {handlers} (table): The handlers used by the client as described in |lsp-handler|.
|
||||
---
|
||||
--- - {requests} (table): The current pending requests in flight
|
||||
--- to the server. Entries are key-value pairs with the key
|
||||
--- being the request ID while the value is a table with `type`,
|
||||
--- `bufnr`, and `method` key-value pairs. `type` is either "pending"
|
||||
--- for an active request, or "cancel" for a cancel request.
|
||||
---
|
||||
--- - {config} (table): copy of the table that was passed by the user
|
||||
--- to |vim.lsp.start_client()|.
|
||||
---
|
||||
@@ -638,8 +645,8 @@ end
|
||||
---@param on_error Callback with parameters (code, ...), invoked
|
||||
--- when the client operation throws an error. `code` is a number describing
|
||||
--- the error. Other arguments may be passed depending on the error kind. See
|
||||
--- |vim.lsp.client_errors| for possible errors.
|
||||
--- Use `vim.lsp.client_errors[code]` to get human-friendly name.
|
||||
--- |vim.lsp.rpc.client_errors| for possible errors.
|
||||
--- Use `vim.lsp.rpc.client_errors[code]` to get human-friendly name.
|
||||
---
|
||||
---@param before_init Callback with parameters (initialize_params, config)
|
||||
--- invoked before the LSP "initialize" phase, where `params` contains the
|
||||
@@ -750,8 +757,8 @@ function lsp.start_client(config)
|
||||
---
|
||||
---@param code (number) Error code
|
||||
---@param err (...) Other arguments may be passed depending on the error kind
|
||||
---@see |vim.lsp.client_errors| for possible errors. Use
|
||||
---`vim.lsp.client_errors[code]` to get a human-friendly name.
|
||||
---@see |vim.lsp.rpc.client_errors| for possible errors. Use
|
||||
---`vim.lsp.rpc.client_errors[code]` to get a human-friendly name.
|
||||
function dispatch.on_error(code, err)
|
||||
local _ = log.error() and log.error(log_prefix, "on_error", { code = lsp.client_errors[code], err = err })
|
||||
err_message(log_prefix, ': Error ', lsp.client_errors[code], ': ', vim.inspect(err))
|
||||
@@ -770,6 +777,10 @@ function lsp.start_client(config)
|
||||
---@param code (number) exit code of the process
|
||||
---@param signal (number) the signal used to terminate (if any)
|
||||
function dispatch.on_exit(code, signal)
|
||||
if config.on_exit then
|
||||
pcall(config.on_exit, code, signal, client_id)
|
||||
end
|
||||
|
||||
active_clients[client_id] = nil
|
||||
uninitialized_clients[client_id] = nil
|
||||
|
||||
@@ -785,10 +796,6 @@ function lsp.start_client(config)
|
||||
vim.notify(msg, vim.log.levels.WARN)
|
||||
end)
|
||||
end
|
||||
|
||||
if config.on_exit then
|
||||
pcall(config.on_exit, code, signal, client_id)
|
||||
end
|
||||
end
|
||||
|
||||
-- Start the RPC client.
|
||||
@@ -1105,9 +1112,9 @@ local text_document_did_change_handler
|
||||
do
|
||||
text_document_did_change_handler = function(_, bufnr, changedtick, firstline, lastline, new_lastline)
|
||||
|
||||
-- Don't do anything if there are no clients attached.
|
||||
-- Detach (nvim_buf_attach) via returning True to on_lines if no clients are attached
|
||||
if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then
|
||||
return
|
||||
return true
|
||||
end
|
||||
util.buf_versions[bufnr] = changedtick
|
||||
local compute_change_and_notify = changetracking.prepare(bufnr, firstline, lastline, new_lastline)
|
||||
@@ -1124,7 +1131,7 @@ function lsp._text_document_did_save_handler(bufnr)
|
||||
if client.resolved_capabilities.text_document_save then
|
||||
local included_text
|
||||
if client.resolved_capabilities.text_document_save_include_text then
|
||||
included_text = text()
|
||||
included_text = text(bufnr)
|
||||
end
|
||||
client.notify('textDocument/didSave', {
|
||||
textDocument = {
|
||||
@@ -1149,6 +1156,12 @@ function lsp.buf_attach_client(bufnr, client_id)
|
||||
client_id = {client_id, 'n'};
|
||||
}
|
||||
bufnr = resolve_bufnr(bufnr)
|
||||
if not vim.api.nvim_buf_is_loaded(bufnr) then
|
||||
local _ = log.warn() and log.warn(
|
||||
string.format("buf_attach_client called on unloaded buffer (id: %d): ", bufnr)
|
||||
)
|
||||
return false
|
||||
end
|
||||
local buffer_client_ids = all_buffer_active_clients[bufnr]
|
||||
-- This is our first time attaching to this buffer.
|
||||
if not buffer_client_ids then
|
||||
@@ -1207,6 +1220,50 @@ function lsp.buf_attach_client(bufnr, client_id)
|
||||
return true
|
||||
end
|
||||
|
||||
--- Detaches client from the specified buffer.
|
||||
--- Note: While the server is notified that the text document (buffer)
|
||||
--- was closed, it is still able to send notifications should it ignore this notification.
|
||||
---
|
||||
---@param bufnr number Buffer handle, or 0 for current
|
||||
---@param client_id number Client id
|
||||
function lsp.buf_detach_client(bufnr, client_id)
|
||||
validate {
|
||||
bufnr = {bufnr, 'n', true};
|
||||
client_id = {client_id, 'n'};
|
||||
}
|
||||
bufnr = resolve_bufnr(bufnr)
|
||||
|
||||
local client = lsp.get_client_by_id(client_id)
|
||||
if not client or not client.attached_buffers[bufnr] then
|
||||
vim.notify(
|
||||
string.format('Buffer (id: %d) is not attached to client (id: %d). Cannot detach.', client_id, bufnr)
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
changetracking.reset_buf(client, bufnr)
|
||||
|
||||
if client.resolved_capabilities.text_document_open_close then
|
||||
local uri = vim.uri_from_bufnr(bufnr)
|
||||
local params = { textDocument = { uri = uri; } }
|
||||
client.notify('textDocument/didClose', params)
|
||||
end
|
||||
|
||||
client.attached_buffers[bufnr] = nil
|
||||
util.buf_versions[bufnr] = nil
|
||||
|
||||
all_buffer_active_clients[bufnr][client_id] = nil
|
||||
if #vim.tbl_keys(all_buffer_active_clients[bufnr]) == 0 then
|
||||
all_buffer_active_clients[bufnr] = nil
|
||||
end
|
||||
|
||||
local namespace = vim.lsp.diagnostic.get_namespace(client_id)
|
||||
vim.diagnostic.reset(namespace, bufnr)
|
||||
|
||||
vim.notify(string.format('Detached buffer (id: %d) from client (id: %d)', bufnr, client_id))
|
||||
|
||||
end
|
||||
|
||||
--- Checks if a buffer is attached for a particular client.
|
||||
---
|
||||
---@param bufnr (number) Buffer handle, or 0 for current
|
||||
@@ -1486,11 +1543,7 @@ local function adjust_start_col(lnum, line, items, encoding)
|
||||
end
|
||||
end
|
||||
if min_start_char then
|
||||
if encoding == 'utf-8' then
|
||||
return min_start_char
|
||||
else
|
||||
return vim.str_byteindex(line, min_start_char, encoding == 'utf-16')
|
||||
end
|
||||
return util._str_byteindex_enc(line, min_start_char, encoding)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
@@ -1655,14 +1708,14 @@ end
|
||||
--
|
||||
-- Can be used to lookup the number from the name or the
|
||||
-- name from the number.
|
||||
-- Levels by name: "trace", "debug", "info", "warn", "error"
|
||||
-- Level numbers begin with "trace" at 0
|
||||
-- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR"
|
||||
-- Level numbers begin with "TRACE" at 0
|
||||
lsp.log_levels = log.levels
|
||||
|
||||
--- Sets the global log level for LSP logging.
|
||||
---
|
||||
--- Levels by name: "trace", "debug", "info", "warn", "error"
|
||||
--- Level numbers begin with "trace" at 0
|
||||
--- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR"
|
||||
--- Level numbers begin with "TRACE" at 0
|
||||
---
|
||||
--- Use `lsp.log_levels` for reverse lookup.
|
||||
---
|
||||
|
@@ -116,31 +116,30 @@ end
|
||||
--- asks the user to select one.
|
||||
--
|
||||
---@returns The client that the user selected or nil
|
||||
local function select_client(method)
|
||||
local clients = vim.tbl_values(vim.lsp.buf_get_clients());
|
||||
clients = vim.tbl_filter(function (client)
|
||||
local function select_client(method, on_choice)
|
||||
validate {
|
||||
on_choice = { on_choice, 'function', false },
|
||||
}
|
||||
local clients = vim.tbl_values(vim.lsp.buf_get_clients())
|
||||
clients = vim.tbl_filter(function(client)
|
||||
return client.supports_method(method)
|
||||
end, clients)
|
||||
-- better UX when choices are always in the same order (between restarts)
|
||||
table.sort(clients, function (a, b) return a.name < b.name end)
|
||||
table.sort(clients, function(a, b)
|
||||
return a.name < b.name
|
||||
end)
|
||||
|
||||
if #clients > 1 then
|
||||
local choices = {}
|
||||
for k,v in pairs(clients) do
|
||||
table.insert(choices, string.format("%d %s", k, v.name))
|
||||
end
|
||||
local user_choice = vim.fn.confirm(
|
||||
"Select a language server:",
|
||||
table.concat(choices, "\n"),
|
||||
0,
|
||||
"Question"
|
||||
)
|
||||
if user_choice == 0 then return nil end
|
||||
return clients[user_choice]
|
||||
vim.ui.select(clients, {
|
||||
prompt = 'Select a language server:',
|
||||
format_item = function(client)
|
||||
return client.name
|
||||
end,
|
||||
}, on_choice)
|
||||
elseif #clients < 1 then
|
||||
return nil
|
||||
on_choice(nil)
|
||||
else
|
||||
return clients[1]
|
||||
on_choice(clients[1])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -152,11 +151,15 @@ end
|
||||
--
|
||||
---@see https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting
|
||||
function M.formatting(options)
|
||||
local client = select_client("textDocument/formatting")
|
||||
if client == nil then return end
|
||||
|
||||
local params = util.make_formatting_params(options)
|
||||
return client.request("textDocument/formatting", params, nil, vim.api.nvim_get_current_buf())
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
select_client('textDocument/formatting', function(client)
|
||||
if client == nil then
|
||||
return
|
||||
end
|
||||
|
||||
return client.request('textDocument/formatting', params, nil, bufnr)
|
||||
end)
|
||||
end
|
||||
|
||||
--- Performs |vim.lsp.buf.formatting()| synchronously.
|
||||
@@ -172,17 +175,20 @@ end
|
||||
---@param timeout_ms (number) Request timeout
|
||||
---@see |vim.lsp.buf.formatting_seq_sync|
|
||||
function M.formatting_sync(options, timeout_ms)
|
||||
local client = select_client("textDocument/formatting")
|
||||
if client == nil then return end
|
||||
|
||||
local params = util.make_formatting_params(options)
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local result, err = client.request_sync("textDocument/formatting", params, timeout_ms, bufnr)
|
||||
if result and result.result then
|
||||
util.apply_text_edits(result.result, bufnr)
|
||||
elseif err then
|
||||
vim.notify("vim.lsp.buf.formatting_sync: " .. err, vim.log.levels.WARN)
|
||||
end
|
||||
select_client('textDocument/formatting', function(client)
|
||||
if client == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local result, err = client.request_sync('textDocument/formatting', params, timeout_ms, bufnr)
|
||||
if result and result.result then
|
||||
util.apply_text_edits(result.result, bufnr)
|
||||
elseif err then
|
||||
vim.notify('vim.lsp.buf.formatting_sync: ' .. err, vim.log.levels.WARN)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- Formats the current buffer by sequentially requesting formatting from attached clients.
|
||||
@@ -238,12 +244,15 @@ end
|
||||
---@param end_pos ({number, number}, optional) mark-indexed position.
|
||||
---Defaults to the end of the last visual selection.
|
||||
function M.range_formatting(options, start_pos, end_pos)
|
||||
local client = select_client("textDocument/rangeFormatting")
|
||||
if client == nil then return end
|
||||
|
||||
local params = util.make_given_range_params(start_pos, end_pos)
|
||||
params.options = util.make_formatting_params(options).options
|
||||
return client.request("textDocument/rangeFormatting", params)
|
||||
select_client('textDocument/rangeFormatting', function(client)
|
||||
if client == nil then
|
||||
return
|
||||
end
|
||||
|
||||
return client.request('textDocument/rangeFormatting', params)
|
||||
end)
|
||||
end
|
||||
|
||||
--- Renames all references to the symbol under the cursor.
|
||||
@@ -618,14 +627,19 @@ end
|
||||
|
||||
--- Executes an LSP server command.
|
||||
---
|
||||
---@param command A valid `ExecuteCommandParams` object
|
||||
---@param command_params table A valid `ExecuteCommandParams` object
|
||||
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
|
||||
function M.execute_command(command)
|
||||
function M.execute_command(command_params)
|
||||
validate {
|
||||
command = { command.command, 's' },
|
||||
arguments = { command.arguments, 't', true }
|
||||
command = { command_params.command, 's' },
|
||||
arguments = { command_params.arguments, 't', true }
|
||||
}
|
||||
request('workspace/executeCommand', command)
|
||||
command_params = {
|
||||
command=command_params.command,
|
||||
arguments=command_params.arguments,
|
||||
workDoneToken=command_params.workDoneToken,
|
||||
}
|
||||
request('workspace/executeCommand', command_params )
|
||||
end
|
||||
|
||||
return M
|
||||
|
@@ -153,19 +153,6 @@ function M.get_namespace(client_id)
|
||||
return _client_namespaces[client_id]
|
||||
end
|
||||
|
||||
--- Save diagnostics to the current buffer.
|
||||
---
|
||||
--- Handles saving diagnostics from multiple clients in the same buffer.
|
||||
---@param diagnostics Diagnostic[]
|
||||
---@param bufnr number
|
||||
---@param client_id number
|
||||
---@private
|
||||
function M.save(diagnostics, bufnr, client_id)
|
||||
local namespace = M.get_namespace(client_id)
|
||||
vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id))
|
||||
end
|
||||
-- }}}
|
||||
|
||||
--- |lsp-handler| for the method "textDocument/publishDiagnostics"
|
||||
---
|
||||
--- See |vim.diagnostic.config()| for configuration options. Handler-specific
|
||||
@@ -245,6 +232,23 @@ end
|
||||
|
||||
-- Deprecated Functions {{{
|
||||
|
||||
|
||||
--- Save diagnostics to the current buffer.
|
||||
---
|
||||
---@deprecated Prefer |vim.diagnostic.set()|
|
||||
---
|
||||
--- Handles saving diagnostics from multiple clients in the same buffer.
|
||||
---@param diagnostics Diagnostic[]
|
||||
---@param bufnr number
|
||||
---@param client_id number
|
||||
---@private
|
||||
function M.save(diagnostics, bufnr, client_id)
|
||||
vim.notify_once('vim.lsp.diagnostic.save is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
local namespace = M.get_namespace(client_id)
|
||||
vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id))
|
||||
end
|
||||
-- }}}
|
||||
|
||||
--- Get all diagnostics for clients
|
||||
---
|
||||
---@deprecated Prefer |vim.diagnostic.get()|
|
||||
@@ -253,6 +257,7 @@ end
|
||||
--- If nil, diagnostics of all clients are included.
|
||||
---@return table with diagnostics grouped by bufnr (bufnr: Diagnostic[])
|
||||
function M.get_all(client_id)
|
||||
vim.notify_once('vim.lsp.diagnostic.get_all is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
local result = {}
|
||||
local namespace
|
||||
if client_id then
|
||||
@@ -274,6 +279,7 @@ end
|
||||
--- Else, return just the diagnostics associated with the client_id.
|
||||
---@param predicate function|nil Optional function for filtering diagnostics
|
||||
function M.get(bufnr, client_id, predicate)
|
||||
vim.notify_once('vim.lsp.diagnostic.get is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
predicate = predicate or function() return true end
|
||||
if client_id == nil then
|
||||
local all_diagnostics = {}
|
||||
@@ -335,6 +341,7 @@ end
|
||||
---@param severity DiagnosticSeverity
|
||||
---@param client_id number the client id
|
||||
function M.get_count(bufnr, severity, client_id)
|
||||
vim.notify_once('vim.lsp.diagnostic.get_count is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
severity = severity_lsp_to_vim(severity)
|
||||
local opts = { severity = severity }
|
||||
if client_id ~= nil then
|
||||
@@ -351,6 +358,7 @@ end
|
||||
---@param opts table See |vim.lsp.diagnostic.goto_next()|
|
||||
---@return table Previous diagnostic
|
||||
function M.get_prev(opts)
|
||||
vim.notify_once('vim.lsp.diagnostic.get_prev is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
if opts then
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@@ -368,6 +376,7 @@ end
|
||||
---@param opts table See |vim.lsp.diagnostic.goto_next()|
|
||||
---@return table Previous diagnostic position
|
||||
function M.get_prev_pos(opts)
|
||||
vim.notify_once('vim.lsp.diagnostic.get_prev_pos is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
if opts then
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@@ -384,6 +393,7 @@ end
|
||||
---
|
||||
---@param opts table See |vim.lsp.diagnostic.goto_next()|
|
||||
function M.goto_prev(opts)
|
||||
vim.notify_once('vim.lsp.diagnostic.goto_prev is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
if opts then
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@@ -401,6 +411,7 @@ end
|
||||
---@param opts table See |vim.lsp.diagnostic.goto_next()|
|
||||
---@return table Next diagnostic
|
||||
function M.get_next(opts)
|
||||
vim.notify_once('vim.lsp.diagnostic.get_next is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
if opts then
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@@ -418,6 +429,7 @@ end
|
||||
---@param opts table See |vim.lsp.diagnostic.goto_next()|
|
||||
---@return table Next diagnostic position
|
||||
function M.get_next_pos(opts)
|
||||
vim.notify_once('vim.lsp.diagnostic.get_next_pos is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
if opts then
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@@ -432,6 +444,7 @@ end
|
||||
---
|
||||
---@deprecated Prefer |vim.diagnostic.goto_next()|
|
||||
function M.goto_next(opts)
|
||||
vim.notify_once('vim.lsp.diagnostic.goto_next is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
if opts then
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@@ -455,6 +468,7 @@ end
|
||||
--- - severity_limit (DiagnosticSeverity):
|
||||
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
|
||||
function M.set_signs(diagnostics, bufnr, client_id, _, opts)
|
||||
vim.notify_once('vim.lsp.diagnostic.set_signs is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
local namespace = M.get_namespace(client_id)
|
||||
if opts and not opts.severity and opts.severity_limit then
|
||||
opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
|
||||
@@ -475,6 +489,7 @@ end
|
||||
--- - severity_limit (DiagnosticSeverity):
|
||||
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
|
||||
function M.set_underline(diagnostics, bufnr, client_id, _, opts)
|
||||
vim.notify_once('vim.lsp.diagnostic.set_underline is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
local namespace = M.get_namespace(client_id)
|
||||
if opts and not opts.severity and opts.severity_limit then
|
||||
opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
|
||||
@@ -496,6 +511,7 @@ end
|
||||
--- - severity_limit (DiagnosticSeverity):
|
||||
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
|
||||
function M.set_virtual_text(diagnostics, bufnr, client_id, _, opts)
|
||||
vim.notify_once('vim.lsp.diagnostic.set_virtual_text is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
local namespace = M.get_namespace(client_id)
|
||||
if opts and not opts.severity and opts.severity_limit then
|
||||
opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
|
||||
@@ -514,6 +530,7 @@ end
|
||||
---@return an array of [text, hl_group] arrays. This can be passed directly to
|
||||
--- the {virt_text} option of |nvim_buf_set_extmark()|.
|
||||
function M.get_virtual_text_chunks_for_line(bufnr, _, line_diags, opts)
|
||||
vim.notify_once('vim.lsp.diagnostic.get_virtual_text_chunks_for_line is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
return vim.diagnostic._get_virt_text_chunks(diagnostic_lsp_to_vim(line_diags, bufnr), opts)
|
||||
end
|
||||
|
||||
@@ -531,6 +548,7 @@ end
|
||||
---@param position table|nil The (0,0)-indexed position
|
||||
---@return table {popup_bufnr, win_id}
|
||||
function M.show_position_diagnostics(opts, buf_nr, position)
|
||||
vim.notify_once('vim.lsp.diagnostic.show_position_diagnostics is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
opts = opts or {}
|
||||
opts.scope = "cursor"
|
||||
opts.pos = position
|
||||
@@ -554,6 +572,7 @@ end
|
||||
---@param client_id number|nil the client id
|
||||
---@return table {popup_bufnr, win_id}
|
||||
function M.show_line_diagnostics(opts, buf_nr, line_nr, client_id)
|
||||
vim.notify_once('vim.lsp.diagnostic.show_line_diagnostics is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
opts = opts or {}
|
||||
opts.scope = "line"
|
||||
opts.pos = line_nr
|
||||
@@ -565,7 +584,7 @@ end
|
||||
|
||||
--- Redraw diagnostics for the given buffer and client
|
||||
---
|
||||
---@deprecated Prefer |vim.diagnostic.redraw()|
|
||||
---@deprecated Prefer |vim.diagnostic.show()|
|
||||
---
|
||||
--- This calls the "textDocument/publishDiagnostics" handler manually using
|
||||
--- the cached diagnostics already received from the server. This can be useful
|
||||
@@ -577,6 +596,7 @@ end
|
||||
--- client. The default is to redraw diagnostics for all attached
|
||||
--- clients.
|
||||
function M.redraw(bufnr, client_id)
|
||||
vim.notify_once('vim.lsp.diagnostic.redraw is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
bufnr = get_bufnr(bufnr)
|
||||
if not client_id then
|
||||
return vim.lsp.for_each_buffer_client(bufnr, function(client)
|
||||
@@ -604,6 +624,7 @@ end
|
||||
--- - {workspace}: (boolean, default true)
|
||||
--- - Set the list with workspace diagnostics
|
||||
function M.set_qflist(opts)
|
||||
vim.notify_once('vim.lsp.diagnostic.set_qflist is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
opts = opts or {}
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@@ -635,6 +656,7 @@ end
|
||||
--- - {workspace}: (boolean, default false)
|
||||
--- - Set the list with workspace diagnostics
|
||||
function M.set_loclist(opts)
|
||||
vim.notify_once('vim.lsp.diagnostic.set_loclist is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
opts = opts or {}
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@@ -662,6 +684,7 @@ end
|
||||
-- send diagnostic information and the client will still process it. The
|
||||
-- diagnostics are simply not displayed to the user.
|
||||
function M.disable(bufnr, client_id)
|
||||
vim.notify_once('vim.lsp.diagnostic.disable is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
if not client_id then
|
||||
return vim.lsp.for_each_buffer_client(bufnr, function(client)
|
||||
M.disable(bufnr, client.id)
|
||||
@@ -682,6 +705,7 @@ end
|
||||
--- client. The default is to enable diagnostics for all attached
|
||||
--- clients.
|
||||
function M.enable(bufnr, client_id)
|
||||
vim.notify_once('vim.lsp.diagnostic.enable is deprecated. See :h deprecated', vim.log.levels.WARN)
|
||||
if not client_id then
|
||||
return vim.lsp.for_each_buffer_client(bufnr, function(client)
|
||||
M.enable(bufnr, client.id)
|
||||
|
@@ -28,7 +28,7 @@ local function progress_handler(_, result, ctx, _)
|
||||
local client_name = client and client.name or string.format("id=%d", client_id)
|
||||
if not client then
|
||||
err_message("LSP[", client_name, "] client has shut down after sending the message")
|
||||
return
|
||||
return vim.NIL
|
||||
end
|
||||
local val = result.value -- unspecified yet
|
||||
local token = result.token -- string or number
|
||||
@@ -70,7 +70,7 @@ M['window/workDoneProgress/create'] = function(_, result, ctx)
|
||||
local client_name = client and client.name or string.format("id=%d", client_id)
|
||||
if not client then
|
||||
err_message("LSP[", client_name, "] client has shut down after sending the message")
|
||||
return
|
||||
return vim.NIL
|
||||
end
|
||||
client.messages.progress[token] = {}
|
||||
return vim.NIL
|
||||
@@ -246,7 +246,7 @@ end
|
||||
---@param config table Configuration table.
|
||||
--- - border: (default=nil)
|
||||
--- - Add borders to the floating window
|
||||
--- - See |vim.api.nvim_open_win()|
|
||||
--- - See |nvim_open_win()|
|
||||
function M.hover(_, result, ctx, config)
|
||||
config = config or {}
|
||||
config.focus_id = ctx.method
|
||||
@@ -285,7 +285,7 @@ local function location_handler(_, result, ctx, _)
|
||||
util.jump_to_location(result[1])
|
||||
|
||||
if #result > 1 then
|
||||
util.set_qflist(util.locations_to_items(result))
|
||||
vim.fn.setqflist({}, ' ', {title = 'LSP locations', items = util.locations_to_items(result)})
|
||||
api.nvim_command("copen")
|
||||
end
|
||||
else
|
||||
@@ -379,7 +379,7 @@ local make_call_hierarchy_handler = function(direction)
|
||||
})
|
||||
end
|
||||
end
|
||||
util.set_qflist(items)
|
||||
vim.fn.setqflist({}, ' ', {title = 'LSP call hierarchy', items = items})
|
||||
api.nvim_command("copen")
|
||||
end
|
||||
end
|
||||
|
@@ -8,8 +8,8 @@ local log = {}
|
||||
-- Log level dictionary with reverse lookup as well.
|
||||
--
|
||||
-- Can be used to lookup the number from the name or the name from the number.
|
||||
-- Levels by name: 'trace', 'debug', 'info', 'warn', 'error'
|
||||
-- Level numbers begin with 'trace' at 0
|
||||
-- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR"
|
||||
-- Level numbers begin with "TRACE" at 0
|
||||
log.levels = vim.deepcopy(vim.log.levels)
|
||||
|
||||
-- Default log level is warn.
|
||||
|
@@ -776,149 +776,9 @@ function protocol.make_client_capabilities()
|
||||
}
|
||||
end
|
||||
|
||||
--[=[
|
||||
export interface DocumentFilter {
|
||||
--A language id, like `typescript`.
|
||||
language?: string;
|
||||
--A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
|
||||
scheme?: string;
|
||||
--A glob pattern, like `*.{ts,js}`.
|
||||
--
|
||||
--Glob patterns can have the following syntax:
|
||||
--- `*` to match one or more characters in a path segment
|
||||
--- `?` to match on one character in a path segment
|
||||
--- `**` to match any number of path segments, including none
|
||||
--- `{}` to group conditions (e.g. `**/*.{ts,js}` matches all TypeScript and JavaScript files)
|
||||
--- `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
|
||||
--- `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
|
||||
pattern?: string;
|
||||
}
|
||||
--]=]
|
||||
|
||||
--[[
|
||||
--Static registration options to be returned in the initialize request.
|
||||
interface StaticRegistrationOptions {
|
||||
--The id used to register the request. The id can be used to deregister
|
||||
--the request again. See also Registration#id.
|
||||
id?: string;
|
||||
}
|
||||
|
||||
export interface DocumentFilter {
|
||||
--A language id, like `typescript`.
|
||||
language?: string;
|
||||
--A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
|
||||
scheme?: string;
|
||||
--A glob pattern, like `*.{ts,js}`.
|
||||
--
|
||||
--Glob patterns can have the following syntax:
|
||||
--- `*` to match one or more characters in a path segment
|
||||
--- `?` to match on one character in a path segment
|
||||
--- `**` to match any number of path segments, including none
|
||||
--- `{}` to group conditions (e.g. `**/*.{ts,js}` matches all TypeScript and JavaScript files)
|
||||
--- `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
|
||||
--- `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
|
||||
pattern?: string;
|
||||
}
|
||||
export type DocumentSelector = DocumentFilter[];
|
||||
export interface TextDocumentRegistrationOptions {
|
||||
--A document selector to identify the scope of the registration. If set to null
|
||||
--the document selector provided on the client side will be used.
|
||||
documentSelector: DocumentSelector | null;
|
||||
}
|
||||
|
||||
--Code Action options.
|
||||
export interface CodeActionOptions {
|
||||
--CodeActionKinds that this server may return.
|
||||
--
|
||||
--The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server
|
||||
--may list out every specific kind they provide.
|
||||
codeActionKinds?: CodeActionKind[];
|
||||
}
|
||||
|
||||
interface ServerCapabilities {
|
||||
--Defines how text documents are synced. Is either a detailed structure defining each notification or
|
||||
--for backwards compatibility the TextDocumentSyncKind number. If omitted it defaults to `TextDocumentSyncKind.None`.
|
||||
textDocumentSync?: TextDocumentSyncOptions | number;
|
||||
--The server provides hover support.
|
||||
hoverProvider?: boolean;
|
||||
--The server provides completion support.
|
||||
completionProvider?: CompletionOptions;
|
||||
--The server provides signature help support.
|
||||
signatureHelpProvider?: SignatureHelpOptions;
|
||||
--The server provides goto definition support.
|
||||
definitionProvider?: boolean;
|
||||
--The server provides Goto Type Definition support.
|
||||
--
|
||||
--Since 3.6.0
|
||||
typeDefinitionProvider?: boolean | (TextDocumentRegistrationOptions & StaticRegistrationOptions);
|
||||
--The server provides Goto Implementation support.
|
||||
--
|
||||
--Since 3.6.0
|
||||
implementationProvider?: boolean | (TextDocumentRegistrationOptions & StaticRegistrationOptions);
|
||||
--The server provides find references support.
|
||||
referencesProvider?: boolean;
|
||||
--The server provides document highlight support.
|
||||
documentHighlightProvider?: boolean;
|
||||
--The server provides document symbol support.
|
||||
documentSymbolProvider?: boolean;
|
||||
--The server provides workspace symbol support.
|
||||
workspaceSymbolProvider?: boolean;
|
||||
--The server provides code actions. The `CodeActionOptions` return type is only
|
||||
--valid if the client signals code action literal support via the property
|
||||
--`textDocument.codeAction.codeActionLiteralSupport`.
|
||||
codeActionProvider?: boolean | CodeActionOptions;
|
||||
--The server provides code lens.
|
||||
codeLensProvider?: CodeLensOptions;
|
||||
--The server provides document formatting.
|
||||
documentFormattingProvider?: boolean;
|
||||
--The server provides document range formatting.
|
||||
documentRangeFormattingProvider?: boolean;
|
||||
--The server provides document formatting on typing.
|
||||
documentOnTypeFormattingProvider?: DocumentOnTypeFormattingOptions;
|
||||
--The server provides rename support. RenameOptions may only be
|
||||
--specified if the client states that it supports
|
||||
--`prepareSupport` in its initial `initialize` request.
|
||||
renameProvider?: boolean | RenameOptions;
|
||||
--The server provides document link support.
|
||||
documentLinkProvider?: DocumentLinkOptions;
|
||||
--The server provides color provider support.
|
||||
--
|
||||
--Since 3.6.0
|
||||
colorProvider?: boolean | ColorProviderOptions | (ColorProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions);
|
||||
--The server provides folding provider support.
|
||||
--
|
||||
--Since 3.10.0
|
||||
foldingRangeProvider?: boolean | FoldingRangeProviderOptions | (FoldingRangeProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions);
|
||||
--The server provides go to declaration support.
|
||||
--
|
||||
--Since 3.14.0
|
||||
declarationProvider?: boolean | (TextDocumentRegistrationOptions & StaticRegistrationOptions);
|
||||
--The server provides execute command support.
|
||||
executeCommandProvider?: ExecuteCommandOptions;
|
||||
--Workspace specific server capabilities
|
||||
workspace?: {
|
||||
--The server supports workspace folder.
|
||||
--
|
||||
--Since 3.6.0
|
||||
workspaceFolders?: {
|
||||
* The server has support for workspace folders
|
||||
supported?: boolean;
|
||||
* Whether the server wants to receive workspace folder
|
||||
* change notifications.
|
||||
*
|
||||
* If a strings is provided the string is treated as a ID
|
||||
* under which the notification is registered on the client
|
||||
* side. The ID can be used to unregister for these events
|
||||
* using the `client/unregisterCapability` request.
|
||||
changeNotifications?: string | boolean;
|
||||
}
|
||||
}
|
||||
--Experimental server capabilities.
|
||||
experimental?: any;
|
||||
}
|
||||
--]]
|
||||
|
||||
--- Creates a normalized object describing LSP server capabilities.
|
||||
---@param server_capabilities table Table of capabilities supported by the server
|
||||
---@return table Normalized table of capabilities
|
||||
function protocol.resolve_capabilities(server_capabilities)
|
||||
local general_properties = {}
|
||||
local text_document_sync_properties
|
||||
|
@@ -133,7 +133,8 @@ local function request_parser_loop()
|
||||
end
|
||||
end
|
||||
|
||||
local client_errors = vim.tbl_add_reverse_lookup {
|
||||
--- Mapping of error codes used by the client
|
||||
local client_errors = {
|
||||
INVALID_SERVER_MESSAGE = 1;
|
||||
INVALID_SERVER_JSON = 2;
|
||||
NO_RESULT_CALLBACK_FOUND = 3;
|
||||
@@ -143,6 +144,8 @@ local client_errors = vim.tbl_add_reverse_lookup {
|
||||
SERVER_RESULT_CALLBACK_ERROR = 7;
|
||||
}
|
||||
|
||||
client_errors = vim.tbl_add_reverse_lookup(client_errors)
|
||||
|
||||
--- Constructs an error message from an LSP error object.
|
||||
---
|
||||
---@param err (table) The error object
|
||||
|
@@ -105,15 +105,16 @@ local function align_end_position(line, byte, offset_encoding)
|
||||
char = compute_line_length(line, offset_encoding) + 1
|
||||
else
|
||||
-- Modifying line, find the nearest utf codepoint
|
||||
local offset = str_utf_end(line, byte)
|
||||
local offset = str_utf_start(line, byte)
|
||||
-- If the byte does not fall on the start of the character, then
|
||||
-- align to the start of the next character.
|
||||
if offset > 0 then
|
||||
char = byte_to_utf(line, byte, offset_encoding) + 1
|
||||
byte = byte + offset
|
||||
else
|
||||
if offset < 0 then
|
||||
byte = byte + str_utf_end(line, byte) + 1
|
||||
end
|
||||
if byte <= #line then
|
||||
char = byte_to_utf(line, byte, offset_encoding)
|
||||
byte = byte + offset
|
||||
else
|
||||
char = compute_line_length(line, offset_encoding) + 1
|
||||
end
|
||||
-- Extending line, find the nearest utf codepoint for the last valid character
|
||||
end
|
||||
@@ -167,7 +168,7 @@ local function compute_start_range(prev_lines, curr_lines, firstline, lastline,
|
||||
char_idx = compute_line_length(prev_line, offset_encoding) + 1
|
||||
else
|
||||
byte_idx = start_byte_idx + str_utf_start(prev_line, start_byte_idx)
|
||||
char_idx = byte_to_utf(prev_line, start_byte_idx, offset_encoding)
|
||||
char_idx = byte_to_utf(prev_line, byte_idx, offset_encoding)
|
||||
end
|
||||
|
||||
-- Return the start difference (shared for new and prev lines)
|
||||
|
@@ -10,14 +10,6 @@ local uv = vim.loop
|
||||
local npcall = vim.F.npcall
|
||||
local split = vim.split
|
||||
|
||||
local _warned = {}
|
||||
local warn_once = function(message)
|
||||
if not _warned[message] then
|
||||
vim.api.nvim_err_writeln(message)
|
||||
_warned[message] = true
|
||||
end
|
||||
end
|
||||
|
||||
local M = {}
|
||||
|
||||
local default_border = {
|
||||
@@ -90,6 +82,49 @@ local function split_lines(value)
|
||||
return split(value, '\n', true)
|
||||
end
|
||||
|
||||
--- Convert byte index to `encoding` index.
|
||||
--- Convenience wrapper around vim.str_utfindex
|
||||
---@param line string line to be indexed
|
||||
---@param index number byte index (utf-8), or `nil` for length
|
||||
---@param encoding string utf-8|utf-16|utf-32|nil defaults to utf-16
|
||||
---@return number `encoding` index of `index` in `line`
|
||||
function M._str_utfindex_enc(line, index, encoding)
|
||||
if not encoding then encoding = 'utf-16' end
|
||||
if encoding == 'utf-8' then
|
||||
if index then return index else return #line end
|
||||
elseif encoding == 'utf-16' then
|
||||
local _, col16 = vim.str_utfindex(line, index)
|
||||
return col16
|
||||
elseif encoding == 'utf-32' then
|
||||
local col32, _ = vim.str_utfindex(line, index)
|
||||
return col32
|
||||
else
|
||||
error("Invalid encoding: " .. vim.inspect(encoding))
|
||||
end
|
||||
end
|
||||
|
||||
--- Convert UTF index to `encoding` index.
|
||||
--- Convenience wrapper around vim.str_byteindex
|
||||
---Alternative to vim.str_byteindex that takes an encoding.
|
||||
---@param line string line to be indexed
|
||||
---@param index number UTF index
|
||||
---@param encoding string utf-8|utf-16|utf-32|nil defaults to utf-16
|
||||
---@return number byte (utf-8) index of `encoding` index `index` in `line`
|
||||
function M._str_byteindex_enc(line, index, encoding)
|
||||
if not encoding then encoding = 'utf-16' end
|
||||
if encoding == 'utf-8' then
|
||||
if index then return index else return #line end
|
||||
elseif encoding == 'utf-16' then
|
||||
return vim.str_byteindex(line, index, true)
|
||||
elseif encoding == 'utf-32' then
|
||||
return vim.str_byteindex(line, index)
|
||||
else
|
||||
error("Invalid encoding: " .. vim.inspect(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!
|
||||
@@ -158,6 +193,11 @@ end
|
||||
local function get_lines(bufnr, rows)
|
||||
rows = type(rows) == "table" and rows or { rows }
|
||||
|
||||
-- This is needed for bufload and bufloaded
|
||||
if bufnr == 0 then
|
||||
bufnr = vim.api.nvim_get_current_buf()
|
||||
end
|
||||
|
||||
---@private
|
||||
local function buf_lines()
|
||||
local lines = {}
|
||||
@@ -237,6 +277,7 @@ end
|
||||
---@private
|
||||
--- Position is a https://microsoft.github.io/language-server-protocol/specifications/specification-current/#position
|
||||
--- Returns a zero-indexed column, since set_lines() does the conversion to
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to utf-16
|
||||
--- 1-indexed
|
||||
local function get_line_byte_from_position(bufnr, position, offset_encoding)
|
||||
-- LSP's line and characters are 0-indexed
|
||||
@@ -247,13 +288,7 @@ local function get_line_byte_from_position(bufnr, position, offset_encoding)
|
||||
if col > 0 then
|
||||
local line = get_line(bufnr, position.line)
|
||||
local ok, result
|
||||
|
||||
if offset_encoding == "utf-16" or not offset_encoding then
|
||||
ok, result = pcall(vim.str_byteindex, line, col, true)
|
||||
elseif offset_encoding == "utf-32" then
|
||||
ok, result = pcall(vim.str_byteindex, line, col, false)
|
||||
end
|
||||
|
||||
ok, result = pcall(_str_byteindex_enc, line, col, offset_encoding)
|
||||
if ok then
|
||||
return result
|
||||
end
|
||||
@@ -325,12 +360,15 @@ end
|
||||
--- Applies a list of text edits to a buffer.
|
||||
---@param text_edits table list of `TextEdit` objects
|
||||
---@param bufnr number Buffer id
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to encoding of first client of `bufnr`
|
||||
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit
|
||||
function M.apply_text_edits(text_edits, bufnr)
|
||||
function M.apply_text_edits(text_edits, bufnr, offset_encoding)
|
||||
validate {
|
||||
text_edits = { text_edits, 't', false };
|
||||
bufnr = { bufnr, 'number', false };
|
||||
offset_encoding = { offset_encoding, 'string', true };
|
||||
}
|
||||
offset_encoding = offset_encoding or M._get_offset_encoding(bufnr)
|
||||
if not next(text_edits) then return end
|
||||
if not api.nvim_buf_is_loaded(bufnr) then
|
||||
vim.fn.bufload(bufnr)
|
||||
@@ -367,8 +405,7 @@ function M.apply_text_edits(text_edits, bufnr)
|
||||
-- Some LSP servers may return +1 range of the buffer content but nvim_buf_set_text can't accept it so we should fix it here.
|
||||
local has_eol_text_edit = false
|
||||
local max = vim.api.nvim_buf_line_count(bufnr)
|
||||
-- TODO handle offset_encoding
|
||||
local _, len = vim.str_utfindex(vim.api.nvim_buf_get_lines(bufnr, -2, -1, false)[1] or '')
|
||||
local len = _str_utfindex_enc(vim.api.nvim_buf_get_lines(bufnr, -2, -1, false)[1] or '', nil, offset_encoding)
|
||||
text_edits = vim.tbl_map(function(text_edit)
|
||||
if max <= text_edit.range.start.line then
|
||||
text_edit.range.start.line = max - 1
|
||||
@@ -960,11 +997,13 @@ function M.jump_to_location(location)
|
||||
|
||||
--- Jump to new location (adjusting for UTF-16 encoding of characters)
|
||||
api.nvim_set_current_buf(bufnr)
|
||||
api.nvim_buf_set_option(0, 'buflisted', true)
|
||||
api.nvim_buf_set_option(bufnr, 'buflisted', true)
|
||||
local range = location.range or location.targetSelectionRange
|
||||
local row = range.start.line
|
||||
local col = get_line_byte_from_position(0, range.start)
|
||||
local col = get_line_byte_from_position(bufnr, range.start)
|
||||
api.nvim_win_set_cursor(0, {row + 1, col})
|
||||
-- Open folds under the cursor
|
||||
vim.cmd("normal! zv")
|
||||
return true
|
||||
end
|
||||
|
||||
@@ -1218,17 +1257,57 @@ function M.stylize_markdown(bufnr, contents, opts)
|
||||
return stripped
|
||||
end
|
||||
|
||||
---@private
|
||||
--- Creates autocommands to close a preview window when events happen.
|
||||
---
|
||||
---@param events (table) list of events
|
||||
---@param winnr (number) window id of preview window
|
||||
---@param events table list of events
|
||||
---@param winnr number window id of preview window
|
||||
---@param bufnrs table list of buffers where the preview window will remain visible
|
||||
---@see |autocmd-events|
|
||||
function M.close_preview_autocmd(events, winnr)
|
||||
local function close_preview_autocmd(events, winnr, bufnrs)
|
||||
local augroup = 'preview_window_'..winnr
|
||||
|
||||
-- close the preview window when entered a buffer that is not
|
||||
-- the floating window buffer or the buffer that spawned it
|
||||
vim.cmd(string.format([[
|
||||
augroup %s
|
||||
autocmd!
|
||||
autocmd BufEnter * lua vim.lsp.util._close_preview_window(%d, {%s})
|
||||
augroup end
|
||||
]], augroup, winnr, table.concat(bufnrs, ',')))
|
||||
|
||||
if #events > 0 then
|
||||
api.nvim_command("autocmd "..table.concat(events, ',').." <buffer> ++once lua pcall(vim.api.nvim_win_close, "..winnr..", true)")
|
||||
vim.cmd(string.format([[
|
||||
augroup %s
|
||||
autocmd %s <buffer> lua vim.lsp.util._close_preview_window(%d)
|
||||
augroup end
|
||||
]], augroup, table.concat(events, ','), winnr))
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
--- Closes the preview window
|
||||
---
|
||||
---@param winnr number window id of preview window
|
||||
---@param bufnrs table|nil optional list of ignored buffers
|
||||
function M._close_preview_window(winnr, bufnrs)
|
||||
vim.schedule(function()
|
||||
-- exit if we are in one of ignored buffers
|
||||
if bufnrs and vim.tbl_contains(bufnrs, api.nvim_get_current_buf()) then
|
||||
return
|
||||
end
|
||||
|
||||
local augroup = 'preview_window_'..winnr
|
||||
vim.cmd(string.format([[
|
||||
augroup %s
|
||||
autocmd!
|
||||
augroup end
|
||||
augroup! %s
|
||||
]], augroup, augroup))
|
||||
pcall(vim.api.nvim_win_close, winnr, true)
|
||||
end)
|
||||
end
|
||||
|
||||
---@internal
|
||||
--- Computes size of float needed to show contents (with optional wrapping)
|
||||
---
|
||||
@@ -1335,7 +1414,7 @@ function M.open_floating_preview(contents, syntax, opts)
|
||||
opts.wrap = opts.wrap ~= false -- wrapping by default
|
||||
opts.stylize_markdown = opts.stylize_markdown ~= false
|
||||
opts.focus = opts.focus ~= false
|
||||
opts.close_events = opts.close_events or {"CursorMoved", "CursorMovedI", "BufHidden", "InsertCharPre"}
|
||||
opts.close_events = opts.close_events or {"CursorMoved", "CursorMovedI", "InsertCharPre"}
|
||||
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
|
||||
@@ -1404,7 +1483,7 @@ function M.open_floating_preview(contents, syntax, opts)
|
||||
api.nvim_buf_set_option(floating_bufnr, 'modifiable', false)
|
||||
api.nvim_buf_set_option(floating_bufnr, 'bufhidden', 'wipe')
|
||||
api.nvim_buf_set_keymap(floating_bufnr, "n", "q", "<cmd>bdelete<cr>", {silent = true, noremap = true, nowait = true})
|
||||
M.close_preview_autocmd(opts.close_events, floating_winnr)
|
||||
close_preview_autocmd(opts.close_events, floating_winnr, {floating_bufnr, bufnr})
|
||||
|
||||
-- save focus_id
|
||||
if opts.focus_id then
|
||||
@@ -1430,11 +1509,11 @@ do --[[ References ]]
|
||||
---
|
||||
---@param bufnr number Buffer id
|
||||
---@param references table List of `DocumentHighlight` objects to highlight
|
||||
---@param offset_encoding string One of "utf-8", "utf-16", "utf-32", or nil. Defaults to utf-16
|
||||
---@param offset_encoding string One of "utf-8", "utf-16", "utf-32", or nil. Defaults to `offset_encoding` of first client of `bufnr`
|
||||
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight
|
||||
function M.buf_highlight_references(bufnr, references, offset_encoding)
|
||||
validate { bufnr = {bufnr, 'n', true} }
|
||||
offset_encoding = offset_encoding or 'utf-16'
|
||||
offset_encoding = offset_encoding or M._get_offset_encoding(bufnr)
|
||||
for _, reference in ipairs(references) do
|
||||
local start_line, start_char = reference["range"]["start"]["line"], reference["range"]["start"]["character"]
|
||||
local end_line, end_char = reference["range"]["end"]["line"], reference["range"]["end"]["character"]
|
||||
@@ -1529,6 +1608,7 @@ end
|
||||
---
|
||||
---@param items (table) list of items
|
||||
function M.set_loclist(items, win_id)
|
||||
vim.api.nvim_echo({{'vim.lsp.util.set_loclist is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
vim.fn.setloclist(win_id or 0, {}, ' ', {
|
||||
title = 'Language Server';
|
||||
items = items;
|
||||
@@ -1542,6 +1622,7 @@ end
|
||||
---
|
||||
---@param items (table) list of items
|
||||
function M.set_qflist(items)
|
||||
vim.api.nvim_echo({{'vim.lsp.util.set_qflist is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
vim.fn.setqflist({}, ' ', {
|
||||
title = 'Language Server';
|
||||
items = items;
|
||||
@@ -1645,43 +1726,78 @@ function M.try_trim_markdown_code_blocks(lines)
|
||||
return 'markdown'
|
||||
end
|
||||
|
||||
local str_utfindex = vim.str_utfindex
|
||||
---@private
|
||||
local function make_position_param()
|
||||
local row, col = unpack(api.nvim_win_get_cursor(0))
|
||||
---@param window (optional, number): window handle or 0 for current, defaults to current
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window`
|
||||
local function make_position_param(window, offset_encoding)
|
||||
window = window or 0
|
||||
local buf = vim.api.nvim_win_get_buf(window)
|
||||
local row, col = unpack(api.nvim_win_get_cursor(window))
|
||||
offset_encoding = offset_encoding or M._get_offset_encoding(buf)
|
||||
row = row - 1
|
||||
local line = api.nvim_buf_get_lines(0, row, row+1, true)[1]
|
||||
local line = api.nvim_buf_get_lines(buf, row, row+1, true)[1]
|
||||
if not line then
|
||||
return { line = 0; character = 0; }
|
||||
end
|
||||
-- TODO handle offset_encoding
|
||||
local _
|
||||
_, col = str_utfindex(line, col)
|
||||
|
||||
col = _str_utfindex_enc(line, col, offset_encoding)
|
||||
|
||||
return { line = row; character = col; }
|
||||
end
|
||||
|
||||
--- Creates a `TextDocumentPositionParams` object for the current buffer and cursor position.
|
||||
---
|
||||
---@param window (optional, number): window handle or 0 for current, defaults to current
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window`
|
||||
---@returns `TextDocumentPositionParams` object
|
||||
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentPositionParams
|
||||
function M.make_position_params()
|
||||
function M.make_position_params(window, offset_encoding)
|
||||
window = window or 0
|
||||
local buf = vim.api.nvim_win_get_buf(window)
|
||||
offset_encoding = offset_encoding or M._get_offset_encoding(buf)
|
||||
return {
|
||||
textDocument = M.make_text_document_params();
|
||||
position = make_position_param()
|
||||
textDocument = M.make_text_document_params(buf);
|
||||
position = make_position_param(window, offset_encoding)
|
||||
}
|
||||
end
|
||||
|
||||
--- Utility function for getting the encoding of the first LSP client on the given buffer.
|
||||
---@param bufnr (number) buffer handle or 0 for current, defaults to current
|
||||
---@returns (string) encoding first client if there is one, nil otherwise
|
||||
function M._get_offset_encoding(bufnr)
|
||||
validate {
|
||||
bufnr = {bufnr, 'n', true};
|
||||
}
|
||||
|
||||
local offset_encoding
|
||||
|
||||
for _, client in pairs(vim.lsp.buf_get_clients(bufnr)) do
|
||||
local this_offset_encoding = client.offset_encoding or "utf-16"
|
||||
if not offset_encoding then
|
||||
offset_encoding = this_offset_encoding
|
||||
elseif offset_encoding ~= this_offset_encoding then
|
||||
vim.notify("warning: multiple different client offset_encodings detected for buffer, this is not supported yet", vim.log.levels.WARN)
|
||||
end
|
||||
end
|
||||
|
||||
return offset_encoding
|
||||
end
|
||||
|
||||
--- Using the current position in the current buffer, creates an object that
|
||||
--- can be used as a building block for several LSP requests, such as
|
||||
--- `textDocument/codeAction`, `textDocument/colorPresentation`,
|
||||
--- `textDocument/rangeFormatting`.
|
||||
---
|
||||
---@param window (optional, number): window handle or 0 for current, defaults to current
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window`
|
||||
---@returns { textDocument = { uri = `current_file_uri` }, range = { start =
|
||||
---`current_position`, end = `current_position` } }
|
||||
function M.make_range_params()
|
||||
local position = make_position_param()
|
||||
function M.make_range_params(window, offset_encoding)
|
||||
local buf = vim.api.nvim_win_get_buf(window)
|
||||
offset_encoding = offset_encoding or M._get_offset_encoding(buf)
|
||||
local position = make_position_param(window, offset_encoding)
|
||||
return {
|
||||
textDocument = M.make_text_document_params(),
|
||||
textDocument = M.make_text_document_params(buf),
|
||||
range = { start = position; ["end"] = position; }
|
||||
}
|
||||
end
|
||||
@@ -1693,27 +1809,29 @@ end
|
||||
---Defaults to the start of the last visual selection.
|
||||
---@param end_pos ({number, number}, optional) mark-indexed position.
|
||||
---Defaults to the end of the last visual selection.
|
||||
---@param bufnr (optional, number): buffer handle or 0 for current, defaults to current
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of `bufnr`
|
||||
---@returns { textDocument = { uri = `current_file_uri` }, range = { start =
|
||||
---`start_position`, end = `end_position` } }
|
||||
function M.make_given_range_params(start_pos, end_pos)
|
||||
function M.make_given_range_params(start_pos, end_pos, bufnr, offset_encoding)
|
||||
validate {
|
||||
start_pos = {start_pos, 't', true};
|
||||
end_pos = {end_pos, 't', true};
|
||||
offset_encoding = {offset_encoding, 's', true};
|
||||
}
|
||||
local A = list_extend({}, start_pos or api.nvim_buf_get_mark(0, '<'))
|
||||
local B = list_extend({}, end_pos or api.nvim_buf_get_mark(0, '>'))
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
offset_encoding = offset_encoding or M._get_offset_encoding(bufnr)
|
||||
local A = list_extend({}, start_pos or api.nvim_buf_get_mark(bufnr, '<'))
|
||||
local B = list_extend({}, end_pos or api.nvim_buf_get_mark(bufnr, '>'))
|
||||
-- convert to 0-index
|
||||
A[1] = A[1] - 1
|
||||
B[1] = B[1] - 1
|
||||
-- account for encoding.
|
||||
-- TODO handle offset_encoding
|
||||
-- account for offset_encoding.
|
||||
if A[2] > 0 then
|
||||
local _, char = M.character_offset(0, A[1], A[2])
|
||||
A = {A[1], char}
|
||||
A = {A[1], M.character_offset(bufnr, A[1], A[2], offset_encoding)}
|
||||
end
|
||||
if B[2] > 0 then
|
||||
local _, char = M.character_offset(0, B[1], B[2])
|
||||
B = {B[1], char}
|
||||
B = {B[1], M.character_offset(bufnr, B[1], B[2], offset_encoding)}
|
||||
end
|
||||
-- we need to offset the end character position otherwise we loose the last
|
||||
-- character of the selection, as LSP end position is exclusive
|
||||
@@ -1722,7 +1840,7 @@ function M.make_given_range_params(start_pos, end_pos)
|
||||
B[2] = B[2] + 1
|
||||
end
|
||||
return {
|
||||
textDocument = M.make_text_document_params(),
|
||||
textDocument = M.make_text_document_params(bufnr),
|
||||
range = {
|
||||
start = {line = A[1], character = A[2]},
|
||||
['end'] = {line = B[1], character = B[2]}
|
||||
@@ -1732,10 +1850,11 @@ end
|
||||
|
||||
--- Creates a `TextDocumentIdentifier` object for the current buffer.
|
||||
---
|
||||
---@param bufnr (optional, number): Buffer handle, defaults to current
|
||||
---@returns `TextDocumentIdentifier`
|
||||
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentIdentifier
|
||||
function M.make_text_document_params()
|
||||
return { uri = vim.uri_from_bufnr(0) }
|
||||
function M.make_text_document_params(bufnr)
|
||||
return { uri = vim.uri_from_bufnr(bufnr or 0) }
|
||||
end
|
||||
|
||||
--- Create the workspace params
|
||||
@@ -1778,14 +1897,16 @@ end
|
||||
---@param buf buffer id (0 for current)
|
||||
---@param row 0-indexed line
|
||||
---@param col 0-indexed byte offset in line
|
||||
---@returns (number, number) UTF-32 and UTF-16 index of the character in line {row} column {col} in buffer {buf}
|
||||
function M.character_offset(bufnr, row, col)
|
||||
local line = get_line(bufnr, row)
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of `buf`
|
||||
---@returns (number, number) `offset_encoding` index of the character in line {row} column {col} in buffer {buf}
|
||||
function M.character_offset(buf, row, col, offset_encoding)
|
||||
local line = get_line(buf, row)
|
||||
offset_encoding = offset_encoding or M._get_offset_encoding(buf)
|
||||
-- If the col is past the EOL, use the line length.
|
||||
if col > #line then
|
||||
return str_utfindex(line)
|
||||
return _str_utfindex_enc(line, nil, offset_encoding)
|
||||
end
|
||||
return str_utfindex(line, col)
|
||||
return _str_utfindex_enc(line, col, offset_encoding)
|
||||
end
|
||||
|
||||
--- Helper function to return nested values in language server settings
|
||||
@@ -1804,7 +1925,6 @@ function M.lookup_section(settings, section)
|
||||
end
|
||||
|
||||
M._get_line_byte_from_position = get_line_byte_from_position
|
||||
M._warn_once = warn_once
|
||||
|
||||
M.buf_versions = {}
|
||||
|
||||
|
@@ -74,8 +74,8 @@ local function uri_from_fname(path)
|
||||
return table.concat(uri_parts)
|
||||
end
|
||||
|
||||
local URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9+-.]*):.*'
|
||||
local WINDOWS_URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9+-.]*):[a-zA-Z]:.*'
|
||||
local URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):.*'
|
||||
local WINDOWS_URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):[a-zA-Z]:.*'
|
||||
|
||||
--- Get a URI from a bufnr
|
||||
---@param bufnr number
|
||||
|
@@ -26,7 +26,9 @@
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release date="2021-12-31" version="0.6.1"/>
|
||||
<release date="2021-11-30" version="0.6.0"/>
|
||||
<release date="2021-09-26" version="0.5.1"/>
|
||||
<release date="2021-07-02" version="0.5.0"/>
|
||||
<release date="2020-08-04" version="0.4.4"/>
|
||||
<release date="2019-11-06" version="0.4.3"/>
|
||||
|
30
runtime/syntax/checkhealth.vim
Normal file
30
runtime/syntax/checkhealth.vim
Normal file
@@ -0,0 +1,30 @@
|
||||
" Vim syntax file
|
||||
" Language: Neovim checkhealth buffer
|
||||
" Last Change: 2021 Dec 15
|
||||
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
runtime! syntax/markdown.vim
|
||||
unlet! b:current_syntax
|
||||
|
||||
syn case match
|
||||
|
||||
" We do not care about markdown syntax errors
|
||||
if hlexists('markdownError')
|
||||
syn clear markdownError
|
||||
endif
|
||||
|
||||
syn keyword healthError ERROR[:] containedin=markdownCodeBlock,mkdListItemLine
|
||||
syn keyword healthWarning WARNING[:] containedin=markdownCodeBlock,mkdListItemLine
|
||||
syn keyword healthSuccess OK[:] containedin=markdownCodeBlock,mkdListItemLine
|
||||
syn match healthHelp "|.\{-}|" containedin=markdownCodeBlock,mkdListItemLine contains=healthBar
|
||||
syn match healthBar "|" contained conceal
|
||||
|
||||
hi def link healthError Error
|
||||
hi def link healthWarning WarningMsg
|
||||
hi def healthSuccess guibg=#5fff00 guifg=#080808 ctermbg=82 ctermfg=232
|
||||
hi def link healthHelp Identifier
|
||||
|
||||
let b:current_syntax = "checkhealth"
|
@@ -1,263 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|
||||
This script squashes a PR tagged with the "typo" label into a single, dedicated
|
||||
"squash PR".
|
||||
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
def get_authors_and_emails_from_pr():
|
||||
"""
|
||||
|
||||
Return all contributing authors and their emails for the PR on current branch.
|
||||
This includes co-authors, meaning that if two authors are credited for a
|
||||
single commit, which is possible with GitHub, then both will get credited.
|
||||
|
||||
"""
|
||||
|
||||
# Get a list of all authors involved in the pull request (including co-authors).
|
||||
authors = subprocess.check_output(
|
||||
[
|
||||
"gh",
|
||||
"pr",
|
||||
"view",
|
||||
os.environ["PR_NUMBER"],
|
||||
"--json",
|
||||
"commits",
|
||||
"--jq",
|
||||
".[][].authors.[].name",
|
||||
],
|
||||
text=True,
|
||||
).splitlines()
|
||||
|
||||
# Get a list of emails of the aforementioned authors.
|
||||
emails = subprocess.check_output(
|
||||
[
|
||||
"gh",
|
||||
"pr",
|
||||
"view",
|
||||
os.environ["PR_NUMBER"],
|
||||
"--json",
|
||||
"commits",
|
||||
"--jq",
|
||||
".[][].authors.[].email",
|
||||
],
|
||||
text=True,
|
||||
).splitlines()
|
||||
|
||||
authors_and_emails = [(author, mail) for author, mail in zip(authors, emails)]
|
||||
|
||||
return authors_and_emails
|
||||
|
||||
|
||||
def rebase_onto_pr():
|
||||
"""
|
||||
|
||||
Rebase current branch onto the PR.
|
||||
|
||||
"""
|
||||
|
||||
# Check out the pull request.
|
||||
subprocess.call(["gh", "pr", "checkout", os.environ["PR_NUMBER"]])
|
||||
|
||||
rebase_onto_master()
|
||||
|
||||
# Change back to the original branch.
|
||||
subprocess.call(["git", "switch", "-"])
|
||||
|
||||
# Rebase onto the pull request, aka include the commits in the pull request
|
||||
# in the current branch. Abort with error message if rebase fails.
|
||||
|
||||
try:
|
||||
subprocess.check_call(["git", "rebase", "-"])
|
||||
except subprocess.CalledProcessError:
|
||||
subprocess.call(["git", "rebase", "--abort"])
|
||||
squash_url = subprocess.check_output(
|
||||
["gh", "pr", "view", "--json", "url", "--jq", ".url"], text=True
|
||||
).strip()
|
||||
|
||||
subprocess.call(
|
||||
[
|
||||
"gh",
|
||||
"pr",
|
||||
"comment",
|
||||
os.environ["PR_NUMBER"],
|
||||
"--body",
|
||||
f"Your edit conflicts with an already scheduled fix \
|
||||
({squash_url}). Please check that batch PR whether your fix is \
|
||||
already included; if not, then please wait until the batch PR \
|
||||
is merged and then rebase your PR on top of master.",
|
||||
]
|
||||
)
|
||||
|
||||
sys.exit(
|
||||
f"\n\nERROR: Your edit conflicts with an already scheduled fix \
|
||||
{squash_url} \n\n"
|
||||
)
|
||||
|
||||
|
||||
def rebase_onto_master():
|
||||
"""
|
||||
|
||||
Rebase current branch onto the master i.e. make sure current branch is up
|
||||
to date. Abort on error.
|
||||
|
||||
"""
|
||||
|
||||
default_branch = f"{os.environ['GITHUB_BASE_REF']}"
|
||||
subprocess.check_call(["git", "rebase", default_branch])
|
||||
|
||||
|
||||
def squash_all_commits(message_body_before):
|
||||
"""
|
||||
|
||||
Squash all commits on the PR into a single commit. Credit all authors by
|
||||
name and email.
|
||||
|
||||
"""
|
||||
|
||||
default_branch = f"{os.environ['GITHUB_BASE_REF']}"
|
||||
subprocess.call(["git", "reset", "--soft", default_branch])
|
||||
|
||||
authors_and_emails = get_authors_and_emails_from_pr()
|
||||
commit_message_coauthors = (
|
||||
"\n"
|
||||
+ "\n".join([f"Co-authored-by: {i[0]} <{i[1]}>" for i in authors_and_emails])
|
||||
+ "\n"
|
||||
+ message_body_before
|
||||
)
|
||||
subprocess.call(
|
||||
["git", "commit", "-m", "chore: typo fixes", "-m", commit_message_coauthors]
|
||||
)
|
||||
|
||||
|
||||
def force_push(branch):
|
||||
"""
|
||||
|
||||
Like the name implies, force push <branch>.
|
||||
|
||||
"""
|
||||
|
||||
gh_actor = os.environ["GITHUB_ACTOR"]
|
||||
gh_token = os.environ["GITHUB_TOKEN"]
|
||||
gh_repo = os.environ["GITHUB_REPOSITORY"]
|
||||
subprocess.call(
|
||||
[
|
||||
"git",
|
||||
"push",
|
||||
"--force",
|
||||
f"https://{gh_actor}:{gh_token}@github.com/{gh_repo}",
|
||||
branch,
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def checkout_branch(branch):
|
||||
"""
|
||||
|
||||
Create and checkout <branch>. Check if branch exists on remote, if so then
|
||||
sync local branch to remote.
|
||||
|
||||
Return True if remote branch exists, else False.
|
||||
|
||||
"""
|
||||
|
||||
# FIXME I'm not sure why the local branch isn't tracking the remote branch
|
||||
# automatically. This works but I'm pretty sure it can be done in a more
|
||||
# "elegant" fashion
|
||||
|
||||
show_ref_output = subprocess.check_output(["git", "show-ref"], text=True).strip()
|
||||
|
||||
if branch in show_ref_output:
|
||||
subprocess.call(["git", "checkout", "-b", branch, f"origin/{branch}"])
|
||||
return True
|
||||
|
||||
subprocess.call(["git", "checkout", "-b", branch])
|
||||
return False
|
||||
|
||||
|
||||
def get_all_pr_urls(pr_branch_exists):
|
||||
"""
|
||||
|
||||
Return a list of URLs for the pull requests with the typo fixes. If a
|
||||
squash branch exists then extract the URLs from the body text.
|
||||
|
||||
"""
|
||||
|
||||
all_pr_urls = ""
|
||||
if pr_branch_exists:
|
||||
all_pr_urls += subprocess.check_output(
|
||||
["gh", "pr", "view", "--json", "body", "--jq", ".body"], text=True
|
||||
)
|
||||
|
||||
all_pr_urls += subprocess.check_output(
|
||||
["gh", "pr", "view", os.environ["PR_NUMBER"], "--json", "url", "--jq", ".url"],
|
||||
text=True,
|
||||
).strip()
|
||||
|
||||
return all_pr_urls
|
||||
|
||||
|
||||
def main():
|
||||
pr_branch = "marvim/squash-typos"
|
||||
|
||||
pr_branch_exists = checkout_branch(pr_branch)
|
||||
|
||||
rebase_onto_master()
|
||||
force_push(pr_branch)
|
||||
|
||||
message_body_before = "\n".join(
|
||||
subprocess.check_output(
|
||||
["git", "log", "--format=%B", "-n1", pr_branch], text=True
|
||||
).splitlines()[2:]
|
||||
)
|
||||
|
||||
rebase_onto_pr()
|
||||
force_push(pr_branch)
|
||||
|
||||
subprocess.call(
|
||||
[
|
||||
"gh",
|
||||
"pr",
|
||||
"create",
|
||||
"--fill",
|
||||
"--head",
|
||||
pr_branch,
|
||||
"--title",
|
||||
"chore: typo fixes (automated)",
|
||||
],
|
||||
text=True,
|
||||
)
|
||||
|
||||
squash_all_commits(message_body_before)
|
||||
force_push(pr_branch)
|
||||
|
||||
all_pr_urls = get_all_pr_urls(pr_branch_exists)
|
||||
subprocess.call(["gh", "pr", "edit", "--add-label", "typo", "--body", all_pr_urls])
|
||||
|
||||
subprocess.call(["gh", "pr", "close", os.environ["PR_NUMBER"]])
|
||||
|
||||
squash_url = subprocess.check_output(
|
||||
["gh", "pr", "view", "--json", "url", "--jq", ".url"], text=True
|
||||
).strip()
|
||||
subprocess.call(
|
||||
[
|
||||
"gh",
|
||||
"pr",
|
||||
"comment",
|
||||
os.environ["PR_NUMBER"],
|
||||
"--body",
|
||||
f"Thank you for your contribution! We collect all typo fixes \
|
||||
into a single pull request and merge it once it gets big enough: \
|
||||
{squash_url}",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@@ -485,6 +485,9 @@ add_executable(nvim ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS}
|
||||
${EXTERNAL_SOURCES} ${EXTERNAL_HEADERS})
|
||||
target_link_libraries(nvim ${NVIM_EXEC_LINK_LIBRARIES})
|
||||
install_helper(TARGETS nvim)
|
||||
if(MSVC)
|
||||
install(FILES $<TARGET_PDB_FILE:nvim> DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL)
|
||||
endif()
|
||||
|
||||
set_property(TARGET nvim APPEND PROPERTY
|
||||
INCLUDE_DIRECTORIES ${LUA_PREFERRED_INCLUDE_DIRS})
|
||||
|
@@ -339,7 +339,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
|
||||
/// @param col Column where to place the mark, 0-based. |api-indexing|
|
||||
/// @param opts Optional parameters.
|
||||
/// - id : id of the extmark to edit.
|
||||
/// - end_line : ending line of the mark, 0-based inclusive.
|
||||
/// - end_row : ending line of the mark, 0-based inclusive.
|
||||
/// - end_col : ending col of the mark, 0-based exclusive.
|
||||
/// - hl_group : name of the highlight group used to highlight
|
||||
/// this mark.
|
||||
@@ -431,16 +431,26 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
}
|
||||
|
||||
int line2 = -1;
|
||||
if (opts->end_line.type == kObjectTypeInteger) {
|
||||
Integer val = opts->end_line.data.integer;
|
||||
|
||||
// For backward compatibility we support "end_line" as an alias for "end_row"
|
||||
if (HAS_KEY(opts->end_line)) {
|
||||
if (HAS_KEY(opts->end_row)) {
|
||||
api_set_error(err, kErrorTypeValidation, "cannot use both end_row and end_line");
|
||||
goto error;
|
||||
}
|
||||
opts->end_row = opts->end_line;
|
||||
}
|
||||
|
||||
if (opts->end_row.type == kObjectTypeInteger) {
|
||||
Integer val = opts->end_row.data.integer;
|
||||
if (val < 0 || val > buf->b_ml.ml_line_count) {
|
||||
api_set_error(err, kErrorTypeValidation, "end_line value outside range");
|
||||
api_set_error(err, kErrorTypeValidation, "end_row value outside range");
|
||||
goto error;
|
||||
} else {
|
||||
line2 = (int)val;
|
||||
}
|
||||
} else if (HAS_KEY(opts->end_line)) {
|
||||
api_set_error(err, kErrorTypeValidation, "end_line is not an integer");
|
||||
} else if (HAS_KEY(opts->end_row)) {
|
||||
api_set_error(err, kErrorTypeValidation, "end_row is not an integer");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -571,10 +581,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
OPTION_TO_BOOL(right_gravity, right_gravity, true);
|
||||
|
||||
// Only error out if they try to set end_right_gravity without
|
||||
// setting end_col or end_line
|
||||
// setting end_col or end_row
|
||||
if (line2 == -1 && col2 == -1 && HAS_KEY(opts->end_right_gravity)) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"cannot set end_right_gravity without setting end_line or end_col");
|
||||
"cannot set end_right_gravity without setting end_row or end_col");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@@ -5,6 +5,7 @@ return {
|
||||
set_extmark = {
|
||||
"id";
|
||||
"end_line";
|
||||
"end_row";
|
||||
"end_col";
|
||||
"hl_group";
|
||||
"virt_text";
|
||||
|
@@ -1147,7 +1147,10 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
|
||||
// Prevent chdir() call in win_enter_ext(), through do_autochdir()
|
||||
int save_acd = p_acd;
|
||||
p_acd = false;
|
||||
// no redrawing and don't set the window title
|
||||
RedrawingDisabled++;
|
||||
win_enter(aucmd_win, false);
|
||||
RedrawingDisabled--;
|
||||
p_acd = save_acd;
|
||||
unblock_autocmds();
|
||||
curwin = aucmd_win;
|
||||
|
@@ -1455,7 +1455,10 @@ void set_curbuf(buf_T *buf, int action)
|
||||
}
|
||||
if (bufref_valid(&prevbufref) && !aborting()) {
|
||||
win_T *previouswin = curwin;
|
||||
if (prevbuf == curbuf) {
|
||||
// Do not sync when in Insert mode and the buffer is open in
|
||||
// another window, might be a timer doing something in another
|
||||
// window.
|
||||
if (prevbuf == curbuf && ((State & INSERT) == 0 || curbuf->b_nwindows <= 1)) {
|
||||
u_sync(false);
|
||||
}
|
||||
close_buffer(prevbuf == curwin->w_buffer ? curwin : NULL,
|
||||
@@ -1495,6 +1498,11 @@ void set_curbuf(buf_T *buf, int action)
|
||||
*/
|
||||
void enter_buffer(buf_T *buf)
|
||||
{
|
||||
// Get the buffer in the current window.
|
||||
curwin->w_buffer = buf;
|
||||
curbuf = buf;
|
||||
curbuf->b_nwindows++;
|
||||
|
||||
// Copy buffer and window local option values. Not for a help buffer.
|
||||
buf_copy_options(buf, BCO_ENTER | BCO_NOHELP);
|
||||
if (!buf->b_help) {
|
||||
@@ -1505,11 +1513,6 @@ void enter_buffer(buf_T *buf)
|
||||
}
|
||||
foldUpdateAll(curwin); // update folds (later).
|
||||
|
||||
// Get the buffer in the current window.
|
||||
curwin->w_buffer = buf;
|
||||
curbuf = buf;
|
||||
curbuf->b_nwindows++;
|
||||
|
||||
if (curwin->w_p_diff) {
|
||||
diff_buf_add(curbuf);
|
||||
}
|
||||
|
@@ -3218,7 +3218,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
|
||||
set_vim_var_nr(VV_MOUSE_COL, 0);
|
||||
|
||||
rettv->vval.v_number = n;
|
||||
if (IS_SPECIAL(n) || mod_mask != 0) {
|
||||
if (n != 0 && (IS_SPECIAL(n) || mod_mask != 0)) {
|
||||
char_u temp[10]; // modifier: 3, mbyte-char: 6, NUL: 1
|
||||
int i = 0;
|
||||
|
||||
|
@@ -3009,7 +3009,12 @@ void ex_append(exarg_T *eap)
|
||||
|
||||
did_undo = true;
|
||||
ml_append(lnum, theline, (colnr_T)0, false);
|
||||
appended_lines_mark(lnum + (empty ? 1 : 0), 1L);
|
||||
if (empty) {
|
||||
// there are no marks below the inserted lines
|
||||
appended_lines(lnum, 1L);
|
||||
} else {
|
||||
appended_lines_mark(lnum, 1L);
|
||||
}
|
||||
|
||||
xfree(theline);
|
||||
++lnum;
|
||||
|
@@ -231,8 +231,8 @@ static int nlua_str_utf_start(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
if (offset < 0 || offset > (intptr_t)s1_len) {
|
||||
return luaL_error(lstate, "index out of range");
|
||||
}
|
||||
int tail_offset = mb_head_off((char_u *)s1, (char_u *)s1 + (char_u)offset - 1);
|
||||
lua_pushinteger(lstate, tail_offset);
|
||||
int head_offset = mb_head_off((char_u *)s1, (char_u *)s1 + offset - 1);
|
||||
lua_pushinteger(lstate, head_offset);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ static int nlua_str_utf_end(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
if (offset < 0 || offset > (intptr_t)s1_len) {
|
||||
return luaL_error(lstate, "index out of range");
|
||||
}
|
||||
int tail_offset = mb_tail_off((char_u *)s1, (char_u *)s1 + (char_u)offset - 1);
|
||||
int tail_offset = mb_tail_off((char_u *)s1, (char_u *)s1 + offset - 1);
|
||||
lua_pushinteger(lstate, tail_offset);
|
||||
return 1;
|
||||
}
|
||||
|
@@ -419,23 +419,43 @@ function vim.defer_fn(fn, timeout)
|
||||
end
|
||||
|
||||
|
||||
--- Notification provider
|
||||
--- Display a notification to the user.
|
||||
---
|
||||
--- Without a runtime, writes to :Messages
|
||||
---@see :help nvim_notify
|
||||
---@param msg string Content of the notification to show to the user
|
||||
---@param log_level number|nil enum from vim.log.levels
|
||||
---@param opts table|nil additional options (timeout, etc)
|
||||
function vim.notify(msg, log_level, opts) -- luacheck: no unused
|
||||
if log_level == vim.log.levels.ERROR then
|
||||
--- This function can be overridden by plugins to display notifications using a
|
||||
--- custom provider (such as the system notification provider). By default,
|
||||
--- writes to |:messages|.
|
||||
---
|
||||
---@param msg string Content of the notification to show to the user.
|
||||
---@param level number|nil One of the values from |vim.log.levels|.
|
||||
---@param opts table|nil Optional parameters. Unused by default.
|
||||
function vim.notify(msg, level, opts) -- luacheck: no unused args
|
||||
if level == vim.log.levels.ERROR then
|
||||
vim.api.nvim_err_writeln(msg)
|
||||
elseif log_level == vim.log.levels.WARN then
|
||||
elseif level == vim.log.levels.WARN then
|
||||
vim.api.nvim_echo({{msg, 'WarningMsg'}}, true, {})
|
||||
else
|
||||
vim.api.nvim_echo({{msg}}, true, {})
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local notified = {}
|
||||
|
||||
--- Display a notification only one time.
|
||||
---
|
||||
--- Like |vim.notify()|, but subsequent calls with the same message will not
|
||||
--- display a notification.
|
||||
---
|
||||
---@param msg string Content of the notification to show to the user.
|
||||
---@param level number|nil One of the values from |vim.log.levels|.
|
||||
---@param opts table|nil Optional parameters. Unused by default.
|
||||
function vim.notify_once(msg, level, opts) -- luacheck: no unused args
|
||||
if not notified[msg] then
|
||||
vim.notify(msg, level, opts)
|
||||
notified[msg] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
function vim.register_keystroke_callback()
|
||||
|
@@ -1011,7 +1011,7 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp,
|
||||
col -= wp->w_leftcol;
|
||||
|
||||
if (col >= 0 && col < wp->w_width) {
|
||||
coloff = col - scol + (local ? 0 : wp->w_wincol) + 1;
|
||||
coloff = col - scol + (local ? 0 : wp->w_wincol + wp->w_border_adj[3]) + 1;
|
||||
} else {
|
||||
scol = ccol = ecol = 0;
|
||||
// character is left or right of the window
|
||||
@@ -1022,7 +1022,7 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp,
|
||||
}
|
||||
}
|
||||
}
|
||||
*rowp = (local ? 0 : wp->w_winrow) + row + rowoff;
|
||||
*rowp = (local ? 0 : wp->w_winrow + wp->w_border_adj[0]) + row + rowoff;
|
||||
*scolp = scol + coloff;
|
||||
*ccolp = ccol + coloff;
|
||||
*ecolp = ecol + coloff;
|
||||
|
@@ -5173,11 +5173,7 @@ static void nv_ident(cmdarg_T *cap)
|
||||
// Start insert mode in terminal buffer
|
||||
restart_edit = 'i';
|
||||
|
||||
add_map((char_u *)"<buffer> <esc> <Cmd>call jobstop(&channel)<CR>", TERM_FOCUS, true);
|
||||
do_cmdline_cmd("autocmd TermClose <buffer> "
|
||||
" if !v:event.status |"
|
||||
" exec 'bdelete! ' .. expand('<abuf>') |"
|
||||
" endif");
|
||||
add_map((char_u *)"<buffer> <esc> <Cmd>bdelete!<CR>", TERM_FOCUS, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1944,10 +1944,9 @@ static void didset_options(void)
|
||||
(void)did_set_spell_option(true);
|
||||
// set cedit_key
|
||||
(void)check_cedit();
|
||||
briopt_check(curwin);
|
||||
// initialize the table for 'breakat'.
|
||||
fill_breakat_flags();
|
||||
fill_culopt_flags(NULL, curwin);
|
||||
didset_window_options(curwin);
|
||||
}
|
||||
|
||||
// More side effects of setting options.
|
||||
@@ -2953,7 +2952,7 @@ ambw_end:
|
||||
}
|
||||
} else if (varp == &curwin->w_p_fdc || varp == &curwin->w_allbuf_opt.wo_fdc) {
|
||||
// 'foldcolumn'
|
||||
if (check_opt_strings(*varp, p_fdc_values, false) != OK) {
|
||||
if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) {
|
||||
errmsg = e_invarg;
|
||||
}
|
||||
} else if (varp == &p_pt) {
|
||||
@@ -3332,6 +3331,9 @@ static int int_cmp(const void *a, const void *b)
|
||||
/// @return OK when the value is valid, FAIL otherwise
|
||||
int check_signcolumn(char_u *val)
|
||||
{
|
||||
if (*val == NUL) {
|
||||
return FAIL;
|
||||
}
|
||||
// check for basic match
|
||||
if (check_opt_strings(val, p_scl_values, false) == OK) {
|
||||
return OK;
|
||||
@@ -6004,6 +6006,7 @@ void win_copy_options(win_T *wp_from, win_T *wp_to)
|
||||
{
|
||||
copy_winopt(&wp_from->w_onebuf_opt, &wp_to->w_onebuf_opt);
|
||||
copy_winopt(&wp_from->w_allbuf_opt, &wp_to->w_allbuf_opt);
|
||||
didset_window_options(wp_to);
|
||||
}
|
||||
|
||||
/// Copy the options from one winopt_T to another.
|
||||
|
@@ -658,7 +658,8 @@ static int qf_get_next_str_line(qfstate_T *state)
|
||||
state->linebuf = IObuff;
|
||||
state->linelen = len;
|
||||
}
|
||||
STRLCPY(state->linebuf, p_str, state->linelen + 1);
|
||||
memcpy(state->linebuf, p_str, state->linelen);
|
||||
state->linebuf[state->linelen] = '\0';
|
||||
|
||||
// Increment using len in order to discard the rest of the line if it
|
||||
// exceeds LINE_MAXLEN.
|
||||
|
@@ -1692,7 +1692,7 @@ static void win_update(win_T *wp, Providers *providers)
|
||||
if (eof) { // we hit the end of the file
|
||||
wp->w_botline = buf->b_ml.ml_line_count + 1;
|
||||
j = win_get_fill(wp, wp->w_botline);
|
||||
if (j > 0 && !wp->w_botfill) {
|
||||
if (j > 0 && !wp->w_botfill && row < wp->w_grid.Rows) {
|
||||
// Display filler text below last line. win_line() will check
|
||||
// for ml_line_count+1 and only draw filler lines
|
||||
foldinfo_T info = FOLDINFO_INIT;
|
||||
@@ -2843,9 +2843,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
|
||||
} else if (wp->w_p_cul
|
||||
&& lnum == wp->w_cursor.lnum
|
||||
&& (wp->w_p_culopt_flags & CULOPT_NBR)
|
||||
&& (row == startrow
|
||||
|| wp->w_p_culopt_flags & CULOPT_LINE)
|
||||
&& filler_todo == 0) {
|
||||
&& (row == startrow + filler_lines
|
||||
|| (row > startrow + filler_lines
|
||||
&& wp->w_p_culopt_flags & CULOPT_LINE))) {
|
||||
// When 'cursorline' is set highlight the line number of
|
||||
// the current line differently.
|
||||
// When 'cursorlineopt' has "screenline" only highlight
|
||||
|
@@ -5248,6 +5248,9 @@ search_line:
|
||||
if (depth == -1) {
|
||||
// match in current file
|
||||
if (l_g_do_tagpreview != 0) {
|
||||
if (!win_valid(curwin_save)) {
|
||||
break;
|
||||
}
|
||||
if (!GETFILE_SUCCESS(getfile(curwin_save->w_buffer->b_fnum, NULL,
|
||||
NULL, true, lnum, false))) {
|
||||
break; // failed to jump to file
|
||||
|
@@ -1466,6 +1466,17 @@ static void refresh_scrollback(Terminal *term, buf_T *buf)
|
||||
int width, height;
|
||||
vterm_get_size(term->vt, &height, &width);
|
||||
|
||||
// May still have pending scrollback after increase in terminal height if the
|
||||
// scrollback wasn't refreshed in time; append these to the top of the buffer.
|
||||
int row_offset = term->sb_pending;
|
||||
while (term->sb_pending > 0 && buf->b_ml.ml_line_count < height) {
|
||||
fetch_row(term, term->sb_pending - row_offset - 1, width);
|
||||
ml_append(0, (uint8_t *)term->textbuf, 0, false);
|
||||
appended_lines(0, 1);
|
||||
term->sb_pending--;
|
||||
}
|
||||
|
||||
row_offset -= term->sb_pending;
|
||||
while (term->sb_pending > 0) {
|
||||
// This means that either the window height has decreased or the screen
|
||||
// became full and libvterm had to push all rows up. Convert the first
|
||||
@@ -1476,7 +1487,7 @@ static void refresh_scrollback(Terminal *term, buf_T *buf)
|
||||
ml_delete(1, false);
|
||||
deleted_lines(1, 1);
|
||||
}
|
||||
fetch_row(term, -term->sb_pending, width);
|
||||
fetch_row(term, -term->sb_pending - row_offset, width);
|
||||
int buf_index = (int)buf->b_ml.ml_line_count - height;
|
||||
ml_append(buf_index, (uint8_t *)term->textbuf, 0, false);
|
||||
appended_lines(buf_index, 1);
|
||||
|
@@ -33,7 +33,7 @@ if has('timers')
|
||||
let g:triggered = 0
|
||||
au CursorHoldI * let g:triggered += 1
|
||||
set updatetime=20
|
||||
call timer_start(LoadAdjust(100), 'ExitInsertMode')
|
||||
call timer_start(LoadAdjust(200), 'ExitInsertMode')
|
||||
call feedkeys('a', 'x!')
|
||||
call assert_equal(1, g:triggered)
|
||||
unlet g:triggered
|
||||
@@ -1897,6 +1897,26 @@ func Test_autocmd_CmdWinEnter()
|
||||
call delete(filename)
|
||||
endfunc
|
||||
|
||||
func Test_autocmd_was_using_freed_memory()
|
||||
pedit xx
|
||||
n x
|
||||
augroup winenter
|
||||
au WinEnter * if winnr('$') > 2 | quit | endif
|
||||
augroup END
|
||||
" Nvim needs large 'winwidth' and 'nowinfixwidth' to crash
|
||||
set winwidth=99999 nowinfixwidth
|
||||
split
|
||||
|
||||
augroup winenter
|
||||
au! WinEnter
|
||||
augroup END
|
||||
|
||||
set winwidth& winfixwidth&
|
||||
bwipe xx
|
||||
bwipe x
|
||||
pclose
|
||||
endfunc
|
||||
|
||||
func Test_FileChangedShell_reload()
|
||||
if !has('unix')
|
||||
return
|
||||
@@ -2125,6 +2145,19 @@ func Test_autocmd_closes_window()
|
||||
au! BufWinLeave
|
||||
endfunc
|
||||
|
||||
func Test_autocmd_quit_psearch()
|
||||
sn aa bb
|
||||
augroup aucmd_win_test
|
||||
au!
|
||||
au BufEnter,BufLeave,BufNew,WinEnter,WinLeave,WinNew * if winnr('$') > 1 | q | endif
|
||||
augroup END
|
||||
ps /
|
||||
|
||||
augroup aucmd_win_test
|
||||
au!
|
||||
augroup END
|
||||
endfunc
|
||||
|
||||
func Test_autocmd_closing_cmdwin()
|
||||
au BufWinLeave * nested q
|
||||
call assert_fails("norm 7q?\n", 'E855:')
|
||||
|
@@ -1017,6 +1017,32 @@ func Test_diff_with_cursorline()
|
||||
call delete('Xtest_diff_cursorline')
|
||||
endfunc
|
||||
|
||||
func Test_diff_with_cursorline_number()
|
||||
CheckScreendump
|
||||
|
||||
let lines =<< trim END
|
||||
hi CursorLine ctermbg=red ctermfg=white
|
||||
hi CursorLineNr ctermbg=white ctermfg=black cterm=underline
|
||||
set cursorline number
|
||||
call setline(1, ["baz", "foo", "foo", "bar"])
|
||||
2
|
||||
vnew
|
||||
call setline(1, ["foo", "foo", "bar"])
|
||||
windo diffthis
|
||||
1wincmd w
|
||||
END
|
||||
call writefile(lines, 'Xtest_diff_cursorline_number')
|
||||
let buf = RunVimInTerminal('-S Xtest_diff_cursorline_number', {})
|
||||
|
||||
call VerifyScreenDump(buf, 'Test_diff_with_cursorline_number_01', {})
|
||||
call term_sendkeys(buf, ":set cursorlineopt=number\r")
|
||||
call VerifyScreenDump(buf, 'Test_diff_with_cursorline_number_02', {})
|
||||
|
||||
" clean up
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('Xtest_diff_cursorline_number')
|
||||
endfunc
|
||||
|
||||
func Test_diff_with_cursorline_breakindent()
|
||||
CheckScreendump
|
||||
|
||||
|
@@ -1,6 +1,8 @@
|
||||
" Tests for various Ex commands.
|
||||
|
||||
source check.vim
|
||||
source shared.vim
|
||||
source term_util.vim
|
||||
|
||||
func Test_ex_delete()
|
||||
new
|
||||
@@ -122,6 +124,27 @@ func Test_append_cmd()
|
||||
close!
|
||||
endfunc
|
||||
|
||||
func Test_append_cmd_empty_buf()
|
||||
CheckRunVimInTerminal
|
||||
let lines =<< trim END
|
||||
func Timer(timer)
|
||||
append
|
||||
aaaaa
|
||||
bbbbb
|
||||
.
|
||||
endfunc
|
||||
call timer_start(10, 'Timer')
|
||||
END
|
||||
call writefile(lines, 'Xtest_append_cmd_empty_buf')
|
||||
let buf = RunVimInTerminal('-S Xtest_append_cmd_empty_buf', {'rows': 6})
|
||||
call WaitForAssert({-> assert_equal('bbbbb', term_getline(buf, 2))})
|
||||
call WaitForAssert({-> assert_equal('aaaaa', term_getline(buf, 1))})
|
||||
|
||||
" clean up
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('Xtest_append_cmd_empty_buf')
|
||||
endfunc
|
||||
|
||||
" Test for the :insert command
|
||||
func Test_insert_cmd()
|
||||
set noautoindent " test assumes noautoindent, but it's on by default in Nvim
|
||||
@@ -151,6 +174,27 @@ func Test_insert_cmd()
|
||||
close!
|
||||
endfunc
|
||||
|
||||
func Test_insert_cmd_empty_buf()
|
||||
CheckRunVimInTerminal
|
||||
let lines =<< trim END
|
||||
func Timer(timer)
|
||||
insert
|
||||
aaaaa
|
||||
bbbbb
|
||||
.
|
||||
endfunc
|
||||
call timer_start(10, 'Timer')
|
||||
END
|
||||
call writefile(lines, 'Xtest_insert_cmd_empty_buf')
|
||||
let buf = RunVimInTerminal('-S Xtest_insert_cmd_empty_buf', {'rows': 6})
|
||||
call WaitForAssert({-> assert_equal('bbbbb', term_getline(buf, 2))})
|
||||
call WaitForAssert({-> assert_equal('aaaaa', term_getline(buf, 1))})
|
||||
|
||||
" clean up
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('Xtest_insert_cmd_empty_buf')
|
||||
endfunc
|
||||
|
||||
" Test for the :change command
|
||||
func Test_change_cmd()
|
||||
set noautoindent " test assumes noautoindent, but it's on by default in Nvim
|
||||
|
@@ -204,6 +204,7 @@ let s:filename_checks = {
|
||||
\ 'gnash': ['gnashrc', '.gnashrc', 'gnashpluginrc', '.gnashpluginrc'],
|
||||
\ 'gnuplot': ['file.gpi'],
|
||||
\ 'go': ['file.go'],
|
||||
\ 'gomod': ['go.mod'],
|
||||
\ 'gp': ['file.gp', '.gprc'],
|
||||
\ 'gpg': ['/.gnupg/options', '/.gnupg/gpg.conf', '/usr/any/gnupg/options.skel', 'any/.gnupg/gpg.conf', 'any/.gnupg/options', 'any/usr/any/gnupg/options.skel'],
|
||||
\ 'grads': ['file.gs'],
|
||||
|
@@ -1483,6 +1483,10 @@ func Test_getchar()
|
||||
call assert_equal('', getcharstr(0))
|
||||
call assert_equal('', getcharstr(1))
|
||||
|
||||
call feedkeys("\<M-F2>", '')
|
||||
call assert_equal("\<M-F2>", getchar(0))
|
||||
call assert_equal(0, getchar(0))
|
||||
|
||||
call setline(1, 'xxxx')
|
||||
" call test_setmouse(1, 3)
|
||||
" let v:mouse_win = 9
|
||||
|
@@ -597,6 +597,31 @@ func Test_cursorline_with_visualmode()
|
||||
call delete('Xtest_cursorline_with_visualmode')
|
||||
endfunc
|
||||
|
||||
func Test_colorcolumn()
|
||||
CheckScreendump
|
||||
|
||||
" check that setting 'colorcolumn' when entering a buffer works
|
||||
let lines =<< trim END
|
||||
split
|
||||
edit X
|
||||
call setline(1, ["1111111111","22222222222","3333333333"])
|
||||
set nomodified
|
||||
set colorcolumn=3,9
|
||||
set number cursorline cursorlineopt=number
|
||||
wincmd w
|
||||
buf X
|
||||
END
|
||||
call writefile(lines, 'Xtest_colorcolumn')
|
||||
let buf = RunVimInTerminal('-S Xtest_colorcolumn', {'rows': 10})
|
||||
call term_sendkeys(buf, ":\<CR>")
|
||||
call term_wait(buf)
|
||||
call VerifyScreenDump(buf, 'Test_colorcolumn_1', {})
|
||||
|
||||
" clean up
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('Xtest_colorcolumn')
|
||||
endfunc
|
||||
|
||||
func Test_colorcolumn_bri()
|
||||
CheckScreendump
|
||||
|
||||
|
@@ -379,4 +379,27 @@ func Test_timer_invalid_callback()
|
||||
call assert_fails('call timer_start(0, "0")', 'E921')
|
||||
endfunc
|
||||
|
||||
func Test_timer_using_win_execute_undo_sync()
|
||||
let bufnr1 = bufnr()
|
||||
new
|
||||
let g:bufnr2 = bufnr()
|
||||
let g:winid = win_getid()
|
||||
exe "buffer " .. bufnr1
|
||||
wincmd w
|
||||
call setline(1, ['test'])
|
||||
autocmd InsertEnter * call timer_start(100, { -> win_execute(g:winid, 'buffer ' .. g:bufnr2) })
|
||||
call timer_start(200, { -> feedkeys("\<CR>bbbb\<Esc>") })
|
||||
call feedkeys("Oaaaa", 'x!t')
|
||||
" will hang here until the second timer fires
|
||||
call assert_equal(['aaaa', 'bbbb', 'test'], getline(1, '$'))
|
||||
undo
|
||||
call assert_equal(['test'], getline(1, '$'))
|
||||
|
||||
bwipe!
|
||||
bwipe!
|
||||
unlet g:winid
|
||||
unlet g:bufnr2
|
||||
au! InsertEnter
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@@ -1482,8 +1482,6 @@ static void win_init(win_T *newp, win_T *oldp, int flags)
|
||||
copyFoldingState(oldp, newp);
|
||||
|
||||
win_init_some(newp, oldp);
|
||||
|
||||
didset_window_options(newp);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4525,6 +4523,7 @@ static void win_enter_ext(win_T *const wp, const int flags)
|
||||
|
||||
fix_current_dir();
|
||||
|
||||
// Careful: autocommands may close the window and make "wp" invalid
|
||||
if (flags & WEE_TRIGGER_NEW_AUTOCMDS) {
|
||||
apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
|
||||
}
|
||||
@@ -4558,7 +4557,7 @@ static void win_enter_ext(win_T *const wp, const int flags)
|
||||
}
|
||||
|
||||
// set window width to desired minimal value
|
||||
if (curwin->w_width < p_wiw && !curwin->w_p_wfw && !wp->w_floating) {
|
||||
if (curwin->w_width < p_wiw && !curwin->w_p_wfw && !curwin->w_floating) {
|
||||
win_setwidth((int)p_wiw);
|
||||
}
|
||||
|
||||
|
@@ -116,7 +116,7 @@ Filtering Tests
|
||||
|
||||
### Filter by name
|
||||
|
||||
Another filter method is by setting a pattern of test name to `TEST_FILTER`.
|
||||
Another filter method is by setting a pattern of test name to `TEST_FILTER` or `TEST_FILTER_OUT`.
|
||||
|
||||
``` lua
|
||||
it('foo api',function()
|
||||
@@ -131,6 +131,10 @@ To run only test with filter name:
|
||||
|
||||
TEST_FILTER='foo.*api' make functionaltest
|
||||
|
||||
To run all tests except ones matching a filter:
|
||||
|
||||
TEST_FILTER_OUT='foo.*api' make functionaltest
|
||||
|
||||
### Filter by file
|
||||
|
||||
To run a *specific* unit test:
|
||||
|
@@ -104,10 +104,10 @@ describe('API/extmarks', function()
|
||||
it("can end extranges past final newline using end_col = 0", function()
|
||||
set_extmark(ns, marks[1], 0, 0, {
|
||||
end_col = 0,
|
||||
end_line = 1
|
||||
end_row = 1
|
||||
})
|
||||
eq("end_col value outside range",
|
||||
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_line = 1 }))
|
||||
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 }))
|
||||
end)
|
||||
|
||||
it('adds, updates and deletes marks', function()
|
||||
@@ -1424,6 +1424,14 @@ describe('API/extmarks', function()
|
||||
eq({ {1, 0, 0}, {2, 0, 8} },
|
||||
meths.buf_get_extmarks(0, ns, 0, -1, {}))
|
||||
end)
|
||||
|
||||
it('can accept "end_row" or "end_line" #16548', function()
|
||||
set_extmark(ns, marks[1], 0, 0, {
|
||||
end_col = 0,
|
||||
end_line = 1
|
||||
})
|
||||
eq({ {1, 0, 0, { end_col = 0, end_row = 1 }} }, get_extmarks(ns, 0, -1, {details=true}))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('Extmarks buffer api with many marks', function()
|
||||
|
@@ -33,6 +33,29 @@ describe('K', function()
|
||||
feed('i'..test_file..'<ESC>K')
|
||||
retry(nil, nil, function() eq(1, eval('filereadable("'..test_file..'")')) end)
|
||||
eq({'fnord'}, eval("readfile('"..test_file.."')"))
|
||||
-- Confirm that Neovim is still in terminal mode after K is pressed (#16692).
|
||||
helpers.sleep(500)
|
||||
eq('t', eval('mode()'))
|
||||
feed('<space>') -- Any key, not just <space>, can be used here to escape.
|
||||
eq('n', eval('mode()'))
|
||||
end)
|
||||
|
||||
it("<esc> kills the buffer for a running 'keywordprg' command", function()
|
||||
helpers.source('set keywordprg=less')
|
||||
eval('writefile(["hello", "world"], "' .. test_file .. '")')
|
||||
feed('i' .. test_file .. '<esc>K')
|
||||
eq('t', eval('mode()'))
|
||||
-- Confirm that an arbitrary keypress doesn't escape (i.e., the process is
|
||||
-- still running). If the process were no longer running, an arbitrary
|
||||
-- keypress would escape.
|
||||
helpers.sleep(500)
|
||||
feed('<space>')
|
||||
eq('t', eval('mode()'))
|
||||
-- Confirm that <esc> kills the buffer for the running command.
|
||||
local bufnr = eval('bufnr()')
|
||||
feed('<esc>')
|
||||
eq('n', eval('mode()'))
|
||||
helpers.neq(bufnr, eval('bufnr()'))
|
||||
end)
|
||||
|
||||
end)
|
||||
|
@@ -1,23 +1,26 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local eq = helpers.eq
|
||||
local dedent = helpers.dedent
|
||||
local exec = helpers.exec
|
||||
local feed = helpers.feed
|
||||
local clear = helpers.clear
|
||||
local funcs = helpers.funcs
|
||||
local command = helpers.command
|
||||
local curbufmeths = helpers.curbufmeths
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
curbufmeths.set_lines(0, 1, true, { 'foo', 'bar', 'baz' })
|
||||
end)
|
||||
|
||||
local buffer_contents = function()
|
||||
return curbufmeths.get_lines(0, -1, false)
|
||||
end
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
|
||||
local cmdtest = function(cmd, prep, ret1)
|
||||
describe(':' .. cmd, function()
|
||||
before_each(function()
|
||||
clear()
|
||||
curbufmeths.set_lines(0, 1, true, { 'foo', 'bar', 'baz' })
|
||||
end)
|
||||
|
||||
local buffer_contents = function()
|
||||
return curbufmeths.get_lines(0, -1, false)
|
||||
end
|
||||
|
||||
it(cmd .. 's' .. prep .. ' the current line by default', function()
|
||||
command(cmd .. '\nabc\ndef\n')
|
||||
eq(ret1, buffer_contents())
|
||||
@@ -52,3 +55,52 @@ end
|
||||
cmdtest('insert', ' before', { 'abc', 'def', 'foo', 'bar', 'baz' })
|
||||
cmdtest('append', ' after', { 'foo', 'abc', 'def', 'bar', 'baz' })
|
||||
cmdtest('change', '', { 'abc', 'def', 'bar', 'baz' })
|
||||
|
||||
describe('the first line is redrawn correctly after inserting text in an empty buffer', function()
|
||||
local screen
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = Screen.new(20, 8)
|
||||
screen:set_default_attr_ids({
|
||||
[1] = {bold = true, foreground = Screen.colors.Blue},
|
||||
[2] = {bold = true, reverse = true},
|
||||
})
|
||||
screen:attach()
|
||||
end)
|
||||
|
||||
it('using :append', function()
|
||||
exec(dedent([[
|
||||
append
|
||||
aaaaa
|
||||
bbbbb
|
||||
.]]))
|
||||
screen:expect([[
|
||||
aaaaa |
|
||||
^bbbbb |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('using :insert', function()
|
||||
exec(dedent([[
|
||||
insert
|
||||
aaaaa
|
||||
bbbbb
|
||||
.]]))
|
||||
screen:expect([[
|
||||
aaaaa |
|
||||
^bbbbb |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
@@ -195,10 +195,10 @@ describe('memory usage', function()
|
||||
local after = monitor_memory_usage(pid)
|
||||
source('bwipe!')
|
||||
poke_eventloop()
|
||||
-- Allow for an increase of 5% in memory usage, which accommodates minor fluctuation,
|
||||
-- Allow for an increase of 10% in memory usage, which accommodates minor fluctuation,
|
||||
-- but is small enough that if memory were not released (prior to PR #14884), the test
|
||||
-- would fail.
|
||||
local upper = before.last * 1.05
|
||||
local upper = before.last * 1.10
|
||||
check_result({before=before, after=after}, pcall(ok, after.last <= upper))
|
||||
end)
|
||||
end)
|
||||
|
@@ -83,4 +83,9 @@ describe('set', function()
|
||||
Press ENTER or type command to continue^ |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('foldcolumn and signcolumn to empty string is disallowed', function()
|
||||
matches('E474: Invalid argument: fdc=', exc_exec('set fdc='))
|
||||
matches('E474: Invalid argument: scl=', exc_exec('set scl='))
|
||||
end)
|
||||
end)
|
||||
|
@@ -1343,7 +1343,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = "We're no strangers to love..."})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header = "We're no strangers to love..."})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@@ -1355,7 +1355,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = {'You know the rules', 'Search'}})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header = {'You know the rules', 'Search'}})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@@ -1370,7 +1370,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = false, scope="buffer"})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header = false, scope="buffer"})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@@ -1387,7 +1387,7 @@ describe('vim.diagnostic', function()
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
vim.api.nvim_win_set_cursor(0, {2, 1})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header=false})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@@ -1402,7 +1402,7 @@ describe('vim.diagnostic', function()
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
vim.api.nvim_win_set_cursor(0, {1, 1})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false, pos=1})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header=false, pos=1})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@@ -1419,7 +1419,7 @@ describe('vim.diagnostic', function()
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
vim.api.nvim_win_set_cursor(0, {2, 2})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false, scope="cursor"})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header=false, scope="cursor"})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@@ -1434,7 +1434,7 @@ describe('vim.diagnostic', function()
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
vim.api.nvim_win_set_cursor(0, {1, 1})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false, scope="cursor", pos={1,3}})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header=false, scope="cursor", pos={1,3}})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@@ -1449,7 +1449,7 @@ describe('vim.diagnostic', function()
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
vim.api.nvim_win_set_cursor(0, {1, 1})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false, scope="cursor", pos={0,first_line_len}})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header=false, scope="cursor", pos={0,first_line_len}})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@@ -1665,7 +1665,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = false, scope = "buffer"})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header = false, scope = "buffer"})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@@ -1678,7 +1678,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = false, scope = "buffer", prefix = ""})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header = false, scope = "buffer", prefix = ""})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@@ -1691,7 +1691,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({
|
||||
header = false,
|
||||
prefix = function(_, i, total)
|
||||
-- Only show a number if there is more than one diagnostic
|
||||
@@ -1712,7 +1712,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({
|
||||
header = false,
|
||||
prefix = function(_, i, total)
|
||||
-- Only show a number if there is more than one diagnostic
|
||||
@@ -1728,7 +1728,21 @@ describe('vim.diagnostic', function()
|
||||
]])
|
||||
|
||||
eq("Error executing lua: .../diagnostic.lua:0: prefix: expected 'string' or 'table' or 'function', got 42",
|
||||
pcall_err(exec_lua, [[ vim.diagnostic.open_float(0, { prefix = 42 }) ]]))
|
||||
pcall_err(exec_lua, [[ vim.diagnostic.open_float({ prefix = 42 }) ]]))
|
||||
end)
|
||||
|
||||
it('works with the old signature', function()
|
||||
eq({'1. Syntax error'}, exec_lua [[
|
||||
local diagnostics = {
|
||||
make_error("Syntax error", 0, 1, 0, 3),
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, { header = false })
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -1918,5 +1932,27 @@ describe('vim.diagnostic', function()
|
||||
return {show_called, hide_called}
|
||||
]])
|
||||
end)
|
||||
|
||||
it('triggers the autocommand when diagnostics are set', function()
|
||||
eq(1, exec_lua [[
|
||||
vim.g.diagnostic_autocmd_triggered = 0
|
||||
vim.cmd('autocmd DiagnosticChanged * let g:diagnostic_autocmd_triggered = 1')
|
||||
vim.api.nvim_buf_set_name(diagnostic_bufnr, "test | test")
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
|
||||
make_error('Diagnostic', 0, 0, 0, 0)
|
||||
})
|
||||
return vim.g.diagnostic_autocmd_triggered
|
||||
]])
|
||||
end)
|
||||
|
||||
it('triggers the autocommand when diagnostics are cleared', function()
|
||||
eq(1, exec_lua [[
|
||||
vim.g.diagnostic_autocmd_triggered = 0
|
||||
vim.cmd('autocmd DiagnosticChanged * let g:diagnostic_autocmd_triggered = 1')
|
||||
vim.api.nvim_buf_set_name(diagnostic_bufnr, "test | test")
|
||||
vim.diagnostic.reset(diagnostic_ns, diagnostic_bufnr)
|
||||
return vim.g.diagnostic_autocmd_triggered
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
@@ -155,6 +155,12 @@ describe('URI methods', function()
|
||||
return pcall(vim.uri_to_fname, 'not_an_uri.txt')
|
||||
]])
|
||||
end)
|
||||
|
||||
it('uri_to_fname should not treat comma as a scheme character', function()
|
||||
eq(false, exec_lua [[
|
||||
return pcall(vim.uri_to_fname, 'foo,://bar')
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
end)
|
||||
|
@@ -2200,6 +2200,40 @@ describe('lua stdlib', function()
|
||||
end)
|
||||
end)
|
||||
|
||||
it('vim.notify_once', function()
|
||||
local screen = Screen.new(60,5)
|
||||
screen:set_default_attr_ids({
|
||||
[0] = {bold=true, foreground=Screen.colors.Blue},
|
||||
[1] = {foreground=Screen.colors.Red},
|
||||
})
|
||||
screen:attach()
|
||||
screen:expect{grid=[[
|
||||
^ |
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
|
|
||||
]]}
|
||||
exec_lua [[vim.notify_once("I'll only tell you this once...", vim.log.levels.WARN)]]
|
||||
screen:expect{grid=[[
|
||||
^ |
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{1:I'll only tell you this once...} |
|
||||
]]}
|
||||
feed('<C-l>')
|
||||
screen:expect{grid=[[
|
||||
^ |
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
|
|
||||
]]}
|
||||
exec_lua [[vim.notify_once("I'll only tell you this once...")]]
|
||||
screen:expect_unchanged()
|
||||
end)
|
||||
|
||||
describe('vim.schedule_wrap', function()
|
||||
it('preserves argument lists', function()
|
||||
exec_lua [[
|
||||
|
@@ -156,7 +156,7 @@ describe('health.vim', function()
|
||||
test_plug.submodule_failed: require("test_plug.submodule_failed.health").check()
|
||||
========================================================================
|
||||
- ERROR: Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception:
|
||||
function health#check, line 24]])
|
||||
function health#check, line 20]])
|
||||
eq(expected, received)
|
||||
end)
|
||||
|
||||
@@ -167,7 +167,7 @@ describe('health.vim', function()
|
||||
broken: health#broken#check
|
||||
========================================================================
|
||||
- ERROR: Failed to run healthcheck for "broken" plugin. Exception:
|
||||
function health#check[24]..health#broken#check, line 1
|
||||
function health#check[20]..health#broken#check, line 1
|
||||
caused an error
|
||||
]])
|
||||
end)
|
||||
@@ -186,7 +186,7 @@ describe('health.vim', function()
|
||||
test_plug.submodule_failed: require("test_plug.submodule_failed.health").check()
|
||||
========================================================================
|
||||
- ERROR: Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception:
|
||||
function health#check, line 24]])
|
||||
function health#check, line 20]])
|
||||
eq(expected, received)
|
||||
end)
|
||||
|
||||
|
@@ -164,6 +164,201 @@ describe('incremental synchronization', function()
|
||||
}
|
||||
test_edit({"a"}, {"rb"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('deleting a line', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 0
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 12,
|
||||
text = ''
|
||||
}
|
||||
}
|
||||
test_edit({"hello world"}, {"dd"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('deleting an empty line', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 2
|
||||
}
|
||||
},
|
||||
rangeLength = 1,
|
||||
text = ''
|
||||
}
|
||||
}
|
||||
test_edit({"hello world", ""}, {"jdd"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('adding a line', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 0,
|
||||
text = 'hello world\n'
|
||||
}
|
||||
}
|
||||
test_edit({"hello world"}, {"yyp"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('adding an empty line', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 0,
|
||||
text = '\n'
|
||||
}
|
||||
}
|
||||
test_edit({"hello world"}, {"o"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
end)
|
||||
describe('multi line edit', function()
|
||||
it('deletion and insertion', function()
|
||||
local expected_text_changes = {
|
||||
-- delete "_fsda" from end of line 1
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 4,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 9,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 5,
|
||||
text = ''
|
||||
},
|
||||
-- delete "hello world\n" from line 2
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 2
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 3
|
||||
}
|
||||
},
|
||||
rangeLength = 12,
|
||||
text = ''
|
||||
},
|
||||
-- delete "1234" from beginning of line 2
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 2
|
||||
},
|
||||
['end'] = {
|
||||
character = 4,
|
||||
line = 2
|
||||
}
|
||||
},
|
||||
rangeLength = 4,
|
||||
text = ''
|
||||
},
|
||||
-- add " asdf" to end of line 1
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 4,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 4,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 0,
|
||||
text = ' asdf'
|
||||
},
|
||||
-- delete " asdf\n" from line 2
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 2
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 3
|
||||
}
|
||||
},
|
||||
rangeLength = 6,
|
||||
text = ''
|
||||
},
|
||||
-- undo entire deletion
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 4,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 9,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 5,
|
||||
text = "_fdsa\nhello world\n1234 asdf"
|
||||
},
|
||||
-- redo entire deletion
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 4,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 9,
|
||||
line = 3
|
||||
}
|
||||
},
|
||||
rangeLength = 27,
|
||||
text = ' asdf'
|
||||
},
|
||||
}
|
||||
local original_lines = {
|
||||
"\\begin{document}",
|
||||
"test_fdsa",
|
||||
"hello world",
|
||||
"1234 asdf",
|
||||
"\\end{document}"
|
||||
}
|
||||
test_edit(original_lines, {"jf_vejjbhhdu<C-R>"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('multi-operation edits', function()
|
||||
@@ -297,6 +492,80 @@ describe('incremental synchronization', function()
|
||||
}
|
||||
test_edit({"🔥"}, {"x"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('replacing a multibyte character with matching prefix', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 1,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 1,
|
||||
text = '⟩'
|
||||
}
|
||||
}
|
||||
-- ⟨ is e29fa8, ⟩ is e29fa9
|
||||
local original_lines = {
|
||||
"\\begin{document}",
|
||||
"⟨",
|
||||
"\\end{document}",
|
||||
}
|
||||
test_edit(original_lines, {"jr⟩"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('replacing a multibyte character with matching suffix', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 1,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 1,
|
||||
text = 'ḟ'
|
||||
}
|
||||
}
|
||||
-- ฟ is e0b89f, ḟ is e1b89f
|
||||
local original_lines = {
|
||||
"\\begin{document}",
|
||||
"ฟ",
|
||||
"\\end{document}",
|
||||
}
|
||||
test_edit(original_lines, {"jrḟ"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('inserting before a multibyte character', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 0,
|
||||
text = ' '
|
||||
}
|
||||
}
|
||||
local original_lines = {
|
||||
"\\begin{document}",
|
||||
"→",
|
||||
"\\end{document}",
|
||||
}
|
||||
test_edit(original_lines, {"ji "}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('deleting a multibyte character from a long line', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
|
@@ -301,6 +301,43 @@ describe('LSP', function()
|
||||
}
|
||||
end)
|
||||
|
||||
it('should detach buffer in response to nvim_buf_detach', function()
|
||||
local expected_handlers = {
|
||||
{NIL, {}, {method="shutdown", client_id=1}};
|
||||
{NIL, {}, {method="finish", client_id=1}};
|
||||
}
|
||||
local client
|
||||
test_rpc_server {
|
||||
test_name = "basic_finish";
|
||||
on_setup = function()
|
||||
exec_lua [[
|
||||
BUFFER = vim.api.nvim_create_buf(false, true)
|
||||
]]
|
||||
eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)"))
|
||||
eq(true, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)"))
|
||||
exec_lua [[
|
||||
vim.api.nvim_command(BUFFER.."bwipeout")
|
||||
]]
|
||||
end;
|
||||
on_init = function(_client)
|
||||
client = _client
|
||||
client.notify('finish')
|
||||
end;
|
||||
on_exit = function(code, signal)
|
||||
eq(0, code, "exit code", fake_lsp_logfile)
|
||||
eq(0, signal, "exit signal", fake_lsp_logfile)
|
||||
end;
|
||||
on_handler = function(err, result, ctx)
|
||||
eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
|
||||
if ctx.method == 'finish' then
|
||||
exec_lua("return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)")
|
||||
eq(false, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)"))
|
||||
client.stop()
|
||||
end
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
it('client should return settings via workspace/configuration handler', function()
|
||||
local expected_handlers = {
|
||||
{NIL, {}, {method="shutdown", client_id=1}};
|
||||
|
@@ -12,6 +12,8 @@ local curbufmeths = helpers.curbufmeths
|
||||
local nvim = helpers.nvim
|
||||
local feed_data = thelpers.feed_data
|
||||
local pcall_err = helpers.pcall_err
|
||||
local exec_lua = helpers.exec_lua
|
||||
local assert_alive = helpers.assert_alive
|
||||
|
||||
describe(':terminal scrollback', function()
|
||||
local screen
|
||||
@@ -527,3 +529,71 @@ describe("'scrollback' option", function()
|
||||
end)
|
||||
|
||||
end)
|
||||
|
||||
describe("pending scrollback line handling", function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = Screen.new(30, 7)
|
||||
screen:attach()
|
||||
screen:set_default_attr_ids {
|
||||
[1] = {foreground = Screen.colors.Brown},
|
||||
[2] = {reverse = true},
|
||||
[3] = {bold = true},
|
||||
}
|
||||
end)
|
||||
|
||||
it("does not crash after setting 'number' #14891", function()
|
||||
exec_lua [[
|
||||
local a = vim.api
|
||||
local buf = a.nvim_create_buf(true, true)
|
||||
local chan = a.nvim_open_term(buf, {})
|
||||
a.nvim_win_set_option(0, "number", true)
|
||||
a.nvim_chan_send(chan, ("a\n"):rep(11) .. "a")
|
||||
a.nvim_win_set_buf(0, buf)
|
||||
]]
|
||||
screen:expect [[
|
||||
{1: 1 }^a |
|
||||
{1: 2 } a |
|
||||
{1: 3 } a |
|
||||
{1: 4 } a |
|
||||
{1: 5 } a |
|
||||
{1: 6 } a |
|
||||
|
|
||||
]]
|
||||
feed('G')
|
||||
screen:expect [[
|
||||
{1: 7 } a |
|
||||
{1: 8 } a |
|
||||
{1: 9 } a |
|
||||
{1: 10 } a |
|
||||
{1: 11 } a |
|
||||
{1: 12 } ^a |
|
||||
|
|
||||
]]
|
||||
assert_alive()
|
||||
end)
|
||||
|
||||
it("does not crash after nvim_buf_call #14891", function()
|
||||
exec_lua [[
|
||||
local a = vim.api
|
||||
local bufnr = a.nvim_create_buf(false, true)
|
||||
a.nvim_buf_call(bufnr, function()
|
||||
vim.fn.termopen({"echo", ("hi\n"):rep(11)})
|
||||
end)
|
||||
a.nvim_win_set_buf(0, bufnr)
|
||||
vim.cmd("startinsert")
|
||||
]]
|
||||
screen:expect [[
|
||||
hi |
|
||||
hi |
|
||||
hi |
|
||||
|
|
||||
|
|
||||
[Process exited 0]{2: } |
|
||||
{3:-- TERMINAL --} |
|
||||
]]
|
||||
assert_alive()
|
||||
end)
|
||||
end)
|
||||
|
@@ -1031,6 +1031,69 @@ if (h->n_buckets < new_n_buckets) { // expand
|
||||
|
|
||||
]]}
|
||||
|
||||
screen:try_resize(50, 11)
|
||||
feed('gg')
|
||||
screen:expect{grid=[[
|
||||
^if (h->n_buckets < new_n_buckets) { // expand |
|
||||
khkey_t *new_keys = (khkey_t *)krealloc((void *)|
|
||||
h->keys, new_n_buckets * sizeof(khkey_t)); |
|
||||
h->keys = new_keys; |
|
||||
if (kh_is_map && val_size) { |
|
||||
char *new_vals = krealloc( h->vals_buf, new_n_|
|
||||
buckets * val_size); |
|
||||
h->vals_buf = new_vals; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
]]}
|
||||
|
||||
feed('G<C-E>')
|
||||
screen:expect{grid=[[
|
||||
khkey_t *new_keys = (khkey_t *)krealloc((void *)|
|
||||
h->keys, new_n_buckets * sizeof(khkey_t)); |
|
||||
h->keys = new_keys; |
|
||||
if (kh_is_map && val_size) { |
|
||||
char *new_vals = krealloc( h->vals_buf, new_n_|
|
||||
buckets * val_size); |
|
||||
h->vals_buf = new_vals; |
|
||||
} |
|
||||
^} |
|
||||
Grugg |
|
||||
|
|
||||
]]}
|
||||
|
||||
feed('gg')
|
||||
screen:expect{grid=[[
|
||||
^if (h->n_buckets < new_n_buckets) { // expand |
|
||||
khkey_t *new_keys = (khkey_t *)krealloc((void *)|
|
||||
h->keys, new_n_buckets * sizeof(khkey_t)); |
|
||||
h->keys = new_keys; |
|
||||
if (kh_is_map && val_size) { |
|
||||
char *new_vals = krealloc( h->vals_buf, new_n_|
|
||||
buckets * val_size); |
|
||||
h->vals_buf = new_vals; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
]]}
|
||||
|
||||
screen:try_resize(50, 12)
|
||||
feed('G')
|
||||
screen:expect{grid=[[
|
||||
if (h->n_buckets < new_n_buckets) { // expand |
|
||||
khkey_t *new_keys = (khkey_t *)krealloc((void *)|
|
||||
h->keys, new_n_buckets * sizeof(khkey_t)); |
|
||||
h->keys = new_keys; |
|
||||
if (kh_is_map && val_size) { |
|
||||
char *new_vals = krealloc( h->vals_buf, new_n_|
|
||||
buckets * val_size); |
|
||||
h->vals_buf = new_vals; |
|
||||
} |
|
||||
^} |
|
||||
Grugg |
|
||||
|
|
||||
]]}
|
||||
|
||||
meths.buf_del_extmark(0, ns, id)
|
||||
screen:expect{grid=[[
|
||||
if (h->n_buckets < new_n_buckets) { // expand |
|
||||
|
@@ -6,7 +6,7 @@ local clear = helpers.clear
|
||||
local command = helpers.command
|
||||
local insert = helpers.insert
|
||||
local write_file = helpers.write_file
|
||||
local source = helpers.source
|
||||
local exec = helpers.exec
|
||||
|
||||
describe('Diff mode screen', function()
|
||||
local fname = 'Xtest-functional-diff-screen-1'
|
||||
@@ -186,6 +186,19 @@ describe('Diff mode screen', function()
|
||||
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
|
||||
:set diffopt+=internal |
|
||||
]])
|
||||
|
||||
screen:try_resize(40, 9)
|
||||
screen:expect([[
|
||||
{1:+ }{5:^+-- 4 lines: 1···}{3:│}{1:+ }{5:+-- 4 lines: 1··}|
|
||||
{1: }5 {3:│}{1: }5 |
|
||||
{1: }6 {3:│}{1: }6 |
|
||||
{1: }7 {3:│}{1: }7 |
|
||||
{1: }8 {3:│}{1: }8 |
|
||||
{1: }9 {3:│}{1: }9 |
|
||||
{1: }10 {3:│}{1: }10 |
|
||||
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('Add a line at the end of file 1', function()
|
||||
@@ -232,6 +245,19 @@ describe('Diff mode screen', function()
|
||||
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
|
||||
:set diffopt+=internal |
|
||||
]])
|
||||
|
||||
screen:try_resize(40, 9)
|
||||
screen:expect([[
|
||||
{1:+ }{5:^+-- 4 lines: 1···}{3:│}{1:+ }{5:+-- 4 lines: 1··}|
|
||||
{1: }5 {3:│}{1: }5 |
|
||||
{1: }6 {3:│}{1: }6 |
|
||||
{1: }7 {3:│}{1: }7 |
|
||||
{1: }8 {3:│}{1: }8 |
|
||||
{1: }9 {3:│}{1: }9 |
|
||||
{1: }10 {3:│}{1: }10 |
|
||||
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('Add a line in the middle of file 2, remove on at the end of file 1', function()
|
||||
@@ -1049,10 +1075,8 @@ it('diff updates line numbers below filler lines', function()
|
||||
[9] = {background = Screen.colors.LightMagenta},
|
||||
[10] = {bold = true, foreground = Screen.colors.Brown},
|
||||
[11] = {foreground = Screen.colors.Brown},
|
||||
[12] = {foreground = Screen.colors.Brown, bold = true, background = Screen.colors.Red};
|
||||
[13] = {background = Screen.colors.Gray90};
|
||||
})
|
||||
source([[
|
||||
exec([[
|
||||
call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b'])
|
||||
vnew
|
||||
call setline(1, ['a', 'a', 'a', 'x', 'x', 'x', 'b', 'b', 'b', 'b', 'b'])
|
||||
@@ -1109,24 +1133,6 @@ it('diff updates line numbers below filler lines', function()
|
||||
{3:[No Name] [+] }{7:[No Name] [+] }|
|
||||
|
|
||||
]])
|
||||
command("set signcolumn number tgc cursorline cursorlineopt=number,line")
|
||||
command("hi CursorLineNr guibg=red")
|
||||
screen:expect{grid=[[
|
||||
{1: }a {3:│}{11: 2 }a |
|
||||
{1: }a {3:│}{11: 1 }a |
|
||||
{1: }a {3:│}{12:3 }{13:^a }|
|
||||
{1: }{8:x}{9: }{3:│}{11: 1 }{8:y}{9: }|
|
||||
{1: }{4:x }{3:│}{11: }{2:----------------}|
|
||||
{1: }{4:x }{3:│}{11: }{2:----------------}|
|
||||
{1: }b {3:│}{11: 2 }b |
|
||||
{1: }b {3:│}{11: 3 }b |
|
||||
{1: }b {3:│}{11: 4 }b |
|
||||
{1: }b {3:│}{11: 5 }b |
|
||||
{1: }b {3:│}{11: 6 }b |
|
||||
{6:~ }{3:│}{6:~ }|
|
||||
{3:[No Name] [+] }{7:[No Name] [+] }|
|
||||
signcolumn=auto |
|
||||
]]}
|
||||
end)
|
||||
|
||||
it('Align the filler lines when changing text in diff mode', function()
|
||||
@@ -1143,7 +1149,7 @@ it('Align the filler lines when changing text in diff mode', function()
|
||||
[7] = {foreground = Screen.colors.Blue1, bold = true};
|
||||
[8] = {reverse = true, bold = true};
|
||||
})
|
||||
source([[
|
||||
exec([[
|
||||
call setline(1, range(1, 15))
|
||||
vnew
|
||||
call setline(1, range(9, 15))
|
||||
|
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
local os = require('os')
|
||||
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
|
||||
local command = helpers.command
|
||||
local command, exec = helpers.command, helpers.exec
|
||||
local eval, exc_exec = helpers.eval, helpers.exc_exec
|
||||
local feed_command, eq = helpers.feed_command, helpers.eq
|
||||
local curbufmeths = helpers.curbufmeths
|
||||
@@ -822,7 +822,7 @@ describe("'listchars' highlight", function()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('CursorLine highlight', function()
|
||||
describe('CursorLine and CursorLineNr highlights', function()
|
||||
before_each(clear)
|
||||
|
||||
it('overridden by Error, ColorColumn if fg not set', function()
|
||||
@@ -1063,7 +1063,7 @@ describe('CursorLine highlight', function()
|
||||
]])
|
||||
end)
|
||||
|
||||
it('with split-windows in diff-mode', function()
|
||||
it('with split windows in diff mode', function()
|
||||
local screen = Screen.new(50,12)
|
||||
screen:set_default_attr_ids({
|
||||
[1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray},
|
||||
@@ -1075,7 +1075,6 @@ describe('CursorLine highlight', function()
|
||||
[7] = {background = Screen.colors.Red, foreground = Screen.colors.White},
|
||||
[8] = {bold = true, foreground = Screen.colors.Blue1},
|
||||
[9] = {bold = true, reverse = true},
|
||||
[10] = {bold = true},
|
||||
})
|
||||
screen:attach()
|
||||
|
||||
@@ -1152,8 +1151,162 @@ describe('CursorLine highlight', function()
|
||||
background = Screen.colors.Red},
|
||||
})
|
||||
end)
|
||||
|
||||
it('CursorLineNr shows correctly just below filler lines', function()
|
||||
local screen = Screen.new(50,12)
|
||||
screen:set_default_attr_ids({
|
||||
[1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray},
|
||||
[2] = {background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1},
|
||||
[3] = {reverse = true},
|
||||
[4] = {background = Screen.colors.LightBlue},
|
||||
[5] = {background = Screen.colors.Red, foreground = Screen.colors.White},
|
||||
[6] = {background = Screen.colors.White, bold = true, foreground = Screen.colors.Black},
|
||||
[7] = {bold = true, foreground = Screen.colors.Blue1},
|
||||
[8] = {bold = true, reverse = true},
|
||||
[9] = {foreground = Screen.colors.Brown},
|
||||
})
|
||||
screen:attach()
|
||||
|
||||
command('hi CursorLine guibg=red guifg=white')
|
||||
command('hi CursorLineNr guibg=white guifg=black gui=bold')
|
||||
command('set cursorline number')
|
||||
command('call setline(1, ["baz", "foo", "foo", "bar"])')
|
||||
feed('2gg0')
|
||||
command('vnew')
|
||||
command('call setline(1, ["foo", "foo", "bar"])')
|
||||
command('windo diffthis')
|
||||
command('1wincmd w')
|
||||
screen:expect([[
|
||||
{1: }{9: }{2:-------------------}{3:│}{1: }{9: 1 }{4:baz }|
|
||||
{1: }{6: 1 }{5:^foo }{3:│}{1: }{6: 2 }{5:foo }|
|
||||
{1: }{9: 2 }foo {3:│}{1: }{9: 3 }foo |
|
||||
{1: }{9: 3 }bar {3:│}{1: }{9: 4 }bar |
|
||||
{7:~ }{3:│}{7:~ }|
|
||||
{7:~ }{3:│}{7:~ }|
|
||||
{7:~ }{3:│}{7:~ }|
|
||||
{7:~ }{3:│}{7:~ }|
|
||||
{7:~ }{3:│}{7:~ }|
|
||||
{7:~ }{3:│}{7:~ }|
|
||||
{8:[No Name] [+] }{3:[No Name] [+] }|
|
||||
|
|
||||
]])
|
||||
command('set cursorlineopt=number')
|
||||
screen:expect([[
|
||||
{1: }{9: }{2:-------------------}{3:│}{1: }{9: 1 }{4:baz }|
|
||||
{1: }{6: 1 }^foo {3:│}{1: }{6: 2 }{5:foo }|
|
||||
{1: }{9: 2 }foo {3:│}{1: }{9: 3 }foo |
|
||||
{1: }{9: 3 }bar {3:│}{1: }{9: 4 }bar |
|
||||
{7:~ }{3:│}{7:~ }|
|
||||
{7:~ }{3:│}{7:~ }|
|
||||
{7:~ }{3:│}{7:~ }|
|
||||
{7:~ }{3:│}{7:~ }|
|
||||
{7:~ }{3:│}{7:~ }|
|
||||
{7:~ }{3:│}{7:~ }|
|
||||
{8:[No Name] [+] }{3:[No Name] [+] }|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('ColorColumn highlight', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = Screen.new(40, 15)
|
||||
Screen:set_default_attr_ids({
|
||||
[1] = {background = Screen.colors.LightRed}, -- ColorColumn
|
||||
[2] = {background = Screen.colors.Grey90}, -- CursorLine
|
||||
[3] = {foreground = Screen.colors.Brown}, -- LineNr
|
||||
[4] = {foreground = Screen.colors.Brown, bold = true}, -- CursorLineNr
|
||||
[5] = {foreground = Screen.colors.Blue, bold = true}, -- NonText
|
||||
-- NonText and ColorColumn
|
||||
[6] = {foreground = Screen.colors.Blue, background = Screen.colors.LightRed, bold = true},
|
||||
[7] = {reverse = true, bold = true}, -- StatusLine
|
||||
[8] = {reverse = true}, -- StatusLineNC
|
||||
})
|
||||
screen:attach()
|
||||
end)
|
||||
|
||||
it('when entering a buffer vim-patch:8.1.2073', function()
|
||||
exec([[
|
||||
set nohidden
|
||||
split
|
||||
edit X
|
||||
call setline(1, ["1111111111","22222222222","3333333333"])
|
||||
set nomodified
|
||||
set colorcolumn=3,9
|
||||
set number cursorline cursorlineopt=number
|
||||
wincmd w
|
||||
buf X
|
||||
]])
|
||||
screen:expect([[
|
||||
{4: 1 }11{1:1}11111{1:1}1 |
|
||||
{3: 2 }22{1:2}22222{1:2}22 |
|
||||
{3: 3 }33{1:3}33333{1:3}3 |
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{8:X }|
|
||||
{4: 1 }^11{1:1}11111{1:1}1 |
|
||||
{3: 2 }22{1:2}22222{1:2}22 |
|
||||
{3: 3 }33{1:3}33333{1:3}3 |
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{7:X }|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it("in 'breakindent' vim-patch:8.2.1689", function()
|
||||
exec([[
|
||||
call setline(1, 'The quick brown fox jumped over the lazy dogs')
|
||||
set co=40 linebreak bri briopt=shift:2 cc=40,41,43
|
||||
]])
|
||||
screen:expect([[
|
||||
^The quick brown fox jumped over the {1: }|
|
||||
{1: } {1:l}azy dogs |
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it("in 'showbreak' vim-patch:8.2.1689", function()
|
||||
exec([[
|
||||
call setline(1, 'The quick brown fox jumped over the lazy dogs')
|
||||
set co=40 showbreak=+++>\\ cc=40,41,43
|
||||
]])
|
||||
screen:expect([[
|
||||
^The quick brown fox jumped over the laz{1:y}|
|
||||
{6:+}{5:+}{6:+}{5:>\} dogs |
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
{5:~ }|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("MsgSeparator highlight and msgsep fillchar", function()
|
||||
local screen
|
||||
|
@@ -6,6 +6,7 @@ local insert = helpers.insert
|
||||
local eq = helpers.eq
|
||||
local eval = helpers.eval
|
||||
local iswin = helpers.iswin
|
||||
local funcs, meths, exec_lua = helpers.funcs, helpers.meths, helpers.exec_lua
|
||||
|
||||
describe('screen', function()
|
||||
local screen
|
||||
@@ -127,14 +128,67 @@ local function screen_tests(linegrid)
|
||||
end)
|
||||
|
||||
it('has correct default title with named file', function()
|
||||
local expected = (iswin() and 'myfile (C:\\mydir) - NVIM'
|
||||
or 'myfile (/mydir) - NVIM')
|
||||
local expected = (iswin() and 'myfile (C:\\mydir) - NVIM' or 'myfile (/mydir) - NVIM')
|
||||
command('set title')
|
||||
command(iswin() and 'file C:\\mydir\\myfile' or 'file /mydir/myfile')
|
||||
screen:expect(function()
|
||||
eq(expected, screen.title)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('is not changed by', function()
|
||||
local file1 = iswin() and 'C:\\mydir\\myfile1' or '/mydir/myfile1'
|
||||
local file2 = iswin() and 'C:\\mydir\\myfile2' or '/mydir/myfile2'
|
||||
local expected = (iswin() and 'myfile1 (C:\\mydir) - NVIM' or 'myfile1 (/mydir) - NVIM')
|
||||
local buf2
|
||||
|
||||
before_each(function()
|
||||
command('edit '..file1)
|
||||
buf2 = funcs.bufadd(file2)
|
||||
command('set title')
|
||||
end)
|
||||
|
||||
it('calling setbufvar() to set an option in a hidden buffer from i_CTRL-R', function()
|
||||
command([[inoremap <F2> <C-R>=setbufvar(]]..buf2..[[, '&autoindent', 1) ? '' : ''<CR>]])
|
||||
feed('i<F2><Esc>')
|
||||
command('redraw!')
|
||||
screen:expect(function()
|
||||
eq(expected, screen.title)
|
||||
end)
|
||||
end)
|
||||
|
||||
it('an RPC call to nvim_buf_set_option in a hidden buffer', function()
|
||||
meths.buf_set_option(buf2, 'autoindent', true)
|
||||
command('redraw!')
|
||||
screen:expect(function()
|
||||
eq(expected, screen.title)
|
||||
end)
|
||||
end)
|
||||
|
||||
it('a Lua callback calling nvim_buf_set_option in a hidden buffer', function()
|
||||
exec_lua(string.format([[
|
||||
vim.schedule(function()
|
||||
vim.api.nvim_buf_set_option(%d, 'autoindent', true)
|
||||
end)
|
||||
]], buf2))
|
||||
command('redraw!')
|
||||
screen:expect(function()
|
||||
eq(expected, screen.title)
|
||||
end)
|
||||
end)
|
||||
|
||||
it('a Lua callback calling nvim_buf_call in a hidden buffer', function()
|
||||
exec_lua(string.format([[
|
||||
vim.schedule(function()
|
||||
vim.api.nvim_buf_call(%d, function() end)
|
||||
end)
|
||||
]], buf2))
|
||||
command('redraw!')
|
||||
screen:expect(function()
|
||||
eq(expected, screen.title)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe(':set icon', function()
|
||||
|
51
test/functional/vimscript/screenpos_spec.lua
Normal file
51
test/functional/vimscript/screenpos_spec.lua
Normal file
@@ -0,0 +1,51 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
local clear, eq, meths = helpers.clear, helpers.eq, helpers.meths
|
||||
local command, funcs = helpers.command, helpers.funcs
|
||||
|
||||
before_each(clear)
|
||||
|
||||
describe('screenpos() function', function()
|
||||
it('works in floating window with border', function()
|
||||
local bufnr = meths.create_buf(false, true)
|
||||
local opts = {
|
||||
relative='editor',
|
||||
height=8,
|
||||
width=12,
|
||||
row=6,
|
||||
col=8,
|
||||
anchor='NW',
|
||||
style='minimal',
|
||||
border='none',
|
||||
focusable=1
|
||||
}
|
||||
local float = meths.open_win(bufnr, false, opts)
|
||||
command('redraw')
|
||||
local pos = funcs.screenpos(bufnr, 1, 1)
|
||||
eq(7, pos.row)
|
||||
eq(9, pos.col)
|
||||
|
||||
-- only left border
|
||||
opts.border = {'', '', '', '', '', '', '', '|'}
|
||||
meths.win_set_config(float, opts)
|
||||
command('redraw')
|
||||
pos = funcs.screenpos(bufnr, 1, 1)
|
||||
eq(7, pos.row)
|
||||
eq(10, pos.col)
|
||||
|
||||
-- only top border
|
||||
opts.border = {'', '_', '', '', '', '', '', ''}
|
||||
meths.win_set_config(float, opts)
|
||||
command('redraw')
|
||||
pos = funcs.screenpos(bufnr, 1, 1)
|
||||
eq(8, pos.row)
|
||||
eq(9, pos.col)
|
||||
|
||||
-- both left and top border
|
||||
opts.border = 'single'
|
||||
meths.win_set_config(float, opts)
|
||||
command('redraw')
|
||||
pos = funcs.screenpos(bufnr, 1, 1)
|
||||
eq(8, pos.row)
|
||||
eq(10, pos.col)
|
||||
end)
|
||||
end)
|
Reference in New Issue
Block a user