Skip to content

Commit

Permalink
Find workspace root (#247)
Browse files Browse the repository at this point in the history
* Find project root by searching upward from the current working directory for one of the project root files.

The default list of project root files was copied from codeium.vim.

* Support LSP and custom function for finding workspace root

* Nothing uses get_relative_path anymore
  • Loading branch information
dimfeld authored Oct 11, 2024
1 parent 3e4421a commit 8394850
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 15 deletions.
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ in your default browser using the xdg-open command.
- `enterprise_mode`: enable enterprise mode
- `detect_proxy`: enable or disable proxy detection
- `enable_chat`: enable chat functionality
- `workspace_root`:
- `use_lsp`: Use Neovim's LSP support to find the workspace root, if possible.
- `paths`: paths to files that indicate a workspace root when not using the LSP support
- `find_root`: An optional function that the plugin will call to find the workspace root.
- `tools`: paths to binaries used by the plugin:

- `uname`: not needed on Windows, defaults given.
Expand Down Expand Up @@ -129,6 +133,48 @@ cmp.setup({
})
```

### Workspace Root Directory

The plugin uses a few techniques to find the workspace root directory, which helps to inform the autocomplete and chat context.

1. Call the optional `workspace_root.find_root` function, if provided. This is described below.
2. Query Neovim's built-in LSP support for the workspace root, if `workspace_root.use_lsp` is not set to `false`.
3. Search upward in the filesystem for a file or directory in `workspace_root.paths` that indicates a workspace root.

The default configuration is:

```lua
require('codeium').setup({
workspace_root = {
use_lsp = true,
find_root = nil,
paths = {
".bzr",
".git",
".hg",
".svn",
"_FOSSIL_",
"package.json",
}
}
})
```

The `find_root` function can help the plugin find the workspace root when you are not using Neovim's built-in LSP
provider. For example, this snippet calls into `coc.nvim` to find the workspace root.

```lua
require('codeium').setup({
workspace_root = {
find_root = function()
return vim.fn.CocAction("currentWorkspacePath")
end
}
})
```



## Troubleshooting

The plugin log is written to `~/.cache/nvim/codeium.log`.
Expand Down
9 changes: 4 additions & 5 deletions lua/codeium/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,8 @@ function Server:new()
cursor_offset = 0,
text = text,
line_ending = line_ending,
absolute_path = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(bufnr), ":p"),
relative_path = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(bufnr), ":"),
absolute_uri = util.get_uri(vim.api.nvim_buf_get_name(bufnr)),
workspace_uri = util.get_uri(util.get_project_root()),
}

request("RefreshContextForIdeAction", {
Expand All @@ -453,12 +453,11 @@ function Server:new()
notify.error("failed refresh context: " .. err.out)
return
end
end
)
end)
end

function m.add_workspace()
local project_root = vim.fn.getcwd()
local project_root = util.get_project_root()
-- workspace already tracked by server
if workspaces[project_root] then
return
Expand Down
12 changes: 12 additions & 0 deletions lua/codeium/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ function M.defaults()
enable_index_service = true,
search_max_workspace_file_count = 5000,
file_watch_max_dir_count = 50000,
workspace_root = {
use_lsp = true,
find_root = nil,
paths = {
".bzr",
".git",
".hg",
".svn",
"_FOSSIL_",
"package.json",
},
},
}
end

Expand Down
9 changes: 4 additions & 5 deletions lua/codeium/source.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ local function codeium_to_cmp(comp, offset, right)
local documentation = comp.completion.text

local label = documentation:sub(offset)
if label:sub(- #right) == right then
label = label:sub(1, - #right - 1)
if label:sub(-#right) == right then
label = label:sub(1, -#right - 1)
end

-- We get the completion part that has the largest offset
Expand Down Expand Up @@ -92,7 +92,7 @@ local function get_other_documents(bufnr)
local other_documents = {}

for _, buf in ipairs(vim.api.nvim_list_bufs()) do
if vim.api.nvim_buf_is_loaded(buf) and vim.bo[buf].filetype ~= '' and buf ~= bufnr then
if vim.api.nvim_buf_is_loaded(buf) and vim.bo[buf].filetype ~= "" and buf ~= bufnr then
table.insert(other_documents, buf_to_codeium(buf))
end
end
Expand Down Expand Up @@ -187,7 +187,7 @@ function Source:complete(params, callback)
language = language,
cursor_position = { row = cursor.row - 1, col = cursor.col - 1 },
absolute_uri = util.get_uri(vim.api.nvim_buf_get_name(bufnr)),
workspace_uri = util.get_uri(util.get_relative_path(bufnr)),
workspace_uri = util.get_uri(util.get_project_root()),
line_ending = line_ending,
cursor_offset = cursor_offset,
},
Expand All @@ -205,7 +205,6 @@ function Source:complete(params, callback)
end
end
)

end

return Source
53 changes: 48 additions & 5 deletions lua/codeium/util.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local enums = require("codeium.enums")
local config = require("codeium.config")
local io = require("codeium.io")
local M = {}

Expand All @@ -19,13 +20,13 @@ function M.get_editor_options(bufnr)

return {
tab_size = M.fallback_call({
{ vim.api.nvim_get_option_value, "shiftwidth", { buf = bufnr, } },
{ vim.api.nvim_get_option_value, "tabstop", { buf = bufnr, } },
{ vim.api.nvim_get_option_value, "shiftwidth", { buf = bufnr } },
{ vim.api.nvim_get_option_value, "tabstop", { buf = bufnr } },
{ vim.api.nvim_get_option_value, "shiftwidth" },
{ vim.api.nvim_get_option_value, "tabstop" },
}, greater_than_zero, 4),
insert_spaces = M.fallback_call({
{ vim.api.nvim_get_option_value, "expandtab", { buf = bufnr, } },
{ vim.api.nvim_get_option_value, "expandtab", { buf = bufnr } },
{ vim.api.nvim_get_option_value, "expandtab" },
}, nil, true),
}
Expand All @@ -35,8 +36,50 @@ function M.get_newline(bufnr)
return enums.line_endings[vim.bo[bufnr].fileformat] or "\n"
end

function M.get_relative_path(bufnr)
return vim.fn.fnamemodify(vim.api.nvim_buf_get_name(bufnr), ":")
local cached_roots = {}
local function _get_project_root()
if config.options.workspace_root.find_root then
root = config.options.workspace_root.find_root()
if root then
return root
end
end

if config.options.workspace_root.use_lsp then
root = vim.lsp.buf.list_workspace_folders()[0]

This comment has been minimized.

Copy link
@zenofile

zenofile Oct 13, 2024

I don't think this is correct since this always returns nil with zero as index.

if root then
return root
end
end

-- From the CWD, walk up the tree looking for a directory that contains one of the project root files
local candidates = config.options.workspace_root.paths
local result = vim.fs.find(candidates, {
path = cwd,
upward = true,
limit = 1,
})

local found = result[1]
local dir
if found then
dir = vim.fs.dirname(found)
else
dir = cwd
end

return dir
end

function M.get_project_root()
local wd = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(0), ":p:h") or vim.fn.getcwd()
if cached_roots[wd] then
return cached_roots[wd]
end

local root = _get_project_root()
cached_roots[wd] = root
return root
end

function M.get_uri(path)
Expand Down

0 comments on commit 8394850

Please sign in to comment.