From beae5fc02602c0ba0f4c2958f13392308d69e67c Mon Sep 17 00:00:00 2001 From: Greg Pomerantz Date: Fri, 5 Jun 2026 13:43:27 -0400 Subject: [PATCH] Fix directory navigation and path initialization - Initialize browser path to the actual startup directory instead of '/' - Improve '..' navigation to be relative to the filesystem root - Fix path duplication issues by avoiding redundant absolute path joining --- cmd/pad/main.go | 15 ++++++++++++--- internal/browser/handlers.go | 23 +++++++++++++++++------ internal/browser/manager.go | 9 ++++++--- internal/editor/logic.go | 10 +++++++--- 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/cmd/pad/main.go b/cmd/pad/main.go index 3eb5d9f..28499cd 100644 --- a/cmd/pad/main.go +++ b/cmd/pad/main.go @@ -4,6 +4,7 @@ import ( "flag" "log" "os" + "path/filepath" "sync" "gioui.org/app" @@ -40,10 +41,18 @@ func run(w *app.Window) error { rootDir := flag.String("root", startpath, "root directory for the filesystem") flag.Parse() - fs := real.NewRealFileSystem(*rootDir) - log.Printf("using filesystem at %s", fs.WorkingDir) + // Initialize the real filesystem rooted at the system root "/" + // so that the browser can navigate the entire system. + fs := real.NewRealFileSystem("/") + + // Get the absolute path of the startup directory + startAbs, err := filepath.Abs(*rootDir) + if err != nil { + startAbs = *rootDir + } + log.Printf("using filesystem at / (startup directory: %s)", startAbs) - logic := editor.NewLogic(fs) + logic := editor.NewLogic(fs, startAbs) renderer := ui.New(ui.Theme{FontSize: 14}, shaper, logic.State()) var mu sync.Mutex var elems []ui.Element diff --git a/internal/browser/handlers.go b/internal/browser/handlers.go index f6dc03a..538521b 100644 --- a/internal/browser/handlers.go +++ b/internal/browser/handlers.go @@ -3,8 +3,6 @@ package browser import ( "fmt" "path/filepath" - "strings" - "pad/internal/ui" ) @@ -81,11 +79,24 @@ func HandleBrowserTap(bm *BrowserManager, s *BrowserState, index int) { // Navigate into directory or up var newPath string if entry.Name == ".." { - newPath = filepath.Dir(s.CurrentPath) + // If we are at the root (".") stay there + if s.CurrentPath == "." || s.CurrentPath == "" { + newPath = "." + } else { + // Get parent directory + parent := filepath.Dir(s.CurrentPath) + if parent == "." || parent == "/" { + newPath = "." + } else { + newPath = parent + } + } } else { - newPath = filepath.Join(s.CurrentPath, entry.Name) - if !strings.HasPrefix(newPath, "/") { - newPath = "/" + newPath + // Join child entry name + if s.CurrentPath == "." { + newPath = entry.Name + } else { + newPath = filepath.Join(s.CurrentPath, entry.Name) } } bm.NavigateTo(newPath) diff --git a/internal/browser/manager.go b/internal/browser/manager.go index a1efa79..aa6ed6a 100644 --- a/internal/browser/manager.go +++ b/internal/browser/manager.go @@ -26,7 +26,8 @@ func NewBrowserManager(state *BrowserState, wp *pool.WorkerPool, fs pool.FileSys } func (bm *BrowserManager) NavigateTo(dirPath string) { - fmt.Printf("NavigateTo: %s\n", dirPath) + fmt.Printf("NavigateTo: dirPath=%s, state.CurrentPath=%s\n", dirPath, bm.state.CurrentPath) + bm.state.CurrentPath = dirPath navigateToDirectory(bm.state, dirPath) bm.state.Loading = true @@ -86,7 +87,6 @@ func (bm *BrowserManager) HandleResult(result pool.Result) { } func (bm *BrowserManager) handleBuildIndexSuccess(result pool.Result) { - fmt.Printf("handleBuildIndexSuccess: TotalEntries=%d\n", len(result.Data.([]types.DirEntry))) bm.state.Loading = false // In the mock implementation, BuildIndexTask returns []types.DirEntry. @@ -95,7 +95,9 @@ func (bm *BrowserManager) handleBuildIndexSuccess(result pool.Result) { var browserEntries []Entry // Add ".." entry if not at root - if bm.state.CurrentPath != "/" && bm.state.CurrentPath != "." { + // We check against "/" specifically. "." is just a relative path for current dir, + // which still has a parent. + if bm.state.CurrentPath != "/" && bm.state.CurrentPath != "" { browserEntries = append(browserEntries, Entry{ Path: filepath.Dir(bm.state.CurrentPath), Name: "..", @@ -107,6 +109,7 @@ func (bm *BrowserManager) handleBuildIndexSuccess(result pool.Result) { for _, e := range entries { info, _ := e.Info() + fmt.Printf("Adding entry: %s\n", e.Name()) browserEntries = append(browserEntries, Entry{ Path: filepath.Join(bm.state.CurrentPath, e.Name()), Name: e.Name(), diff --git a/internal/editor/logic.go b/internal/editor/logic.go index 511cc08..6ad96e6 100644 --- a/internal/editor/logic.go +++ b/internal/editor/logic.go @@ -66,7 +66,7 @@ type Logic struct { } // NewLogic creates a new Logic instance, accepting an optional mockFS. -func NewLogic(mfs pool.FileSystem) *Logic { +func NewLogic(mfs pool.FileSystem, startPath ...string) *Logic { state := NewState() TheState = state @@ -81,8 +81,12 @@ func NewLogic(mfs pool.FileSystem) *Logic { wp := pool.NewWorkerPool(4) wp.Start() - // Set browser initial path to mock root - state.Browser.CurrentPath = "/" + // Set browser initial path + path := "/" + if len(startPath) > 0 { + path = startPath[0] + } + state.Browser.CurrentPath = path bm, _ := browser.NewBrowserManager(&state.Browser, wp, mockFS) TheLogic = &Logic{