Skip to content

feat: open external files from browser via "i" key #178

@oobagi

Description

@oobagi

Problem

Opening external files (e.g. ~/.zshrc, config files) currently requires exiting
the TUI and running notebook ~/.zshrc from the CLI. This breaks flow — the whole
point of the TUI is staying in it.

Context

The plumbing already exists:

  • openFile() in cmd/file.go handles reading, editing, saving, and permission
    preservation for arbitrary files
  • recents.RecordExternal() tracks external files in the Recent section after opening
  • Input mode (startCreate, startRename in browser.go) provides a status-bar
    text prompt pattern with Enter/Esc handling and cursor blink
  • External files already render in recents via format.ShortenHome() and can be
    re-opened from there

The new feature would wire these together: i → input prompt → validate path → open file.

Possible approaches

Approach A: Reuse inputMode directly

  • How: Add startImport() following the startCreate()/startRename() pattern.
    Set inputPrompt = "Open file:", resolve path in inputAction callback, then
    set m.selected with FilePath and quit to the browse loop.
  • Pros: Minimal new code, fully consistent with existing UX
  • Cons: No tab-completion for paths (can be added later)
  • Files: internal/browser/browser.go (key handler + startImport), help overlay

Approach B: Selection-based with path in Selection

  • How: Same as A but instead of opening inline, return a Selection{FilePath: path}
    so the browse.go loop handles opening via existing openFile() path
  • Pros: Keeps editor launch in one place (browse.go), external files return to L0
    correctly via existing FromRecent logic
  • Cons: None significant — this is the cleaner version of A
  • Files: internal/browser/browser.go, cmd/browse.go (already handles FilePath)

Approach B is recommended — it reuses the browse loop's existing external file handling.

Tasks

  • Add startImport() method using the inputMode pattern
  • Bind i key at L0 (confirm unbound — currently unused)
  • In the input action: expand ~, resolve to absolute path, validate file exists
    and is readable, return Selection{FilePath: path, FromRecent: true}
  • Add i Open file to browser help overlay
  • Add test for import flow (input mode → path → selection)

Test plan

  • Press i at L0 → status bar shows "Open file:" prompt
  • Enter valid path (absolute, relative, ~/...) → file opens in editor
  • Save and quit editor → file appears in Recent section
  • Enter nonexistent path → inline error, stays in browser
  • Enter unreadable path → inline error with OS message
  • Esc during prompt → cancels cleanly, no side effects
  • Existing external file re-opening from recents still works

Scope

Type: feature
Size: small

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