Skip to content

Commit

Permalink
feat(lsp-root): take into account workspaces when finding root
Browse files Browse the repository at this point in the history
  • Loading branch information
TheLeoP committed Jul 29, 2024
1 parent dcab508 commit a1cae80
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 38 deletions.
43 changes: 21 additions & 22 deletions lua/project_nvim/project.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,42 @@ local config = require("project_nvim.config")
local history = require("project_nvim.utils.history")
local glob = require("project_nvim.utils.globtopattern")
local path = require("project_nvim.utils.path")
local uv = vim.loop
local uv = vim.uv
local M = {}

-- Internal states
M.attached_lsp = false
---@type string
M.last_project = nil
M.last_project = nil ---@type string?

--- Tries to return the root of the project using LSP
---@return string|nil root_dir
---@return string|nil method
function M.find_lsp_root()
-- Returns nil or string
local filetype = vim.api.nvim_buf_get_option(0, "filetype")
local clients = vim.lsp.get_active_clients({ bufnr = 0 })
if next(clients) == nil then return nil, nil end

for _, client in pairs(clients) do
local filetypes = client.config.filetypes
if
filetypes
and vim.tbl_contains(filetypes, filetype)
and not vim.tbl_contains(config.options.ignore_lsp, client.name)
then
return client.config.root_dir, ('"%s" lsp'):format(client.name)
end
end

return nil, nil
---@type string
local workspace_root = vim
.iter(vim.lsp.get_clients({ bufnr = 0 }))
:filter(function(client) return not vim.tbl_contains({}, client.name) end)
:map(function(client) return client.workspace_folders end)
:flatten(1)
:map(function(workspace_folder) return workspace_folder.name end)
:find(function(root)
root = path.normalize(root)
local current_file = vim.api.nvim_buf_get_name(0)
current_file = path.normalize(current_file)
return current_file:find(vim.pesc(root))
end)

if not workspace_root then return end

return workspace_root, "lsp"
end

--- Tries to return the root of the project using pattern matching
---@return string|nil root_dir
---@return string|nil method
function M.find_pattern_root()
local search_dir = vim.fn.expand("%:p:h", true)
if vim.fn.has("win32") == 1 then search_dir = vim.fs.normalize(search_dir) end
search_dir = path.normalize(search_dir)

local last_dir_cache = ""
local curr_dir_cache = {}
Expand Down Expand Up @@ -168,7 +167,7 @@ function M.get_project_root()
}
for _, detection_method in ipairs(config.options.detection_methods) do
local root, method = find_root[detection_method]()
if root == nil then return nil end
if not root then return end
return root, method
end
end
Expand Down
15 changes: 1 addition & 14 deletions lua/project_nvim/utils/history.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
local path = require("project_nvim.utils.path")
local uv = vim.loop
local M = {}
local is_windows = vim.fn.has("win32") == 1 or vim.fn.has("wsl") == 1

---@type string[]
M.recent_projects = nil -- projects from previous neovim sessions
Expand All @@ -27,18 +26,6 @@ local function dir_exists(dir)
return false
end

---@param path_to_normalize string
---@return string
local function normalize_path(path_to_normalize)
local normalized_path = vim.fs.normalize(path_to_normalize)

if is_windows then
normalized_path = normalized_path:sub(1, 1):upper() .. normalized_path:sub(2) --[[@as string]]
end

return normalized_path
end

---@param tbl string[]
---@return string[]
local function delete_duplicates(tbl)
Expand All @@ -48,7 +35,7 @@ local function delete_duplicates(tbl)
local output = {}

for _, v in ipairs(tbl) do
local normalised_path = normalize_path(v)
local normalised_path = path.normalize(v)
if not cache[normalised_path] then
cache[normalised_path] = true
table.insert(output, normalised_path)
Expand Down
13 changes: 11 additions & 2 deletions lua/project_nvim/utils/path.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,23 @@ end
---@return boolean
function M.is_excluded(dir)
for _, dir_pattern in ipairs(config.options.exclude_dirs) do
if dir:match(dir_pattern) ~= nil then return true end
if not dir:match(dir_pattern) then return true end
end

return false
end

---@param path string
---@return boolean
function M.exists(path) return vim.fn.empty(vim.fn.glob(path)) == 0 end
function M.exists(path) return vim.uv.fs_stat(path) ~= nil end

---@param path string
---@return string
function M.normalize(path)
path = vim.fs.normalize(path)
path = path:gsub([[\]], "/")
if vim.fn.has("win32") == 1 then path = path:sub(1, 1):upper() .. path:sub(2) end
return path
end

return M

0 comments on commit a1cae80

Please sign in to comment.