Skip to content

feat: directory browser mode — browse filesystem with split-pane file preview #195

@oobagi

Description

@oobagi

Problem

The only way to browse and read arbitrary files on disk is to leave the terminal and open VS Code (or similar) just for the sidebar file tree. Notebook should support this workflow natively — a directory mode that shows a file listing on the left and file contents on the right.

Context

The browser (internal/browser/browser.go) currently uses a single-column layout with level-based navigation (level: 0 = notebooks, level: 1 = notes). There's no split-pane layout anywhere in the codebase. The editor has a read-only view mode (viewMode flag) with markdown rendering that could be reused for file preview.

Key existing patterns to build on:

  • Mode flags: showHelp, themeMode, inputMode — cascading boolean flags that control rendering and input precedence
  • Filtered indirect access: cursor → filtered[] → data source — used for all list navigation
  • Async loading: message types like notebooksLoadedMsg + tea.Cmd functions
  • Preview pane: showPreview already appends inline previews to note lines — but this needs a true side-by-side layout
  • Selection return: Selection.FilePath already exists for external file paths

Related: #178 (open external files via i key) — directory mode would complement or subsume that.

Approach

Create a new internal/filebrowser/ package with its own Bubble Tea Model. Wire it into the app as a separate program (same pattern as browser ↔ editor), entered via a keybind from the browser (e.g., d for directory).

Architecture

internal/filebrowser/
├── filebrowser.go    # Model, Init, Update, View, key handlers
├── render.go         # Split-pane layout, file tree, content pane
└── preview.go        # File content reading, binary detection, truncation

Split-pane layout (lipgloss):

┌─ sidebar (30-40%) ──────┬─ content (60-70%) ──────────────┐
│ 📁 ..                   │ # README.md                     │
│ 📁 cmd/                 │                                 │
│ 📁 internal/            │ Notebook is a terminal-based... │
│   main.go               │                                 │
│ > go.mod                │ ## Installation                 │
│   go.sum                │ ...                             │
│   README.md             │                                 │
├──────────────────────────┤                                 │
│ /filter...              │                                 │
└──────────────────────────┴─────────────────────────────────┘
  breadcrumb: ~/Developer/notebook           3/12 files  go.mod

Key behaviors

  • Left pane: directory listing with cursor, dirs first then files, .. entry at top
  • Right pane: file content preview (read-only, scrollable), markdown rendered for .md files
  • Enter on dir: navigate into it, reload listing
  • Enter on file: could open in $EDITOR or return to browser with file path
  • Esc / Backspace: go up one directory (or exit mode)
  • /: filter files in current directory (reuse existing filter pattern)
  • p: toggle preview pane (like browser's showPreview)
  • y: copy file path to clipboard (reuse internal/clipboard)

File preview handling

  • Text files: show raw content, scroll with j/k or arrow keys in right pane
  • Markdown files: render with existing view mode renderer if feasible
  • Binary files: show file size, type, and "binary file" message
  • Large files: truncate with "file too large to preview" after threshold (~100KB)

Tasks

  • Create internal/filebrowser/ package with Model struct — dir path, entries, cursor, filtered indices, preview content, scroll offset
  • Implement os.ReadDir() loading via async tea.Cmd message pattern
  • Build split-pane View() with lipgloss — sidebar file list + content pane, responsive to terminal width
  • Add cursor navigation, directory enter/exit, .. parent traversal
  • Add file content reading for right pane — text detection, size limits, scroll
  • Add filter mode (reuse filtering/filtered[] pattern from browser)
  • Add breadcrumb bar showing current directory path
  • Add clipboard support (y to copy path)
  • Wire into cmd/ — launch from browser via keybind, handle return
  • Integrate theming via theme.Current()

Acceptance criteria

  • Can enter directory mode from the browser via keybind
  • Directory listing shows folders first, then files, with .. at top
  • Navigating into directories and back out works smoothly
  • Selecting a file shows its contents in the right pane
  • Right pane scrolls for long files
  • Binary files show a placeholder instead of garbled content
  • Filter narrows the file list
  • Esc exits back to the notebook browser
  • Respects current theme

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions