feat: per-thread default working directories - #33
Open
ytaskiran wants to merge 18 commits into
Open
Conversation
Enter used to select the highlighted subdirectory and exit, so pressing it right after the picker opened silently grabbed the alphabetically-first child instead of the directory you were standing in. The current directory is now row 0 of the list, where the cursor starts. Enter there confirms it; Enter on a subdirectory row walks into that row instead of exiting. Tab still completes into the first match from row 0, so typing a segment and tabbing walks downward like a shell. Row 0 always exists, which removes the old "empty filtered set falls back to current" special case. Drops Ctrl+x. Backspacing up to ~ and confirming does the same job without a second key to learn.
The "use <path>" list row duplicated the path line directly above it, showing the same directory twice. The path line now carries the prefix column and highlight the entries use, so it reads as row 0 of one navigable column rather than a separate element. Selection state shows as the marker plus highlight, and the block cursor appears only while the line is active.
The path suffix only rendered on the selected thread, so it appeared and vanished as the cursor moved down the tree. It now always renders. Selection changes brightness rather than visibility: unselected rows use a new thread_path_dim, derived like thread_dim but pushed further toward the border colour so the path stays legible without competing with the thread name. On the selected row the tree's highlight style covers the whole line, so the path reads at full brightness there.
- shorten_home: with no resolvable home, home_dir yields / and stripping that prefix turned every absolute path into a bogus ~/... path. - new_session: the success bool was discarded, so tmux refusing the request led to switch-client on a nonexistent session and a silent exit. Adding -c made that reachable for a directory that stats but cannot be entered. - open_dir_picker: an unset thread launches sessions in home, so the picker now starts at home instead of tws's launch directory. Pressing c then Enter on such a thread no longer silently records the cwd. - The picker's filter text is dimmed while the path row is selected, so it does not read as a path segment Enter would take. - An empty listing now distinguishes "no subdirectories" from a filter that excluded everything. - Status hints: Enter is "use / open" since it descends on every row but the first, and Backspace's "up" hint was missing entirely. - set_thread_working_dir takes a PathBuf; no caller clears the field since Ctrl+x was dropped.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Each thread can carry an optional default working directory. Sessions launched from that thread start there. Threads without one start in the home directory.
How it works
Press
con a thread to open the directory picker. The top row is the directory you are browsing, and the cursor starts there:Enteron the top row accepts the directory you are browsingEnteron a subdirectory descends into it, so Enter never records a directory you did not navigate toTabcompletes into the first match, so typing a segment and tabbing walks downward like a shellBackspacedeletes a filter character, or goes up a level when the filter is emptyEsccancelsTyping filters the list; the filter is dimmed because
Entertakes the directory, not the typed text. To point a thread back at home, Backspace up to~and pressEnter.Creating a thread opens the picker right after you name it.
Escthere leaves a valid thread with no directory. The tree shows each thread's directory as a dim suffix, brighter on the selected row.Notes for review
~rather than inheriting the directorytwswas launched from. Launch behavior no longer depends on where you started the app.~, and tmux shows a warning. Inside tmux this goes throughdisplay-message, becauseswitch-clientends the app before another frame is drawn.~form is display-only.Thread.working_diruses#[serde(default)], so existingstate.jsonfiles load unchanged, and an older binary ignores the field.core/workdir.rswith no ratatui dependency, which is what makes it unit-testable.app.rsgrows oneModevariant and a handler that delegates every keystroke.centered_rectmoved fromfinder_modal.rstocomponents/mod.rsso both modals share one copy.[keys.dir_picker]config section; every binding is rebindable.Verification
cargo fmt --all --checkandcargo clippy --all-targets -- -D warningscleanpwd, the home fallback, and the stale-directory path both falling back and surfacing its warningReview round
Eight findings from a review pass were verified against the code and all seven actionable ones fixed in f5811e9: the
shorten_homefake-~bug when home is unresolvable,new_session's discarded failure, the picker'scwdfallback, the filter reading as a path segment, "no subdirectories" vs "no matches", the staleEnterhint and missing Backspace hint, and a vestigialOptionon the setter. One was deliberately deferred and recorded: previewing which entryTabwill jump to under a substring filter.🤖 Generated with Claude Code