grace/dots

dotfiles/nix configs

git clone https://git.gae.moe/grace/dots

Grace Yoderhx and vcs changesddf0c79

main
2.5 KiB98 linesraw
1---@brief
2---
3--- https://github.com/golang/tools/tree/master/gopls
4---
5--- Google's lsp server for golang.
6
7--- @class go_dir_custom_args
8---
9--- @field envvar_id string
10---
11--- @field custom_subdir string?
12
13local mod_cache = nil
14local std_lib = nil
15
16---@param custom_args go_dir_custom_args
17---@param on_complete fun(dir: string | nil)
18local function identify_go_dir(custom_args, on_complete)
19  local cmd = { 'go', 'env', custom_args.envvar_id }
20  vim.system(cmd, { text = true }, function(output)
21    local res = vim.trim(output.stdout or '')
22    if output.code == 0 and res ~= '' then
23      if custom_args.custom_subdir and custom_args.custom_subdir ~= '' then
24        res = res .. custom_args.custom_subdir
25      end
26      on_complete(res)
27    else
28      vim.schedule(function()
29        vim.notify(
30          ('[gopls] identify ' .. custom_args.envvar_id .. ' dir cmd failed with code %d: %s\n%s'):format(
31            output.code,
32            vim.inspect(cmd),
33            output.stderr
34          )
35        )
36      end)
37      on_complete(nil)
38    end
39  end)
40end
41
42---@return string?
43local function get_std_lib_dir()
44  if std_lib and std_lib ~= '' then
45    return std_lib
46  end
47
48  identify_go_dir({ envvar_id = 'GOROOT', custom_subdir = '/src' }, function(dir)
49    if dir then
50      std_lib = dir
51    end
52  end)
53  return std_lib
54end
55
56---@return string?
57local function get_mod_cache_dir()
58  if mod_cache and mod_cache ~= '' then
59    return mod_cache
60  end
61
62  identify_go_dir({ envvar_id = 'GOMODCACHE' }, function(dir)
63    if dir then
64      mod_cache = dir
65    end
66  end)
67  return mod_cache
68end
69
70---@param fname string
71---@return string?
72local function get_root_dir(fname)
73  if mod_cache and fname:sub(1, #mod_cache) == mod_cache then
74    local clients = vim.lsp.get_clients({ name = 'gopls' })
75    if #clients > 0 then
76      return clients[#clients].config.root_dir
77    end
78  end
79  if std_lib and fname:sub(1, #std_lib) == std_lib then
80    local clients = vim.lsp.get_clients({ name = 'gopls' })
81    if #clients > 0 then
82      return clients[#clients].config.root_dir
83    end
84  end
85  return vim.fs.root(fname, 'go.work') or vim.fs.root(fname, 'go.mod') or vim.fs.root(fname, '.git') or vim.fs.root(fname, '.jj')
86end
87
88return {
89  cmd = { 'gopls' },
90  filetypes = { 'go', 'gomod', 'gowork', 'gotmpl' },
91  root_dir = function(bufnr, on_dir)
92    local fname = vim.api.nvim_buf_get_name(bufnr)
93    get_mod_cache_dir()
94    get_std_lib_dir()
95    -- see: https://github.com/neovim/nvim-lspconfig/issues/804
96    on_dir(get_root_dir(fname))
97  end,
98}