- Add Mirror pane keybinding p (for 'Pane'), SSH restored on s - Add session-scoped cursor memory per directory - Fix cursor memory bug: DisplayName() adds trailing / for directories - Fix remote mirror: use active.Path instead of mount.RemotePath - Remove F-key/Mouse/b/c entries from F1 help dialog - Remove Mirror from ShortHelp footer (F-keys only) - Add missing letter-key bindings to help: p, s, a, n, x
3.8 KiB
3.8 KiB
Feature Plan: Mirror Pane & Per-Directory Cursor Memory
Feature 1: Mirror active pane directory to opposite pane
Keybinding research
- Midnight Commander (MC):
Alt-i— makes the other panel equal to current directory - Total Commander:
Ctrl-PgDnopens directory under cursor in opposite panel - Far Manager:
Ctrl-Left/Right— opens in opposite panel
Recommendation: Bind to p (for "Pane"). Ctrl-i sends the same byte as Tab (ASCII 0x09) so it conflicts with Switch. p is free, accessible, and "Pane" reflects the meaning.
How it works
- Read active pane's current path (including remote mount state)
- Apply that path to the passive (opposite) pane
- If active is in a remote mount, also clone the remote mount stack to the passive pane
- Reload both panes to reflect the change
Code changes
internal/ui/keymap.go
- Add
Mirrorkey binding field toKeyMapstruct - Bind to
"p"with help text"p"/"mirror pane"
internal/ui/model.go
- Add handler
handleMirrorPane():- Get active pane path and remote mount state
- Switch passive pane to match (copy remote stack if applicable)
- Reload passive pane (using
reloadPaneorreloadRemotePane) - Set status:
"Mirrored: <path>"
- Add key match case before the
defaultswitch
Feature 2: Per-directory cursor position memory (session scope)
Current state
enterSelected()savespane.Pathto history for back-nav, then reloads target dir withselected.Nameas preserve key — butselected.Nameis the name of the directory being entered, not a cursor anchorgoParent()pops history and reloads parent using the child directory name as preserve — cursor lands on the directory we came from- Missing: When navigating back into a previously-visited directory, there's no saved cursor position for it
Design
Add a cursorMemory field to BrowserPane — a map[string]string mapping directory path → last selected entry display name.
This integrates cleanly with the existing SetEntries(entries, preserveKey) / FindSelected() infrastructure.
Flow
enterSelected() / enterRemoteDir():
1. Save to cursorMemory: pane.Path → selected entry's Name
2. Push history (existing)
3. Set path, reload (existing)
4. The reload already uses preserve=selected.Name for the new dir,
but cursorMemory will help when coming back later
reloadPane() / reloadRemotePane():
1. Try preserve key first (existing behavior)
2. If preserve is empty, check cursorMemory[pane.Path]
and use that as preserveKey instead
Code changes
internal/ui/pane.go
- Add field to
BrowserPane:CursorMemory map[string]string - Method
SaveCursor(path string, name string)— stores cursor position - Method
LoadCursor(path string) string— retrieves saved cursor
internal/ui/model.go
- In
enterSelected()(line ~1886): afterpane.PushHistory(pane.Path), addpane.SaveCursor(pane.Path, selected.Name) - In
enterRemoteDir()(line ~5726): same save logic - In
goParent(): save cursor before navigating away (already partially done via history) - In
reloadPane()(line ~1672): after existing preserve logic, if no preserve key and directory has cursor memory, use it - In
reloadRemotePane()(line ~5535): same fallback
Files modified
| File | Changes |
|---|---|
internal/ui/keymap.go |
Add Mirror field, binding p |
internal/ui/pane.go |
Add CursorMemory field + methods |
internal/ui/model.go |
Add handleMirrorPane(), save/restore cursor in navigation methods |
Not changed
internal/fs/— storage layer unaffectedinternal/config/— no config changes neededinternal/theme/— no theme changes needed