Skip to content

feat(sidebar): add configurable path abbreviation styles [5]#152

Draft
AbysmalBiscuit wants to merge 11 commits into
mathix420:masterfrom
AbysmalBiscuit:feat/sidebar-path-display
Draft

feat(sidebar): add configurable path abbreviation styles [5]#152
AbysmalBiscuit wants to merge 11 commits into
mathix420:masterfrom
AbysmalBiscuit:feat/sidebar-path-display

Conversation

@AbysmalBiscuit

@AbysmalBiscuit AbysmalBiscuit commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Adds an opt-in path abbreviation style for sidebar and git-panel paths, plus two path-display bug fixes that change default output.

Stacked on #138. The first two commits (ed57ddba, b68df290) belong to that PR — review from 7a9a1fe3 onward. Rebased on current master; merges cleanly.

Bug fixes (these change default output)

Diff panes no longer take their title from the terminal. ConPTY emits an OSC 0 carrying the child's command line, so a diff pane's header could flip to C:\Program Files\Git\cmd\git …. Diff panes now pin diff: <path> and ignore title sequences; shell sessions still follow their child's title as before.

WSL workspaces render in Linux spelling. A worktree under \\wsl.localhost\<distro>\home\… now shows as /home/… in the sidebar, the git panel header, the command palette and the base-branch picker, instead of the UNC path.

Feature (opt-in, default inert)

[ui.path_style] picks how each site abbreviates a path:

[ui.path_style]
diff_title = "full"   # default
git_rows   = "fish"   # ~/G/monorepo
git_header = "zed"    # filename first, parent trailing

[ui.path_style.filename]
color = "#e6e6e6"
bold = true

[ui.path_style.parent]
italic = true
  • full — current behavior, the default at every site
  • fish — fish-shell style, parents shortened to one character (~/G/monorepo)
  • zed — filename first with the parent path after it, each with its own configurable color/bold/italic

Every site defaults to full and both emphases default to unset, so an unmodified config renders identically to today. Unknown values log a warning and fall back to full.

Testing

cargo test -p alacritree — 507 passed, 2 ignored.

One failure, session::tests::a_pane_runs_its_child_without_a_console_host_handshake, is pre-existing and unrelated: it asserts a wall-clock ConPTY spawn budget of ~3s and trips at ~3.1s under full-suite parallel load. It passes in isolation at 0.04s and fails the same way on master.

Not covered by CI

No PTY harness, so these want a manual pass on Windows before merge:

  • A diff opened from the git panel reads diff: <path> in the pane header, tab tooltip, sidebar session row and command-palette entry — never the git command line.
  • A WSL worktree's git panel header, command palette and base-branch picker all agree on /home/….
  • An unmodified config renders every path exactly as it did before.

Known gap

Hover tooltips on elided sidebar paths are unreliable on Windows. egui adds a tooltip whenever a galley elides, so this should already work; the leading hypothesis (the clickable row shadowing the label's hover) was refuted in a headless repro. Diagnosing it needs a live GUI session and is not part of this PR.

AbysmalBiscuit and others added 11 commits July 25, 2026 10:24
Search-mode Enter/Esc were hardcoded in panel_filter and could not be
rebound, and Enter never scrolled the activated row into view.

Add three search-scoped actions — SidebarSearchConfirm (Enter),
SidebarSearchCancel (Esc), and SidebarSearchCancelToTerminal
(Shift+Esc) — dispatched through the keyboard binding system from the
focused panel's nav pass. handle_shortcuts drops search-scoped actions
so the terminal's own Enter/Esc still reach the PTY. Confirm scrolls the
acted-on row into view via a focus-independent pending target, resolving
a now-hidden child to its owning project header. Cancel returns the
cursor to the seed row and preserves the s/a toggle filters.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Confirming a fuzzy search ran the row's full activation: a project
header toggled its expansion, and a worktree or session switched
workspace and moved focus to the terminal. Search is how you find a
row, so acting on it in the same keystroke is surprising — and for a
header destructive, collapsing the project you had just gone looking
for.

Confirm now only leaves search, puts the cursor on the highlighted row
and scrolls it in, keeping focus in the sidebar. Activation stays a
second, explicit Enter in browsing mode. That makes confirm the twin of
cancel, so both share one landing helper per panel, and the git panel
follows the same rule instead of opening a diff.

Search lists matched worktrees and sessions whatever their project's
expanded flag says, so a child under a collapsed project vanished the
moment the query cleared. Confirm expands that project first —
expand-only, and never for a header, which is what keeps selecting a
project from behaving as a toggle.

Dropping activation also drops the reason for the focus-independent
pending scroll target, which existed only because activation focused
the terminal and nulled the paint-time cursor. The ordinary cursor-move
scroll suffices once its moved flag is forced rather than keyed on
cursor identity: restoring the unfiltered list can move the same row
far off-screen. That also fixes git cancel, which could leave a
surviving row unscrolled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ConPTY publishes the child's command line as an OSC 0 title at
startup, overwriting the "diff: <path>" name alacritree gave the
pane. Derive the pin from Session.kind rather than storing a second
title_pinned field that could drift from it. Shells still follow
their child's title; bells and exits are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The git panel renders workspace paths raw, so a WSL project shows as
\wsl.localhost\kali-linux\home\lev\... instead of the /home/lev/...
the user typed. display_path renders WSL locations in the distro's
own spelling and leaves native paths untouched, distinct from
windows_to_linux which also rewrites C:\ into /mnt/c for git's benefit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Every worktree/project/workspace label rendered paths with
path.display(), which spells a WSL location as its Windows UNC form
(\wsl.localhost\<distro>\...) instead of the /home/... path the user
typed inside the distro. Route every user-visible path — git panel
header, palette rows, workspace labels, base-branch picker, and the
$path row-label template variable — through wsl::display_path, which
keeps native paths untouched and renders WSL locations in the
distro's own spelling.

Comparisons, keys, and filters (diff_key, the sidebar filter,
git_nav cursors) keep operating on the raw path; only rendering
changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a pure, egui-free module that splits a path into root/parent/name
and renders it in three styles: Full (identity, the default), Fish
(each parent segment collapses to its first character), and Zed (name
leads, parent trails). Root detection matches Windows prefixes (drive,
UNC, \?\, WSL UNC shares) before any separator scanning, since \ and
: are legal characters in Unix filenames. Home-directory collapsing to
~ is case- and separator-insensitive on Windows paths (NTFS folds case
past ASCII) and exact on POSIX paths.

Nothing calls this module yet; it is wired in a later task.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds PathStyleConfig/TextEmphasis on UiTheme so each path-rendering
site (diff pane title, git-panel rows, git-panel header) can select
Full/Fish/Zed independently, plus the two text emphases the Zed style
paints filenames and parents with. Unrecognized style strings warn
once and fall back to "full", mirroring parse_scrollbar. Every default
resolves to Full/no-emphasis so an unmodified config renders exactly
as it does today; nothing reads this config yet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
WSL projects now carry their distro's $HOME (from a new final section
in DISCOVER_SCRIPT), so path rendering can collapse it to `~` without
guessing the prefix from the path itself.

Both refresh paths -- the folder-picker's background discovery and
the synchronous Project::refresh -- now adopt discovered fields
through one Project::adopt_discovered method instead of each hand-
copying its own field list. A field discovered but not added to both
lists used to silently vanish on whichever path skipped it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Threads PathStyleConfig from Config through Theme so the free-standing
row painters can spell a path without taking a &Config, and wires
path_style::render into the three display sites: the git panel
header (post wsl::display_path, since the header is the one absolute
path), the diff pane title, and the two git row painters
(file_row, branch_diff_row). diff_key, the git filter, and cursor
navigation continue to operate on the raw path; only the rendered
label text is styled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Under Zed the filename and parent path now paint as a single
LayoutJob so filename/parent can carry distinct color and weight
without an item_spacing gap between two labels. Full and Fish
still paint as a single plain truncating label, unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
path_label() forced .selectable(false) on both branches, silently
turning off text selection on the git-panel header path even under
the default (unconfigured) Full style — a regression the header
never had before path_label existed. The two git rows need to stay
non-selectable (a selectable label would eat the row's click), but
the header must not.

Thread a selectable bool through path_label so each call site keeps
its own prior behavior: true at the header, false at the two rows.

Also extract the Zed job's span decomposition into zed_spans() so
the fidelity test exercises the same code path path_label runs,
instead of recomputing the split logic by hand, and add a coverage
test that drives path_label through a real Ui to assert the header's
response senses drag (selectable) while a row's does not.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@AbysmalBiscuit
AbysmalBiscuit force-pushed the feat/sidebar-path-display branch from 7d79ee6 to ba0425c Compare July 25, 2026 08:32
@AbysmalBiscuit AbysmalBiscuit changed the title feat(sidebar): add configurable path abbreviation styles feat(sidebar): add configurable path abbreviation styles [5] Jul 25, 2026
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