Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions doc/VectorCode.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*VectorCode.txt* For Last change: 2025 March 27
*VectorCode.txt* For Last change: 2025 March 28

==============================================================================
Table of Contents *VectorCode-table-of-contents*
Expand Down Expand Up @@ -324,7 +324,13 @@ interface:
1. The `default` backend which works exactly like the original implementation
used in previous versions;
2. The `lsp` based backend, which make use of the experimental `vectorcode-server`
implemented in version 0.4.0.
implemented in version 0.4.0. If you want to customise the LSP executable or
any options supported by `vim.lsp.ClientConfig`, you can do so by using
`vim.lsp.config()` or
nvim-lspconfig <https://github.com/neovim/nvim-lspconfig>. The LSP will
attempt to read configurations from these 2 sources before it starts. (If
`vim.lsp.config.vectorcode_server` is not `nil`, this will be used and
nvim-lspconfig will be ignored.)

-------------------------------------------------------------------------------
Features default lsp
Expand Down
8 changes: 7 additions & 1 deletion docs/neovim.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,13 @@ interface:
1. The `default` backend which works exactly like the original implementation
used in previous versions;
2. The `lsp` based backend, which make use of the experimental `vectorcode-server`
implemented in version 0.4.0.
implemented in version 0.4.0. If you want to customise the LSP executable or
any options supported by `vim.lsp.ClientConfig`, you can do so by using
`vim.lsp.config()` or
[nvim-lspconfig](https://github.com/neovim/nvim-lspconfig). The LSP will
attempt to read configurations from these 2 sources before it starts. (If
`vim.lsp.config.vectorcode_server` is not `nil`, this will be used and
nvim-lspconfig will be ignored.)


| Features | `default` | `lsp` |
Expand Down
70 changes: 3 additions & 67 deletions lua/vectorcode/cacher/lsp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,66 +35,8 @@ end

---@return boolean
local function is_lsp_running()
local clients = vim.lsp.get_clients({ name = "vectorcode_server" })
if #clients == 0 then
return false
end
client_id = clients[1].id
return true
end

---@param project_root string?
---@param ok_to_fail boolean?
---@return boolean
local function start_server(project_root, ok_to_fail)
if is_lsp_running() then
return true
end

if ok_to_fail == nil then
ok_to_fail = true
end
local cmd = { "vectorcode-server" }
if
type(project_root) == "string"
and vim.list_contains({ "directory" }, vim.uv.fs_stat(project_root).type)
then
vim.list_extend(cmd, { "--project_root", project_root })
else
local try_root = vim.fs.root(".", ".vectorcode") or vim.fs.root(".", ".git")
if try_root ~= nil then
vim.list_extend(cmd, { "--project_root", try_root })
else
vim.schedule(function()
vim.notify(
"Failed to start vectorcode-server due to failing to resolve the project root.",
vim.log.levels.ERROR,
notify_opts
)
end)
return false
end
end
local id, err = vim.lsp.start_client({
name = "vectorcode_server",
cmd = cmd,
})

if err ~= nil and (vc_config.get_user_config().notify or not ok_to_fail) then
vim.schedule(function()
vim.notify(
("Failed to start vectorcode-server due to the following error:\n%s"):format(
err
),
vim.log.levels.ERROR,
notify_opts
)
end)
return false
else
client_id = id
return true
end
client_id = job_runner.init()
return client_id ~= nil
end

---@type table<integer, VectorCode.Cache>
Expand Down Expand Up @@ -223,13 +165,7 @@ M.register_buffer = vc_config.check_cli_wrap(
opts =
vim.tbl_deep_extend("force", vc_config.get_user_config().async_opts, opts or {})

if
not start_server(opts.project_root or vim.api.nvim_buf_get_name(bufnr), false)
then
-- failed to start the server
return false
end
assert(client_id ~= nil)
assert(is_lsp_running())

if CACHE[bufnr] ~= nil then
-- update the options and/or query_cb
Expand Down
28 changes: 24 additions & 4 deletions lua/vectorcode/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@ local config = {
on_setup = { update = false, lsp = false },
}

---@return vim.lsp.ClientConfig
local lsp_configs = function()
local cfg =
{ cmd = { "vectorcode-server" }, root_markers = { ".vectorcode", ".git" } }
if vim.lsp.config ~= nil and vim.lsp.config.vectorcode_server ~= nil then
-- nvim >= 0.11.0
cfg = vim.tbl_deep_extend("force", cfg, vim.lsp.config.vectorcode_server)
else
-- nvim < 0.11.0
local ok, lspconfig = pcall(require, "lspconfig.configs")
if ok and lspconfig.vectorcode_server ~= nil then
cfg = lspconfig.vectorcode_server.config_def.default_config
end
end
return cfg
end

local setup_config = vim.deepcopy(config, true)
local notify_opts = { title = "VectorCode" }

Expand Down Expand Up @@ -55,11 +72,12 @@ local startup_handler = check_cli_wrap(function(configs)
end)
end
if configs.on_setup.lsp then
local lsp_module = require("vectorcode.jobrunner.lsp")
if type(lsp_module) == "table" then
-- this will trigger the private `get_client` function in the runner and hence start the LSP
lsp_module.is_job_running(0)
local ok, runner = pcall(require, "vectorcode.jobrunner.lsp")
if not ok or not type(runner) == "table" or runner == nil then
vim.notify("Failed to start vectorcode-server.", vim.log.levels.WARN, notify_opts)
return
end
runner.init()
end
end)

Expand Down Expand Up @@ -135,4 +153,6 @@ return {
has_cli = has_cli,

check_cli_wrap = check_cli_wrap,

lsp_configs = lsp_configs,
}
1 change: 1 addition & 0 deletions lua/vectorcode/jobrunner/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ local utils = require("vectorcode.utils")
---@field run fun(args: string[], timeout_ms: integer?, bufnr: integer):(result:table, error:table)
---@field is_job_running fun(job_handle: integer):boolean
---@field stop_job fun(job_handle: integer)
---@field init function?

return {
--- Automatically find project_root from buffer path if it's not already specified.
Expand Down
58 changes: 18 additions & 40 deletions lua/vectorcode/jobrunner/lsp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,55 +14,33 @@ local CLIENT = nil
local vc_config = require("vectorcode.config")
local notify_opts = vc_config.notify_opts

--- Returns the Client ID if applicable, or `nil` if the language server fails to start
---@param ok_to_fail boolean
local function get_client(ok_to_fail)
---@return integer?
function jobrunner.init(ok_to_fail)
ok_to_fail = ok_to_fail or true
if #vim.lsp.get_clients({ name = "vectorcode_server" }) > 0 then
CLIENT = vim.lsp.get_clients({ name = "vectorcode_server" })[1]
local client_id = vim.lsp.start(vc_config.lsp_configs(), {})
if client_id ~= nil then
-- server started
CLIENT = vim.lsp.get_client_by_id(client_id) --[[@as vim.lsp.Client]]
else
local cmd = { "vectorcode-server" }

local try_root = vim.fs.root(".", ".vectorcode") or vim.fs.root(".", ".git")
if try_root ~= nil then
vim.list_extend(cmd, { "--project_root", try_root })
else
-- failed to start server
if vc_config.get_user_config().notify or not ok_to_fail then
vim.schedule(function()
vim.notify(
"Failed to start vectorcode-server due to failing to resolve the project root.",
"Failed to start vectorcode-server due some error.",
vim.log.levels.ERROR,
notify_opts
)
end)
return false
end
local id, err = vim.lsp.start_client({
name = "vectorcode_server",
cmd = cmd,
})

if err ~= nil and (vc_config.get_user_config().notify or not ok_to_fail) then
vim.schedule(function()
vim.notify(
("Failed to start vectorcode-server due to the following error:\n%s"):format(
err
),
vim.log.levels.ERROR,
notify_opts
)
end)
return false
elseif id ~= nil then
local cli = vim.lsp.get_client_by_id(id)
if cli ~= nil then
CLIENT = cli
return true
end
end
return nil
end
return client_id
end

function jobrunner.run(args, timeout_ms, bufnr)
get_client(false)
jobrunner.init(false)
assert(CLIENT ~= nil)
assert(bufnr ~= nil)
if timeout_ms == nil or timeout_ms < 0 then
Expand All @@ -85,7 +63,7 @@ function jobrunner.run(args, timeout_ms, bufnr)
end

function jobrunner.run_async(args, callback, bufnr)
get_client(false)
jobrunner.init(false)
assert(CLIENT ~= nil)
assert(bufnr ~= nil)

Expand All @@ -106,7 +84,7 @@ function jobrunner.run_async(args, callback, bufnr)
end
end
args = require("vectorcode.jobrunner").find_root(args, bufnr)
local _, id = CLIENT.request(
local _, id = CLIENT:request(
vim.lsp.protocol.Methods.workspace_executeCommand,
{ command = "vectorcode", arguments = args },
function(err, result, _, _)
Expand All @@ -124,7 +102,7 @@ function jobrunner.run_async(args, callback, bufnr)
end

function jobrunner.is_job_running(job_handler)
get_client(true)
jobrunner.init(true)
if CLIENT ~= nil then
local request_data = CLIENT.requests[job_handler]
return request_data ~= nil and request_data.type == "pending"
Expand All @@ -133,9 +111,9 @@ function jobrunner.is_job_running(job_handler)
end

function jobrunner.stop_job(job_handler)
get_client(true)
jobrunner.init(true)
if CLIENT ~= nil then
CLIENT.cancel_request(job_handler)
CLIENT:cancel_request(job_handler)
end
end

Expand Down