aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2025-01-11 15:11:16 +0100
committerFlorian Fischer <florian.fischer@muhq.space>2025-01-11 15:11:16 +0100
commit29afc301ea05bc907444b698c91b141c26167baa (patch)
tree63141257deab54705be8c937ef7f1c0b95b7512d
parentf04bb93e982060ed27e5cf6e4a8d97edeb0910b6 (diff)
downloadvis-lspc-29afc301ea05bc907444b698c91b141c26167baa.tar.gz
vis-lspc-29afc301ea05bc907444b698c91b141c26167baa.zip
make universal root detection opt-in
-rw-r--r--README.md20
-rw-r--r--init.lua11
-rw-r--r--lspc.lua8
-rwxr-xr-xtools/find-upwards2
-rw-r--r--util.lua7
5 files changed, 42 insertions, 6 deletions
diff --git a/README.md b/README.md
index c8ae477..6825aef 100644
--- a/README.md
+++ b/README.md
@@ -122,10 +122,13 @@ Available options are:
* `confirm_cmd = 'vis-menu'` - program to prompt for user confirmation
* `ls_map` - a table mapping `vis` syntax names to language server configurations
* `highlight_diagnostics = 'line'` - highlight the `range` or `line`number of available diagnostics
-* `workspace_edit_remember_cursor = true` - restore the primary cursor position after a workspaceEdit
+* `diagnostic_style_id = nil` - vis style id used to highlight diagnostics, win.STYLE_LEXER_MAX is used by default
* `diagnostic_styles = { error = 'back:red', warning = 'back:yellow', information = 'back:yellow', hint = 'back:yellow', }` - styles used to highlight different diagnostics
-* `show_message = 'message'` - how to present information. `'message'`: use `vis:message`; `'open'`: use a new window supporting syntax highlighting.
+* `workspace_edit_remember_cursor = true` - restore the primary cursor position after a workspaceEdit
* `message_level = 3` - the level of shown messages retrieved via `window/showMessage` notifications
+* `show_message = 'message'` - how to present information. `'message'`: use `vis:message`; `'open'`: use a new window supporting syntax highlighting.
+* `universal_root_globs = {}` - Globs to consider as workspace root for any language server (e.g. `*.git` or `*.hg`).
+* `fallback_dirname_as_root = false` - If set to true a file's directory is used as workspace root if no explicit root was found.
#### Configure your own Language Server
@@ -163,6 +166,19 @@ ls_map.lua = {
Language servers configured in `vis-lspc` can be found in `supported_servers.lua`.
+### Workspace Detection
+
+During server initialization an URI to the root of the workspace (a folder opened by the editor) can be passed to the server.
+Workspaces are used to implement certain project wide [features](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_symbol).
+
+Since vis has no sense of folders and I think it is the job of each individual language server to detect the root of language idiomatic projects, workspace root detection is only activated for certain language servers by default.
+
+If you want to use some universal criteria to detect project roots, like always using a file's directory or considering all source-control repositories as projects you can use the configuration options `universal_root_globs` and `fallback_dirname_as_root`.
+
+Additionally, you can configure globs to detect a project's root for each language server using the `roots` member in its `ls_map` table entry.
+
+For example `roots = {'compile_commands.json', '.clangd'}` is used to detect the project root for clangd.
+
### Events
vis-lspc extends vis' event system with its own set of events:
diff --git a/init.lua b/init.lua
index f2d4f45..0cbbe99 100644
--- a/init.lua
+++ b/init.lua
@@ -1262,16 +1262,23 @@ end
local function find_root_uri(ls, file_path)
local globs = ''
- local roots = ls.roots
+ local roots = ls.conf.roots
if roots then
for _, glob in ipairs(roots) do
globs = globs .. glob .. '\n'
end
end
- globs = globs .. '.git\n.hg\n'
+ if lspc.universal_root_globs then
+ for _, glob in ipairs(lspc.universal_root_globs) do
+ globs = globs .. glob .. '\n'
+ end
+ end
local root_path = util.find_upwards(globs, file_path)
+ if not root_path and lspc.fallback_dirname_as_root then
+ root_path = util.dirname(file_path)
+ end
return root_path and path_to_uri(root_path)
end
diff --git a/lspc.lua b/lspc.lua
index 721199a..d988009 100644
--- a/lspc.lua
+++ b/lspc.lua
@@ -19,7 +19,7 @@ local lspc = {
-- automatically start a language server when a new window is opened
autostart = true,
-- program used to let the user make choices
- -- The available choices are pass to <menu_cmd> on stdin separated by '\n'
+ -- The available choices are passed to <menu_cmd> on stdin separated by '\n'
menu_cmd = 'vis-menu -l 10',
-- program used to ask the user for confirmation
confirm_cmd = 'vis-menu',
@@ -49,6 +49,12 @@ local lspc = {
-- 'message': use vis:message; 'open': use a new split window allowing for syntax highlighting
show_message = 'message',
+ -- Globs that are considered to be workspace roots (e.g. ".git" or ".hg")
+ universal_root_globs = {},
+
+ -- Should a file's directory be used as workspace root if no explicit root was found.
+ fallback_dirname_as_root = false,
+
-- events
events = {
LS_INITIALIZED = 'LspcEvent::LS_INITIALIZED',
diff --git a/tools/find-upwards b/tools/find-upwards
index 5f0edfe..85dc722 100755
--- a/tools/find-upwards
+++ b/tools/find-upwards
@@ -23,4 +23,4 @@ while read -r glob; do
done
done
-echo "$BASEDIR"
+exit 1
diff --git a/util.lua b/util.lua
index 114aad4..8d9df9b 100644
--- a/util.lua
+++ b/util.lua
@@ -123,6 +123,13 @@ function util.get_relative_path(cwd_components, absolute_path_or_components)
return dir:sub(2)
end
+--- Strip the last component from a pathname
+-- @param the pathname
+-- @return the pathname up to the last '/'
+function util.dirname(name)
+ return name:match('(.*[/])')
+end
+
--- Create an iterator yielding the nth line of a file
--
-- @param path The path to the file