mirror of
https://github.com/neovim/neovim.git
synced 2024-12-23 20:55:18 -07:00
Compare commits
6 Commits
dc542a3374
...
85c29d24c3
Author | SHA1 | Date | |
---|---|---|---|
|
85c29d24c3 | ||
|
7121983c45 | ||
|
888a803755 | ||
|
07d5dc8938 | ||
|
f9eb68f340 | ||
|
6d3ff992ff |
@ -1126,6 +1126,9 @@ Lua module: vim.lsp.client *lsp-client*
|
||||
• {server_capabilities} (`lsp.ServerCapabilities?`) Response from the
|
||||
server sent on `initialize` describing the
|
||||
server's capabilities.
|
||||
• {server_info} (`lsp.ServerInfo?`) Response from the server
|
||||
sent on `initialize` describing information
|
||||
about the server.
|
||||
• {progress} (`vim.lsp.Client.Progress`) A ring buffer
|
||||
(|vim.ringbuf()|) containing progress messages
|
||||
sent by the server. See
|
||||
|
396
runtime/doc/lua-plugin.txt
Normal file
396
runtime/doc/lua-plugin.txt
Normal file
@ -0,0 +1,396 @@
|
||||
*lua-plugin.txt* Nvim
|
||||
|
||||
NVIM REFERENCE MANUAL
|
||||
|
||||
Guide to developing Lua plugins for Nvim
|
||||
|
||||
|
||||
Type |gO| to see the table of contents.
|
||||
|
||||
==============================================================================
|
||||
Introduction *lua-plugin*
|
||||
|
||||
This is a guide for getting started with Nvim plugin development. It is not
|
||||
intended as a set of rules, but as a collection of recommendations for good
|
||||
practices.
|
||||
|
||||
For a guide to using Lua in Nvim, please refer to |lua-guide|.
|
||||
|
||||
==============================================================================
|
||||
Type safety *lua-plugin-type-safety*
|
||||
|
||||
Lua, as a dynamically typed language, is great for configuration. It provides
|
||||
virtually immediate feedback.
|
||||
But for larger projects, this can be a double-edged sword, leaving your plugin
|
||||
susceptible to unexpected bugs at the wrong time.
|
||||
|
||||
You can leverage LuaCATS https://luals.github.io/wiki/annotations/
|
||||
annotations, along with lua-language-server https://luals.github.io/ to catch
|
||||
potential bugs in your CI before your plugin's users do.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Tools *lua-plugin-type-safety-tools*
|
||||
|
||||
- lua-typecheck-action https://github.com/marketplace/actions/lua-typecheck-action
|
||||
- luacheck https://github.com/lunarmodules/luacheck for additional linting
|
||||
|
||||
==============================================================================
|
||||
User commands *lua-plugin-user-commands*
|
||||
|
||||
Many users rely on command completion to discover available user commands. If
|
||||
a plugin pollutes the command namespace with lots of commands, this can
|
||||
quickly become overwhelming.
|
||||
|
||||
Example:
|
||||
|
||||
- `FooAction1 {arg}`
|
||||
- `FooAction2 {arg}`
|
||||
- `FooAction3`
|
||||
- `BarAction1`
|
||||
- `BarAction2`
|
||||
|
||||
Instead of doing this, consider gathering subcommands under scoped commands
|
||||
and implementing completions for each subcommand.
|
||||
|
||||
Example:
|
||||
|
||||
- `Foo action1 {arg}`
|
||||
- `Foo action2 {arg}`
|
||||
- `Foo action3`
|
||||
- `Bar action1`
|
||||
- `Bar action2`
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Subcommand completions example *lua-plugin-user-commands-completions-example*
|
||||
|
||||
In this example, we want to provide:
|
||||
|
||||
- Subcommand completions if the user has typed `:Foo ...`
|
||||
- Argument completions if they have typed `:Foo {subcommand}`
|
||||
|
||||
First, define a type for each subcommand, which has:
|
||||
|
||||
- An implementation: A function which is called when executing the subcommand.
|
||||
- An optional command completion callback, which takes the lead of the
|
||||
subcommand's arguments.
|
||||
|
||||
>lua
|
||||
---@class FooSubcommand
|
||||
---@field impl fun(args:string[], opts: table)
|
||||
---@field complete? fun(subcmd_arg_lead: string): string[]
|
||||
<
|
||||
Next, we define a table mapping subcommands to their implementations and
|
||||
completions:
|
||||
>lua
|
||||
---@type table<string, FooSubcommand>
|
||||
local subcommand_tbl = {
|
||||
action1 = {
|
||||
impl = function(args, opts)
|
||||
-- Implementation (args is a list of strings)
|
||||
end,
|
||||
-- This subcommand has no completions
|
||||
},
|
||||
action2 = {
|
||||
impl = function(args, opts)
|
||||
-- Implementation
|
||||
end,
|
||||
complete = function(subcmd_arg_lead)
|
||||
-- Simplified example
|
||||
local install_args = {
|
||||
"first",
|
||||
"second",
|
||||
"third",
|
||||
}
|
||||
return vim.iter(install_args)
|
||||
:filter(function(install_arg)
|
||||
-- If the user has typed `:Foo action2 fi`,
|
||||
-- this will match 'first'
|
||||
return install_arg:find(subcmd_arg_lead) ~= nil
|
||||
end)
|
||||
:totable()
|
||||
end,
|
||||
-- ...
|
||||
},
|
||||
}
|
||||
<
|
||||
Then, create a Lua function to implement the main command:
|
||||
>lua
|
||||
---@param opts table :h lua-guide-commands-create
|
||||
local function foo_cmd(opts)
|
||||
local fargs = opts.fargs
|
||||
local subcommand_key = fargs[1]
|
||||
-- Get the subcommand's arguments, if any
|
||||
local args = #fargs > 1 and vim.list_slice(fargs, 2, #fargs) or {}
|
||||
local subcommand = subcommand_tbl[subcommand_key]
|
||||
if not subcommand then
|
||||
vim.notify("Foo: Unknown command: " .. subcommand_key, vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
-- Invoke the subcommand
|
||||
subcommand.impl(args, opts)
|
||||
end
|
||||
<
|
||||
See also |lua-guide-commands-create|.
|
||||
|
||||
Finally, we register our command, along with the completions:
|
||||
>lua
|
||||
-- NOTE: the options will vary, based on your use case.
|
||||
vim.api.nvim_create_user_command("Foo", foo_cmd, {
|
||||
nargs = "+",
|
||||
desc = "My awesome command with subcommand completions",
|
||||
complete = function(arg_lead, cmdline, _)
|
||||
-- Get the subcommand.
|
||||
local subcmd_key, subcmd_arg_lead = cmdline:match("^Foo[!]*%s(%S+)%s(.*)$")
|
||||
if subcmd_key
|
||||
and subcmd_arg_lead
|
||||
and subcommand_tbl[subcmd_key]
|
||||
and subcommand_tbl[subcmd_key].complete
|
||||
then
|
||||
-- The subcommand has completions. Return them.
|
||||
return subcommand_tbl[subcmd_key].complete(subcmd_arg_lead)
|
||||
end
|
||||
-- Check if cmdline is a subcommand
|
||||
if cmdline:match("^Foo[!]*%s+%w*$") then
|
||||
-- Filter subcommands that match
|
||||
local subcommand_keys = vim.tbl_keys(subcommand_tbl)
|
||||
return vim.iter(subcommand_keys)
|
||||
:filter(function(key)
|
||||
return key:find(arg_lead) ~= nil
|
||||
end)
|
||||
:totable()
|
||||
end
|
||||
end,
|
||||
bang = true, -- If you want to support ! modifiers
|
||||
})
|
||||
<
|
||||
==============================================================================
|
||||
Keymaps *lua-plugin-keymaps*
|
||||
|
||||
Avoid creating keymaps automatically, unless they are not controversial. Doing
|
||||
so can easily lead to conflicts with user |mapping|s.
|
||||
|
||||
NOTE: An example for uncontroversial keymaps are buffer-local |mapping|s for
|
||||
specific file types or floating windows.
|
||||
|
||||
A common approach to allow keymap configuration is to define a declarative DSL
|
||||
https://en.wikipedia.org/wiki/Domain-specific_language via a `setup` function.
|
||||
|
||||
However, doing so means that
|
||||
|
||||
- You will have to implement and document it yourself.
|
||||
- Users will likely face inconsistencies if another plugin has a slightly
|
||||
different DSL.
|
||||
- |init.lua| scripts that call such a `setup` function may throw an error if
|
||||
the plugin is not installed or disabled.
|
||||
|
||||
As an alternative, you can provide |<Plug>| mappings to allow users to define
|
||||
their own keymaps with |vim.keymap.set()|.
|
||||
|
||||
- This requires one line of code in user configs.
|
||||
- Even if your plugin is not installed or disabled, creating the keymap won't
|
||||
throw an error.
|
||||
|
||||
Another option is to simply expose a Lua function or |user-commands|.
|
||||
|
||||
However, some benefits of |<Plug>| mappings over this are that you can
|
||||
|
||||
- Enforce options like `expr = true`.
|
||||
- Expose functionality only for specific |map-modes|.
|
||||
- Expose different behavior for different |map-modes| with a single |<Plug>|
|
||||
mapping, without adding impurity or complexity to the underlying Lua
|
||||
implementation.
|
||||
|
||||
NOTE: If you have a function that takes a large options table, creating lots
|
||||
of |<Plug>| mappings to expose all of its uses could become
|
||||
overwhelming. It may still be beneficial to create some for the most
|
||||
common ones.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Example *lua-plugin-plug-mapping-example*
|
||||
|
||||
In your plugin:
|
||||
>lua
|
||||
vim.keymap.set("n", "<Plug>(SayHello)", function()
|
||||
print("Hello from normal mode")
|
||||
end, { noremap = true })
|
||||
|
||||
vim.keymap.set("v", "<Plug>(SayHello)", function()
|
||||
print("Hello from visual mode")
|
||||
end, { noremap = true })
|
||||
<
|
||||
In the user's config:
|
||||
>lua
|
||||
vim.keymap.set({"n", "v"}, "<leader>h", "<Plug>(SayHello)")
|
||||
<
|
||||
==============================================================================
|
||||
Initialization *lua-plugin-initialization*
|
||||
|
||||
Newcomers to Lua plugin development will often put all initialization logic in
|
||||
a single `setup` function, which takes a table of options.
|
||||
If you do this, users will be forced to call this function in order to use
|
||||
your plugin, even if they are happy with the default configuration.
|
||||
|
||||
Strictly separated configuration and smart initialization allow your plugin to
|
||||
work out of the box.
|
||||
|
||||
NOTE: A well designed plugin has minimal impact on startup time.
|
||||
See also |lua-plugin-lazy-loading|.
|
||||
|
||||
Common approaches to a strictly separated configuration are:
|
||||
|
||||
- A Lua function, e.g. `setup(opts)` or `configure(opts)`, which only overrides the
|
||||
default configuration and does not contain any initialization logic.
|
||||
- A Vimscript compatible table (e.g. in the |vim.g| or |vim.b| namespace) that your
|
||||
plugin reads from and validates at initialization time.
|
||||
See also |lua-vim-variables|.
|
||||
|
||||
Typically, automatic initialization logic is done in a |plugin| or |ftplugin|
|
||||
script. See also |'runtimepath'|.
|
||||
|
||||
==============================================================================
|
||||
Lazy loading *lua-plugin-lazy-loading*
|
||||
|
||||
When it comes to initializing your plugin, assume your users may not be using
|
||||
a plugin manager that takes care of lazy loading for you.
|
||||
Making sure your plugin does not unnecessarily impact startup time is your
|
||||
responsibility. A plugin's functionality may evolve over time, potentially
|
||||
leading to breakage if users have to hack into the loading mechanisms.
|
||||
Furthermore, a plugin that implements its own lazy initialization properly will
|
||||
likely have less overhead than the mechanisms used by a plugin manager or user
|
||||
to load that plugin lazily.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Defer `require` calls *lua-plugin-lazy-loading-defer-require*
|
||||
|
||||
|plugin| scripts should not eagerly `require` Lua modules.
|
||||
|
||||
For example, instead of:
|
||||
>lua
|
||||
local foo = require("foo")
|
||||
vim.api.nvim_create_user_command("MyCommand", function()
|
||||
foo.do_something()
|
||||
end, {
|
||||
-- ...
|
||||
})
|
||||
<
|
||||
which will eagerly load the `foo` module and any other modules it imports
|
||||
eagerly, you can lazy load it by moving the `require` into the command's
|
||||
implementation.
|
||||
>lua
|
||||
vim.api.nvim_create_user_command("MyCommand", function()
|
||||
local foo = require("foo")
|
||||
foo.do_something()
|
||||
end, {
|
||||
-- ...
|
||||
})
|
||||
<
|
||||
NOTE: For a Vimscript alternative to `require`, see |autoload|.
|
||||
|
||||
NOTE: In case you are worried about eagerly creating user commands, autocommands
|
||||
or keymaps at startup:
|
||||
Plugin managers that provide abstractions for lazy-loading plugins on
|
||||
such events will need to create these themselves.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Filetype-specific functionality *lua-plugin-lazy-loading-filetype*
|
||||
|
||||
Consider making use of |filetype| for any functionality that is specific to a
|
||||
filetype, by putting the initialization logic in a `ftplugin/{filetype}.lua`
|
||||
script.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Example *lua-plugin-lazy-loading-filetype-example*
|
||||
|
||||
A plugin tailored to Rust development might have initialization in
|
||||
`ftplugin/rust.lua`:
|
||||
>lua
|
||||
if not vim.g.loaded_my_rust_plugin then
|
||||
-- Initialize
|
||||
end
|
||||
-- NOTE: Using `vim.g.loaded_` prevents the plugin from initializing twice
|
||||
-- and allows users to prevent plugins from loading
|
||||
-- (in both Lua and Vimscript).
|
||||
vim.g.loaded_my_rust_plugin = true
|
||||
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
-- do something specific to this buffer,
|
||||
-- e.g. add a |<Plug>| mapping or create a command
|
||||
vim.keymap.set("n", "<Plug>(MyPluginBufferAction)", function()
|
||||
print("Hello")
|
||||
end, { noremap = true, buffer = bufnr, })
|
||||
<
|
||||
==============================================================================
|
||||
Configuration *lua-plugin-configuration*
|
||||
|
||||
Once you have merged the default configuration with the user's config, you
|
||||
should validate configs.
|
||||
|
||||
Validations could include:
|
||||
|
||||
- Correct types, see |vim.validate()|
|
||||
- Unknown fields in the user config (e.g. due to typos).
|
||||
This can be tricky to implement, and may be better suited for a |health|
|
||||
check, to reduce overhead.
|
||||
|
||||
==============================================================================
|
||||
Troubleshooting *lua-plugin-troubleshooting*
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Health checks *lua-plugin-troubleshooting-health*
|
||||
|
||||
Provide health checks in `lua/{plugin}/health.lua`.
|
||||
|
||||
Some things to validate:
|
||||
|
||||
- User configuration
|
||||
- Proper initialization
|
||||
- Presence of Lua dependencies (e.g. other plugins)
|
||||
- Presence of external dependencies
|
||||
|
||||
See also |vim.health| and |health-dev|.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Minimal config template *lua-plugin-troubleshooting-minimal-config*
|
||||
|
||||
It can be useful to provide a template for a minimal configuration, along with
|
||||
a guide on how to use it to reproduce issues.
|
||||
|
||||
==============================================================================
|
||||
Versioning and releases *lua-plugin-versioning-releases*
|
||||
|
||||
Consider
|
||||
|
||||
- Using SemVer https://semver.org/ tags and releases to properly communicate
|
||||
bug fixes, new features, and breaking changes.
|
||||
- Automating versioning and releases in CI.
|
||||
- Publishing to luarocks https://luarocks.org, especially if your plugin
|
||||
has dependencies or components that need to be built; or if it could be a
|
||||
dependency for another plugin.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Further reading *lua-plugin-versioning-releases-further-reading*
|
||||
|
||||
- Luarocks <3 Nvim https://github.com/nvim-neorocks/sample-luarocks-plugin
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Tools *lua-plugin-versioning-releases-tools*
|
||||
|
||||
- luarocks-tag-release
|
||||
https://github.com/marketplace/actions/luarocks-tag-release
|
||||
- release-please-action
|
||||
https://github.com/marketplace/actions/release-please-action
|
||||
- semantic-release
|
||||
https://github.com/semantic-release/semantic-release
|
||||
|
||||
==============================================================================
|
||||
Documentation *lua-plugin-documentation*
|
||||
|
||||
Provide vimdoc (see |help-writing|), so that users can read your plugin's
|
||||
documentation in Nvim, by entering `:h {plugin}` in |command-mode|.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Tools *lua-plugin-documentation-tools*
|
||||
|
||||
- panvimdoc https://github.com/kdheepak/panvimdoc
|
||||
|
||||
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
|
@ -115,6 +115,7 @@ LSP
|
||||
• |vim.lsp.util.make_position_params()|, |vim.lsp.util.make_range_params()|
|
||||
and |vim.lsp.util.make_given_range_params()| now require the `position_encoding`
|
||||
parameter.
|
||||
• `:checkhealth vim.lsp` displays the server version (if available).
|
||||
|
||||
LUA
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -211,7 +211,7 @@ local function reuse_client_default(client, config)
|
||||
|
||||
for _, config_folder in ipairs(config_folders) do
|
||||
local found = false
|
||||
for _, client_folder in ipairs(client.workspace_folders) do
|
||||
for _, client_folder in ipairs(client.workspace_folders or {}) do
|
||||
if config_folder.uri == client_folder.uri then
|
||||
found = true
|
||||
break
|
||||
|
@ -174,6 +174,10 @@ local validate = vim.validate
|
||||
--- capabilities.
|
||||
--- @field server_capabilities lsp.ServerCapabilities?
|
||||
---
|
||||
--- Response from the server sent on `initialize` describing information about
|
||||
--- the server.
|
||||
--- @field server_info lsp.ServerInfo?
|
||||
---
|
||||
--- A ring buffer (|vim.ringbuf()|) containing progress messages
|
||||
--- sent by the server.
|
||||
--- @field progress vim.lsp.Client.Progress
|
||||
@ -556,6 +560,8 @@ function Client:initialize()
|
||||
self.offset_encoding = self.server_capabilities.positionEncoding
|
||||
end
|
||||
|
||||
self.server_info = result.serverInfo
|
||||
|
||||
if next(self.settings) then
|
||||
self:notify(ms.workspace_didChangeConfiguration, { settings = self.settings })
|
||||
end
|
||||
|
@ -40,6 +40,8 @@ local function check_active_clients()
|
||||
local clients = vim.lsp.get_clients()
|
||||
if next(clients) then
|
||||
for _, client in pairs(clients) do
|
||||
local server_version = vim.tbl_get(client, 'server_info', 'version')
|
||||
or '? (no serverInfo.version response)'
|
||||
local cmd ---@type string
|
||||
local ccmd = client.config.cmd
|
||||
if type(ccmd) == 'table' then
|
||||
@ -62,6 +64,7 @@ local function check_active_clients()
|
||||
end
|
||||
report_info(table.concat({
|
||||
string.format('%s (id: %d)', client.name, client.id),
|
||||
string.format('- Version: %s', server_version),
|
||||
dirs_info,
|
||||
string.format('- Command: %s', cmd),
|
||||
string.format('- Settings: %s', vim.inspect(client.settings, { newline = '\n ' })),
|
||||
|
@ -8,9 +8,9 @@ vim.api.nvim_create_user_command('Man', function(params)
|
||||
if params.bang then
|
||||
man.init_pager()
|
||||
else
|
||||
local ok, err = pcall(man.open_page, params.count, params.smods, params.fargs)
|
||||
if not ok then
|
||||
vim.notify(man.errormsg or err, vim.log.levels.ERROR)
|
||||
local err = man.open_page(params.count, params.smods, params.fargs)
|
||||
if err then
|
||||
vim.notify('man.lua: ' .. err, vim.log.levels.ERROR)
|
||||
end
|
||||
end
|
||||
end, {
|
||||
@ -31,6 +31,9 @@ vim.api.nvim_create_autocmd('BufReadCmd', {
|
||||
pattern = 'man://*',
|
||||
nested = true,
|
||||
callback = function(params)
|
||||
require('man').read_page(vim.fn.matchstr(params.match, 'man://\\zs.*'))
|
||||
local err = require('man').read_page(assert(params.match:match('man://(.*)')))
|
||||
if err then
|
||||
vim.notify('man.lua: ' .. err, vim.log.levels.ERROR)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
@ -229,10 +229,9 @@ static Object _call_function(String fn, Array args, dict_T *self, Arena *arena,
|
||||
funcexe.fe_selfdict = self;
|
||||
|
||||
TRY_WRAP(err, {
|
||||
// call_func() retval is deceptive, ignore it. Instead we set `msg_list`
|
||||
// (see above) to capture abort-causing non-exception errors.
|
||||
call_func(fn.data, (int)fn.size, &rettv, (int)args.size,
|
||||
vim_args, &funcexe);
|
||||
// call_func() retval is deceptive, ignore it. Instead TRY_WRAP sets `msg_list` to capture
|
||||
// abort-causing non-exception errors.
|
||||
(void)call_func(fn.data, (int)fn.size, &rettv, (int)args.size, vim_args, &funcexe);
|
||||
});
|
||||
|
||||
if (!ERROR_SET(err)) {
|
||||
@ -280,18 +279,23 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Arena *arena,
|
||||
typval_T rettv;
|
||||
bool mustfree = false;
|
||||
switch (dict.type) {
|
||||
case kObjectTypeString:
|
||||
case kObjectTypeString: {
|
||||
int eval_ret;
|
||||
TRY_WRAP(err, {
|
||||
eval0(dict.data.string.data, &rettv, NULL, &EVALARG_EVALUATE);
|
||||
clear_evalarg(&EVALARG_EVALUATE, NULL);
|
||||
});
|
||||
eval_ret = eval0(dict.data.string.data, &rettv, NULL, &EVALARG_EVALUATE);
|
||||
clear_evalarg(&EVALARG_EVALUATE, NULL);
|
||||
});
|
||||
if (ERROR_SET(err)) {
|
||||
return rv;
|
||||
}
|
||||
if (eval_ret != OK) {
|
||||
abort(); // Should not happen.
|
||||
}
|
||||
// Evaluation of the string arg created a new dict or increased the
|
||||
// refcount of a dict. Not necessary for a RPC dict.
|
||||
mustfree = true;
|
||||
break;
|
||||
}
|
||||
case kObjectTypeDict:
|
||||
object_to_vim(dict, &rettv, err);
|
||||
break;
|
||||
|
@ -1854,6 +1854,20 @@ describe('LSP', function()
|
||||
end,
|
||||
}
|
||||
end)
|
||||
|
||||
it('vim.lsp.start when existing client has no workspace_folders', function()
|
||||
exec_lua(create_server_definition)
|
||||
eq(
|
||||
{ 2, 'foo', 'foo' },
|
||||
exec_lua(function()
|
||||
local server = _G._create_server()
|
||||
vim.lsp.start { cmd = server.cmd, name = 'foo' }
|
||||
vim.lsp.start { cmd = server.cmd, name = 'foo', root_dir = 'bar' }
|
||||
local foos = vim.lsp.get_clients()
|
||||
return { #foos, foos[1].name, foos[2].name }
|
||||
end)
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('parsing tests', function()
|
||||
|
@ -21,13 +21,12 @@ local function get_search_history(name)
|
||||
local man = require('man')
|
||||
local res = {}
|
||||
--- @diagnostic disable-next-line:duplicate-set-field
|
||||
man.find_path = function(sect, name0)
|
||||
man._find_path = function(name0, sect)
|
||||
table.insert(res, { sect, name0 })
|
||||
return nil
|
||||
end
|
||||
local ok, rv = pcall(man.open_page, -1, { tab = 0 }, args)
|
||||
assert(not ok)
|
||||
assert(rv and rv:match('no manual entry'))
|
||||
local err = man.open_page(-1, { tab = 0 }, args)
|
||||
assert(err and err:match('no manual entry'))
|
||||
return res
|
||||
end)
|
||||
end
|
||||
@ -225,7 +224,7 @@ describe(':Man', function()
|
||||
matches('^/.+', actual_file)
|
||||
local args = { nvim_prog, '--headless', '+:Man ' .. actual_file, '+q' }
|
||||
matches(
|
||||
('Error detected while processing command line:\r\n' .. 'man.lua: "no manual entry for %s"'):format(
|
||||
('Error detected while processing command line:\r\n' .. 'man.lua: no manual entry for %s'):format(
|
||||
pesc(actual_file)
|
||||
),
|
||||
fn.system(args, { '' })
|
||||
@ -235,8 +234,8 @@ describe(':Man', function()
|
||||
|
||||
it('tries variants with spaces, underscores #22503', function()
|
||||
eq({
|
||||
{ '', 'NAME WITH SPACES' },
|
||||
{ '', 'NAME_WITH_SPACES' },
|
||||
{ vim.NIL, 'NAME WITH SPACES' },
|
||||
{ vim.NIL, 'NAME_WITH_SPACES' },
|
||||
}, get_search_history('NAME WITH SPACES'))
|
||||
eq({
|
||||
{ '3', 'some other man' },
|
||||
@ -255,8 +254,8 @@ describe(':Man', function()
|
||||
{ 'n', 'some_other_man' },
|
||||
}, get_search_history('n some other man'))
|
||||
eq({
|
||||
{ '', '123some other man' },
|
||||
{ '', '123some_other_man' },
|
||||
{ vim.NIL, '123some other man' },
|
||||
{ vim.NIL, '123some_other_man' },
|
||||
}, get_search_history('123some other man'))
|
||||
eq({
|
||||
{ '1', 'other_man' },
|
||||
@ -265,11 +264,10 @@ describe(':Man', function()
|
||||
end)
|
||||
|
||||
it('can complete', function()
|
||||
t.skip(t.is_os('mac') and t.is_arch('x86_64'), 'not supported on intel mac')
|
||||
eq(
|
||||
true,
|
||||
exec_lua(function()
|
||||
return #require('man').man_complete('f', 'Man g') > 0
|
||||
return #require('man').man_complete('f', 'Man f') > 0
|
||||
end)
|
||||
)
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user