- Reorder Category() to check known extensions (text, config, image,
pdf, audio, video, archive) before the executable bit check.
Fixes video/audio/image files with executable bit being opened in
editor instead of system default application.
- Remove 'executable' from isEditableEntry() - executables are now
launched via handleExecute() instead of opened in Neovim.
- Add handleExecute() method that runs executable files in the
terminal via tea.ExecProcess.
- Update handleOpenSelected() to route: text/config -> editor,
executable -> launch, everything else -> system default (xdg-open).
- Bump version to v0.2.1
Add rich preview support for three new file categories by leveraging
external CLI tools with graceful fallback when tools are missing.
- PDF: text extraction via pdftotext, page count via pdfinfo
- Audio: metadata via ffprobe (duration, bitrate, codec, sample rate, channels)
- Video: metadata via ffprobe (duration, bitrate, video/audio codec, resolution)
- New PreviewKind constants: PDF, Audio, Video
- New Metadata fields for extended preview data
- New extension maps and Category() entries for pdf/audio/video
- Icons: PDF (), audio (), video () in preview header
Closes#5
Pressing / opens a filter bar at the bottom of the screen. As the user
types, the active pane's entries are filtered in real-time using
case-insensitive substring matching. The .. entry is always preserved.
Key bindings:
/ - open filter input (re-opens with previous query if active)
Esc - clear filter and restore full list
Enter - commit filter (keeps filtering active, closes input bar)
Up/Down - navigate the filtered list while typing
PgUp/Dn - scroll the filtered list
Filter is automatically cleared when navigating to a different directory
(Enter on a folder, Backspace to parent, opening an archive).
Modified files:
- internal/ui/keymap.go: added Filter key binding (/)
- internal/ui/model.go: filterMode, filterQuery, filterInput fields;
filteredPane() helper for View rendering; filter handling in Update();
renderFilterBar() for the bottom bar UI; clearFilter() helper;
adjustCursorForFilter() to keep cursor in bounds
Created files:
- plans/feature-roadmap.md
Root cause: renderPreviewPane() was stuffing directory entries into the
viewport model via SetContent(), then rendering through
renderPreviewContent() which wraps the viewport in an additional
border+padding box. This reduced the effective content width by 4
characters compared to the browser pane's innerWidth (width-2), causing
column misalignment where the date column would wrap to the next line.
Fix: For directory previews, directly render entries using the same
renderPaneRows() and renderColumnsHeader() functions as the browser
pane, at the same innerWidth. A temporary BrowserPane is created with
the directory entries, and renderPaneRows() is called with active=false,
producing pixel-identical output to the main file browser.
Removed renderDirectoryPreviewBody() which is no longer needed.
- Update README with all 17 built-in themes
- Add font installation instructions for NixOS and Arch Linux
- Add terminal font config for Foot, WezTerm, and Windows Terminal
- Bump version references from v0.1.8 to v0.1.9
- View (F3): add 'v' as alternative key, help shows 'F3/v'
- ShortHelp footer: add Move (F6/m) and Mkdir (F7/n)
- FullHelp: remove Visual ('v visual') from help panels
- Fix: remove 'n' from Cancel keys so it doesn't conflict
with Mkdir's 'n' binding (Cancel now only uses Esc)
- Reset cursor to '..' (position 0) when entering an archive so it
doesn't stay at the previous directory's cursor position
- Fix archive exit landing in /tmp when pressing Enter on '..' inside
an archive by delegating to archive-aware goParent() in enterSelected()
- Fix goParent() to handle ALL navigation within archive mounts
explicitly instead of falling through to filepath.Dir which may
navigate outside the mount to /tmp
- Fix format cycling text color reset by preserving '(f to change)'
hint in modal note, ensuring renderModalNoteLine applies proper
key/action styling via the '(' separator match
Expand textExtensions with many missing common text file extensions
(.lua, .rb, .vue, .svelte, .dart, .tex, .scala, .lisp, and many more).
Add textFilenames list for well-known text files without a meaningful
extension (Makefile, Dockerfile, README, LICENSE, .gitignore, etc.)
so they open in the editor via handleEdit() instead of falling back
to xdg-open via handleOpenExternal().
Replace full ANSI reset sequences (\x1b[0m) added by lipgloss.Render() for
gutter markers, cursor highlights, and selection highlights with
background-preserving resets (\x1b[39;22;23;24;59;48;2;R;G;Bm) that restore
the panel background color.
Without this fix, every \x1b[0m from lipgloss-styled elements in
renderTextCursorContent resets the panel background (set by the outer
renderPreviewContent wrapper), causing some letters to have incorrect or
missing background color in caret mode.