Skip to content

feat(configuration): expand ~ in extends and fall back to a user configuration - #878

Merged
psteinroe merged 1 commit into
mainfrom
feat/config-home-and-global
Oct 19, 2026
Merged

psteinroe merged 1 commit into
mainfrom
feat/config-home-and-global

Conversation

@psteinroe

Copy link
Copy Markdown
Collaborator

Addresses #640. Related to #13.

What changed

~ in extends. Entries that start with ~/, or are exactly ~, now resolve against the home directory. ~\ is also accepted on Windows. Before this change, .jsonc entries were always joined onto the config's directory, so ~/... became <project>/~/... and failed to load:

// before: Cannot read file /project/~/.config/shared.jsonc
// after:  loads /home/alice/.config/shared.jsonc
{ "extends": ["~/.config/shared.jsonc"] }

A path with ~ is always treated as a file path, whatever its extension, so ~/shared.json doesn't go through the package resolver. If the home directory is unknown, the entry falls back to the old behaviour and fails with the usual "can't load" error.

User configuration fallback. If the search finds no project config, the user config is loaded. The search walks up from the CLI working directory or the editor's workspace folder. It looks for postgres-language-server.jsonc in the first of these directories that has one:

Platform Location
Linux $XDG_CONFIG_HOME/postgres-language-server/, else ~/.config/postgres-language-server/
macOS $XDG_CONFIG_HOME or ~/.config (as on Linux), then ~/Library/Application Support/postgres-language-server/
Windows %APPDATA%\postgres-language-server\

The semantics are kept simple on purpose:

  • A project config always wins, and the user config is never merged into it. To combine them, a project config adds the user config to extends, which now works thanks to ~.
  • An explicit --config-path, PGLS_CONFIG_PATH or editor configurationPath never falls back. A missing file there is still an error.
  • The user config applies to the project as if it sat in the project directory. LoadedConfiguration::directory_path is the project directory, so the LSP resolves vcs.root and .gitignore against the project, not ~/.config/.... Globs already resolve against the working directory. Relative extends inside the user config still resolve against the user config's own directory.
  • Only the current file name is looked up in the user config directory. The deprecated postgrestools.jsonc is not.

Why macOS also checks ~/.config. The directories crate only knows ~/Library/Application Support, but most CLI tools on macOS read ~/.config/<tool> (gh, helix, bat, starship, …), and that's where users look first. Checking both keeps the native location working and puts ~/.config first. No new environment variable is added: XDG_CONFIG_HOME covers relocating it on Unix.

Implementation. FileSystem gets home_directory() and user_config_directories(). OsFileSystem reads them from the OS (pgls_fs::dir). MemoryFileSystem returns nothing unless the test sets them, so tests never touch the real home directory. Unit tests in pgls_workspace::configuration cover:

  • ~ expansion (including non-.jsonc entries)
  • the fallback and its lookup order
  • that it isn't merged into a project config
  • that it isn't used with an explicit path
  • relative extends inside the user config

pgls_fs::dir tests cover the XDG resolution. docs/configuration.md documents both features and the precedence.

Risks

  • Anyone who already has a postgres-language-server.jsonc in their config directory will now have it applied to projects without a config. That's the intended effect, but it is a behaviour change.
  • The LSP still only reloads when the project-root config file changes. Edits to the user config, like edits to any extended file, take effect on the next reload or restart. Watching it is left for a follow-up.
  • Windows and macOS directory resolution is covered by unit tests of the pure helper, but I only ran it end to end on Linux.

@psteinroe
psteinroe merged commit 4000b24 into main Oct 19, 2026
9 checks passed
@psteinroe
psteinroe deleted the feat/config-home-and-global branch October 19, 2026 06:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant