From 29afc301ea05bc907444b698c91b141c26167baa Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Sat, 11 Jan 2025 15:11:16 +0100 Subject: make universal root detection opt-in --- README.md | 20 ++++++++++++++++++-- init.lua | 11 +++++++++-- lspc.lua | 8 +++++++- tools/find-upwards | 2 +- util.lua | 7 +++++++ 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 on stdin separated by '\n' + -- The available choices are passed to 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 -- cgit v1.2.3