tui-file-explorer
A keyboard-driven, two-pane file manager widget for Ratatui.
Use it as an embeddable library widget or run it as the standalone tfe CLI tool.
Preview
Navigation · Search · Sort — cargo run --example basic

File Operations — copy, cut, paste, delete across two panes · cargo run --bin tfe

27 Live Themes — cargo run --example theme_switcher

DualPane Library Widget — Tab focus, w toggle, independent panes · cargo run --example dual_pane

Options Panel & Snackbar — editor picker, toggles, error notification · cargo run --bin tfe then Shift+O

Features
- 🗂️ Two-pane layout — independent left and right explorer panes,
Tabto switch focus - 📋 File operations — copy (
y), cut (x), paste (p), and delete (d) between panes - 🔍 Incremental search — press
/to filter entries live as you type - 🔃 Sort modes — cycle
Name → Size ↓ → Extensionwiths - 🎛️ Extension filter — only matching files are selectable; dirs are always navigable
- 👁️ Toggle hidden dot-file visibility with
. - ⌨️ Full keyboard navigation: Miller-columns
←/→(ascend/descend), vim keys (h/j/k/l),↑/↓/j/k,PgUp/PgDn,g/G—→on a file moves down, never exits the TUI - 🎨 27 named themes — Catppuccin, Dracula, Nord, Tokyo Night, Kanagawa, Gruvbox, and more
- 🎛️ Live theme panel — press
tto open a side panel,[/]to cycle themes - 🔧 Fluent builder API for ergonomic embedding — both
FileExplorerandDualPane - 📦
DualPanelibrary widget — drop a full two-pane explorer into any Ratatui app with one struct - 🖥️
cdon exit — dismiss withEsc/qand your terminal jumps to the directory you were browsing; one-time setup withtfe --init <shell>(bash, zsh, fish, powershell) - ✅ Lean library — only
ratatui+crosstermrequired (clapis opt-out)
Stats
| Metric | Value |
|---|---|
| Library dependencies | 2 (ratatui, crossterm) |
| Named colour themes | 27 |
| Sort modes | 3 (Name, Size ↓, Extension) |
| File operations | 4 (copy, cut, paste, delete) |
| Key bindings | 20+ |
| File-type icons | 50+ extensions mapped |
| Public API surface | 10 types, 6 free functions |
| Unit tests | 475 |
Installation
As a library
[]
= "0.3"
= "0.30"
Library-only (no clap-powered CLI binary):
[]
= { = "0.3", = false }
As a CLI tool
Installs the tfe binary onto your PATH.
Quick Start
Single-pane
use ;
use ;
// 1. Create once — e.g. in your App::new
let mut explorer = builder
.allow_extension
.allow_extension
.sort_mode // largest files first
.show_hidden
.build;
// 2. Inside Terminal::draw:
// render(&mut explorer, frame, frame.area());
// 3. Inside your key-handler — ↑/↓/←/→ scroll the list, Enter confirms:
let key = new;
match explorer.handle_key
Dual-pane
use ;
use ;
use PathBuf;
// 1. Create once — left pane defaults to cwd; right pane can differ.
let mut dual = builder
.right_dir
.show_hidden
.build;
let theme = default;
// 2. Inside Terminal::draw:
// render_dual_pane_themed(&mut dual, frame, frame.area(), &theme);
// 3. Inside your key-handler:
let key = new;
match dual.handle_key
Key Bindings
Navigation
| Key | Action |
|---|---|
↑ / k |
Move cursor up |
↓ / j |
Move cursor down |
PgUp |
Jump up 10 rows |
PgDn |
Jump down 10 rows |
g / Home |
Jump to top |
G / End |
Jump to bottom |
→ / l / Enter |
Descend into directory; on a file → moves cursor down, l/Enter confirm (exits TUI) |
← / h / Backspace |
Ascend to parent directory |
Tab |
Switch active pane (left ↔ right) |
w |
Toggle two-pane ↔ single-pane layout |
Explorer actions
| Key | Action |
|---|---|
/ |
Activate incremental search |
s |
Cycle sort mode (Name → Size ↓ → Extension) |
. |
Toggle hidden (dot-file) entries |
Esc |
Clear search (if active), then dismiss |
q |
Dismiss when search is not active |
File operations
| Key | Action |
|---|---|
y |
Yank — mark highlighted entry for copy |
x |
Cut — mark highlighted entry for move |
p |
Paste — copy/move clipboard into the other pane's directory |
d |
Delete — remove highlighted entry (asks for confirmation) |
Layout & theme controls
| Key | Action |
|---|---|
w |
Toggle two-pane ↔ single-pane layout |
t |
Next theme |
T |
Toggle theme panel (right sidebar) |
[ |
Previous theme |
Search mode (after pressing /)
| Key | Action |
|---|---|
| Any character | Append to query — list filters live |
Backspace |
Remove last character; empty query exits search |
Esc |
Clear query and exit search |
↑ / ↓ / j / k |
Scroll the filtered results |
→ / Enter / l |
Descend into directory or confirm/navigate entry |
← / Backspace / h |
Ascend to parent directory |
Two-Pane File Manager
The tfe binary opens a split-screen file manager with a left and right pane.
┌─── Left Pane (active) ──────────┬─── Right Pane ───────────────────┐
│ 📁 ~/projects/tui-file-explorer │ 📁 ~/projects/tui-file-explorer │
├─────────────────────────────────┤──────────────────────────────────┤
│ ▶ 📁 src/ │ 📁 src/ │
│ 📁 examples/ │ 📁 examples/ │
│ 📄 Cargo.toml │ 📄 Cargo.toml │
│ 📄 README.md │ 📄 README.md │
├─────────────────────────────────┴──────────────────────────────────┤
│ 📋 Copy: main.rs Tab pane y copy x cut p paste d del │
└────────────────────────────────────────────────────────────────────┘
- The active pane renders with your full theme accent; the inactive pane dims its borders so focus is always clear at a glance
- Press
Tabto switch which pane has keyboard focus - Arrow keys (
←/→) scroll the cursor up/down without entering or exiting a directory — useEnter/lto descend andBackspace/hto ascend - Press
wto collapse to a single pane — the hidden pane keeps its state and reappears when you presswagain - Press
t/[to cycle themes forward / backward; pressTto open the theme panel - Each pane navigates independently — scroll to different directories and use one as source, one as destination
File Operations (Copy / Cut / Paste / Delete)
The classic Midnight Commander source-to-destination workflow:
- Navigate to the file you want in the active pane
yto yank (copy) orxto cut it — the status bar confirms what is in the clipboardTabto switch to the other pane and navigate to the destination directorypto paste — the file is copied (or moved for cut) into that pane's directory
Active pane: ~/projects/src/ Other pane: ~/backup/
▶ main.rs ← press y ← press p here → main.rs appears
If the destination file already exists a confirmation modal appears asking whether to overwrite. Delete (d) also shows a modal before any data is removed.
All file operations support directories — copy and delete both recurse automatically.
Incremental Search
Press / to activate search mode. The footer transforms into a live input bar showing your query. Entries are filtered in real-time using a case-insensitive substring match on the file name.
// Inspect search state programmatically:
println!;
println!;
Behaviour details:
Backspaceon a non-empty query pops the last characterBackspaceon an empty query deactivates search without dismissingEscclears the query and deactivates search — a secondEsc(when search is already inactive) dismisses the explorer entirely- Search is automatically cleared when navigating into a subdirectory or ascending to a parent
Sort Modes
Press s to cycle through three sort modes, or set one directly:
use ;
let mut explorer = new;
explorer.set_sort_mode; // largest files first
println!; // "size ↓"
| Mode | Trigger | Description |
|---|---|---|
SortMode::Name |
s (1st press) |
Alphabetical A → Z — the default |
SortMode::SizeDesc |
s (2nd press) |
Largest files first |
SortMode::Extension |
s (3rd press) |
Grouped by extension, then by name |
Directories always sort alphabetically among themselves regardless of the active mode. The current sort mode is shown in the footer status panel at all times.
Extension Filtering
Only files whose extension matches the filter are selectable. Directories are always shown and always navigable, regardless of the filter.
use FileExplorer;
// Builder API (preferred)
let explorer = builder
.allow_extension
.allow_extension
.build;
// Or replace the filter at runtime — reloads the listing immediately
explorer.set_extension_filter;
// Pass an empty filter to allow all files
explorer.set_extension_filter;
Non-matching files are shown dimmed so the directory structure remains visible. Attempting to confirm a non-matching file shows a status message in the footer.
Builder API
FileExplorer::builder
FileExplorer::builder gives a fluent, chainable construction API:
use ;
let explorer = builder
.allow_extension // add one extension at a time
.allow_extension
.show_hidden // show dot-files on startup
.sort_mode // initial sort order
.build;
Or pass the full filter list at once:
let explorer = builder
.extension_filter
.build;
The classic FileExplorer::new(dir, filter) constructor is still available and fully backwards-compatible.
DualPane::builder
DualPane::builder mirrors the single-pane builder and adds dual-pane-specific options:
use ;
use PathBuf;
let dual = builder
.right_dir // independent right-pane directory
.allow_extension // applied to both panes
.allow_extension
.show_hidden // both panes
.sort_mode // both panes
.single_pane // start in dual-pane mode (default)
.build;
Once built, pane directories, sort mode, and hidden-file visibility can still be changed independently on dual.left and dual.right at runtime.
| Builder method | Effect |
|---|---|
.right_dir(path) |
Independent starting directory for the right pane |
.allow_extension(ext) |
Append one extension to the shared filter |
.extension_filter(vec) |
Replace the shared filter entirely |
.show_hidden(bool) |
Hidden-file visibility for both panes |
.sort_mode(mode) |
Initial sort order for both panes |
.single_pane(bool) |
Start in single-pane mode (default false) |
Theming
Every colour used by the widget is overridable through the Theme struct. Pass a Theme to render_themed instead of render:
use ;
use Color;
let theme = default
.brand // widget title
.accent // borders & current path
.dir // directory names & icons
.sel_bg // highlighted-row background
.success // status bar & selectable files
.match_file;
terminal.draw?;
Named presets (27 included)
All presets are available as associated constructors on Theme:
use Theme;
let t = dracula;
let t = nord;
let t = catppuccin_mocha;
let t = catppuccin_latte;
let t = tokyo_night;
let t = tokyo_night_storm;
let t = gruvbox_dark;
let t = kanagawa_wave;
let t = kanagawa_dragon;
let t = moonfly;
let t = oxocarbon;
let t = grape;
let t = ocean;
let t = neon;
// Iterate the full catalogue (name, description, theme):
for in all_presets
Full preset list:
Default · Dracula · Nord · Solarized Dark · Solarized Light · Gruvbox Dark · Gruvbox Light · Catppuccin Latte · Catppuccin Frappé · Catppuccin Macchiato · Catppuccin Mocha · Tokyo Night · Tokyo Night Storm · Tokyo Night Light · Kanagawa Wave · Kanagawa Dragon · Kanagawa Lotus · Moonfly · Nightfly · Oxocarbon · Grape · Ocean · Sunset · Forest · Rose · Mono · Neon
Palette constants
The default colours are exported as pub const values for use alongside complementary widgets:
| Constant | Default | Used for |
|---|---|---|
C_BRAND |
Rgb(255, 100, 30) |
Widget title |
C_ACCENT |
Rgb(80, 200, 255) |
Borders, current-path text |
C_SUCCESS |
Rgb(80, 220, 120) |
Selectable files, status bar |
C_DIM |
Rgb(120, 120, 130) |
Hints, non-matching files |
C_FG |
White |
Default foreground |
C_SEL_BG |
Rgb(40, 60, 80) |
Selected-row background |
C_DIR |
Rgb(255, 210, 80) |
Directory names & icons |
C_MATCH |
Rgb(80, 220, 120) |
Extension-matched file names |
Examples
basic
examples/basic.rs — a fully self-contained Ratatui app demonstrating:
- Builder API and full event loop
- All
ExplorerOutcomevariants - Custom
Theme - Optional CLI extension-filter arguments
# Browse everything
# Only .rs and .toml files are selectable
dual_pane
examples/dual_pane.rs — a fully self-contained dual-pane Ratatui app built entirely on the library API (no binary code):
DualPane::builderwith an optional independent right-pane directoryrender_dual_pane_themedfor rendering both panes in one call- All
DualPaneOutcomevariants - Status bar showing active pane and current layout mode
| Key | Action |
|---|---|
Tab |
Switch focus left ↔ right |
w |
Toggle single-pane / dual-pane mode |
↑ / ↓ / j / k |
Move cursor up / down |
← / → |
Scroll cursor up / down (no navigation side-effects) |
Enter / l |
Descend into directory or confirm file |
Backspace / h |
Ascend to parent directory |
. |
Toggle hidden files |
/ |
Incremental search |
s |
Cycle sort mode |
Esc / q |
Quit |
# Both panes start in the current directory
# Left pane starts in cwd, right pane starts in /tmp
theme_switcher
examples/theme_switcher.rs — live theme switching without restarting, with a sidebar showing the full theme catalogue.
| Key | Action |
|---|---|
Tab |
Next theme |
Shift+Tab |
Previous theme |
↑ / ↓ / j / k |
Move cursor up / down |
← / → |
Scroll cursor up / down (no navigation side-effects) |
Enter / l |
Descend into directory or confirm file |
Backspace / h |
Ascend to parent directory |
. |
Toggle hidden files |
/ |
Search |
s |
Cycle sort mode |
Esc / q |
Quit |
options
examples/options.rs — dual-pane explorer with a fully interactive options panel:
- Editor picker: cycle through
none → helix → nvim → vim → nano → microwithe(while panel is open) - Error snackbar when
eis pressed outside the panel with no editor configured - Toggle
cd-on-exit, single-pane mode, and hidden-file visibility from the panel - Selecting a file with
Enterstays in the TUI and shows a helpful message when no editor is set
| Key | Action |
|---|---|
O |
Toggle options panel |
e (panel open) |
Cycle editor |
e (panel closed) |
Open current file in editor (or show snackbar if none set) |
Shift+C |
Toggle cd-on-exit |
w |
Toggle single-pane mode |
h |
Toggle hidden files |
s |
Cycle sort mode |
t |
Cycle theme |
Tab |
Switch active pane |
Esc / q |
Quit |
open_file
examples/open_file.rs — single-pane explorer that opens files in your editor and resumes browsing:
- Resolves editor from CLI arg →
$VISUAL→$EDITOR→vi - Tears down the TUI, launches the editor synchronously, then restores the TUI
- Status bar shows the last-opened filename and editor used
- Supports multi-word editor strings like
"code --wait"
# Uses $VISUAL / $EDITOR
# Explicit editor
Example Demos
Navigation & Search
Run: cargo run --example basic

Demonstrates directory navigation, incremental search (/), sort mode cycling (s), hidden-file toggle (.), directory descent and ascent, and file selection.
Incremental Search
Run: cargo run --example basic then press /

Shows the full search lifecycle: activate with /, type to filter live, use Backspace to narrow or clear, and Esc to cancel without dismissing the explorer.
Sort Modes
Run: cargo run --example basic then press s

Demonstrates Name → Size ↓ → Extension → Name cycling, combined with search, and sort persistence across directory navigation.
Extension Filter
Run: cargo run --example basic -- rs toml

Only .rs and .toml files are selectable; all other files appear dimmed. The footer reflects the active filter at all times.
File Operations
Run: cargo run --bin tfe

Demonstrates the full copy then paste and cut (move) then paste workflows across both panes, followed by a delete with confirmation modal. The clipboard status bar updates live after each y / x / p keystroke, and an overwrite-prompt appears when the destination file already exists.
Theme Switcher
Run: cargo run --example theme_switcher

Live theme cycling through all 27 named palettes with a real-time sidebar showing the catalogue and the active theme's description.
Pane Toggle
Run: cargo run --bin tfe

Demonstrates the three layout controls in sequence:
Tab— switch keyboard focus between the left and right pane; each pane navigates independently so you can be in different directories at the same timew— collapse to single-pane (the active pane expands to full width) and back to two-pane (the hidden pane reappears with its cursor position preserved)T— open and close the theme-picker sidebar; uset/[to cycle themes while the panel is open; both panes remain fully navigable with the panel visible
Options Panel & Snackbar
Run: cargo run --bin tfe then press Shift+O

Demonstrates the full options panel workflow:
Shift+O— open and close the options side panele(panel open) — cycle the editor:none → helix → nvim → vim → nano → micro → nonee(panel closed, no editor set) — triggers the error snackbar floating above the action bar, auto-dismissing after 4 secondsShift+C— togglecd-on-exiton/off with live indicatorw— toggle single-pane mode from inside the panelT— open the theme panel (closes the options panel); both panels cannot be open simultaneously
DualPane Library Widget
Run: cargo run --example dual_pane

A complete two-pane file manager built entirely on the library API — no binary code. Demonstrates:
DualPane::builderconstructing two independent panesrender_dual_pane_themedrendering both panes in a single callTabswitching keyboard focus; each pane tracks its own cursor and directorywcollapsing to single-pane mode (active pane fills the full width) and back- Incremental search (
/) and sort cycling (s) inside the active pane - A live status bar showing the active pane label and current layout mode
DualPaneOutcome::Selected— selecting a file prints its path to stdout and exits
Demo Quick Reference
| Demo | Command | Highlights |
|---|---|---|
| Navigation + Search | cargo run --example basic |
All key bindings, search, sort, selection |
| Extension filter | cargo run --example basic -- rs toml |
Dimmed non-matching files, footer status |
| Incremental search | cargo run --example basic → / |
Live filtering, backspace, Esc behaviour |
| Sort modes | cargo run --example basic → s |
Three modes, combined with search |
| Dual-pane (library) | cargo run --example dual_pane |
DualPane widget, Tab focus, w toggle, status bar |
| Dual-pane (right dir) | cargo run --example dual_pane -- /tmp |
Independent left/right starting directories |
| File operations | cargo run --bin tfe |
Copy, cut, paste, delete, overwrite modal |
| Theme switcher | cargo run --example theme_switcher |
27 live themes, sidebar catalogue |
| Pane toggle | cargo run --bin tfe |
Tab focus-switch, w single/two-pane, T theme panel |
| Options panel | cargo run --bin tfe then Shift+O |
Editor picker, toggles, error snackbar |
| Dual-pane GIF | vhs examples/vhs/dual_pane.tape |
Full dual_pane example recorded end-to-end |
CLI Usage
| Flag | Description |
|---|---|
[PATH] |
Starting directory (default: current directory) |
-e, --ext <EXT> |
Only select files with this extension (repeatable) |
-H, --hidden |
Show hidden dot-files on startup |
-t, --theme <THEME> |
Colour theme — see --list-themes |
--list-themes |
Print all 27 available themes and exit |
--show-themes |
Open the theme panel on startup (T toggles it at runtime) |
--single-pane |
Start in single-pane mode (default is two-pane; toggle at runtime with w) |
--print-dir |
Print the parent directory of the selected file instead of the full path |
-0, --null |
Terminate output with a NUL byte (for xargs -0) |
--cd |
Enable cd-on-exit: on dismiss, print the active pane's directory to stdout (persisted) |
--no-cd |
Disable cd-on-exit (persisted) |
--init <SHELL> |
Install the shell wrapper for cd-on-exit and exit. Shells: bash, zsh, fish, powershell, nushell |
-h, --help |
Show help |
-V, --version |
Show version |
Exit codes
| Code | Meaning |
|---|---|
0 |
File selected — path printed to stdout |
0 |
Dismissed with --cd enabled — active pane's directory printed to stdout |
1 |
Dismissed without --cd — nothing printed |
2 |
Bad arguments or I/O error |
Shell integration (cd on exit)
The killer feature: press Esc or q to dismiss tfe and your terminal
automatically cds to whichever directory you were browsing.
Works on macOS, Linux, and Windows with bash, zsh, fish, PowerShell,
and Nushell.
cd-on-exit is enabled by default. Run tfe --no-cd to turn it off,
or tfe --cd to turn it back on. The setting is persisted across sessions.
How setup works
On the very first run, tfe automatically:
- Detects your shell (
$NU_VERSIONfor Nushell,$SHELLon Unix/macOS,$PSModulePathfor PowerShell on Windows). - Writes the shell wrapper function to your rc file (e.g.
~/.zshrc,~/.config/nushell/config.nu). - Emits a special
source:directive to stdout that the wrapper — now written but not yet active — cannot intercept yet.
Because the wrapper isn't active in the current session until the rc file is sourced, you need to do one of the following, once:
Or simply open a new terminal tab/window — the wrapper will be active automatically from that point on, forever.
Why only once? A child process (like
tfe) cannot modify its parent shell's environment — that is a hard OS rule. The shell wrapper exists precisely to work around this: once it is active, it interceptstfe's stdout, acts onsource:directives andcdpaths, and everything is fully automatic with no further user action required.
From the second session onward — fully automatic
Once the wrapper is active, using tfe is completely seamless:
- Dismiss with
Escorq→ shellcds to the directory you were browsing. - Select a file with
Enter→ path is printed to stdout for piping. - No flags, no commands, no thought required.
Manual installation (--init)
If you prefer to install the wrapper explicitly rather than waiting for the auto-install on first run:
--init is idempotent — running it twice will never duplicate the snippet.
It tells you exactly where it wrote and reminds you to source the file.
How it works under the hood
| Situation | stdout | exit code |
|---|---|---|
File selected (Enter / l) |
selected file path | 0 |
Dismissed (Esc / q) + cd-on-exit enabled |
active pane's directory | 0 |
| Dismissed + cd-on-exit disabled | (nothing) | 1 |
| First run — wrapper just installed | source:<rc-path> then directory |
0 |
The TUI renders on stderr so it is never swallowed by the shell's
$() capture. The wrapper reads tfe's stdout line by line: lines
beginning with source: are sourced in the current shell; any other
non-empty line is passed to cd / Set-Location.
Windows
- PowerShell: fully supported —
tfe --init powershellor auto-detected. - Nushell: fully supported on Windows —
tfe --init nushell. - CMD: not supported (CMD has no shell functions). Use WSL and run
tfe --init bashortfe --init zshinside WSL.
# Open the selected file in $EDITOR (bypasses the wrapper)
|
# Select a Rust source file and edit it
|
# Start with the Catppuccin Mocha theme and the theme panel open
# Start in single-pane mode (useful for narrow terminals)
# List all available themes
# NUL-delimited output (safe for filenames with spaces or newlines)
|
Theme names are case-insensitive and hyphens/spaces are interchangeable:
catppuccin-mocha,Catppuccin Mocha, andcatppuccin mochaall resolve to the same preset.
Public API
The public surface is intentionally narrow for stability:
Single-pane
| Item | Kind | Description |
|---|---|---|
FileExplorer |
struct |
Core state machine — cursor, entries, search, sort state |
FileExplorerBuilder |
struct |
Fluent builder for FileExplorer |
ExplorerOutcome |
enum |
Result of handle_key — Selected, Dismissed, Pending, Unhandled |
FsEntry |
struct |
A single directory entry (name, path, size, extension, is_dir) |
SortMode |
enum |
Name | SizeDesc | Extension |
Theme |
struct |
Colour palette with builder methods and 27 named presets |
render |
fn |
Render one pane using the default theme |
render_themed |
fn |
Render one pane with a custom Theme |
entry_icon |
fn |
Map an FsEntry to its Unicode icon |
fmt_size |
fn |
Format a byte count as a human-readable string (1.5 KB) |
Dual-pane
| Item | Kind | Description |
|---|---|---|
DualPane |
struct |
Owns left + right: FileExplorer; routes keys; manages focus and single-pane mode |
DualPaneBuilder |
struct |
Fluent builder for DualPane — independent dirs, shared filter/sort/hidden |
DualPaneActive |
enum |
Left | Right — which pane has focus; .other() flips it |
DualPaneOutcome |
enum |
Result of DualPane::handle_key — Selected, Dismissed, Pending, Unhandled |
render_dual_pane |
fn |
Render both panes using the default theme |
render_dual_pane_themed |
fn |
Render both panes with a custom Theme |
Module Layout
Library (src/lib.rs re-exports)
| Module | Contents |
|---|---|
types |
FsEntry, ExplorerOutcome, SortMode — data types only, no I/O |
palette |
Palette constants + Theme builder + 27 named presets |
explorer |
FileExplorer, FileExplorerBuilder, entry_icon, fmt_size |
dual_pane |
DualPane, DualPaneBuilder, DualPaneActive, DualPaneOutcome |
render |
render, render_themed, render_dual_pane, render_dual_pane_themed — pure rendering, no state |
Because rendering is fully decoupled from state, you can slot either widget into any Ratatui layout, render it conditionally as an overlay, or build a completely custom renderer by reading FileExplorer's public fields directly.
Binary (tfe CLI, not part of the public library API)
| Module | Contents |
|---|---|
main |
Cli struct (argument parsing), run(), run_loop() — thin entry-point only |
app |
App state, Pane, ClipOp, ClipboardItem, Modal, handle_event |
ui |
draw(), render_theme_panel(), render_options_panel(), render_nav_hints(), render_nav_hints_spans(), render_action_bar(), render_action_bar_spans(), render_modal(), render_snackbar() |
fs |
copy_dir_all(), resolve_output_path() |
persistence |
AppState, load_state(), save_state(), resolve_theme_idx() |
shell_init |
Shell, detect_shell(), snippet(), rc_path_with(), is_installed(), install(), install_or_print() |
Generating Demo GIFs
Install VHS then run:
# Generate all GIFs at once (requires just)
# Or individually
GIFs are written to examples/vhs/generated/ and tracked with Git LFS.
| Tape | Demo | Command |
|---|---|---|
basic.tape |
Navigation, search, sort, hidden-file toggle, selection | cargo run --example basic |
search.tape |
Full incremental search lifecycle | cargo run --example basic |
sort.tape |
Name → Size ↓ → Extension cycling | cargo run --example basic |
filter.tape |
Extension filter — selectable vs dimmed files | cargo run --example basic -- rs toml |
file_ops.tape |
Copy, cut, paste, delete, overwrite modal | cargo run --bin tfe |
theme_switcher.tape |
Live cycling of all 27 themes with sidebar | cargo run --example theme_switcher |
pane_toggle.tape |
Tab focus-switch, w single/dual, T theme panel |
cargo run --bin tfe |
dual_pane.tape |
DualPane library widget — Tab, w, status bar |
cargo run --example dual_pane |
options.tape |
Options panel, editor picker, toggles, error snackbar | cargo run --bin tfe |
Development
Prerequisites
- Rust 1.75.0 or later (MSRV)
just— task runnergit-cliff— changelog generatorvhs— GIF recorder (optional, for demos)
Common tasks
License
MIT — see LICENSE for details.
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
Acknowledgments
Built for the Ratatui ecosystem.
Special thanks to the Ratatui team for an outstanding TUI framework.