Expand description
§tui-file-explorer
A self-contained, keyboard-driven file-browser widget for Ratatui.
§Design goals
- Zero application-specific dependencies — only
ratatui,crossterm, and the standard library are required. - Narrow public surface — the public API is intentionally small so the crate can evolve without breaking changes.
- Extension filtering — pass a list of allowed extensions so that only
relevant files are selectable (e.g.
["iso", "img"]); directories are always navigable. - Keyboard-driven —
↑/↓/←/→scroll the list,Enter/lto descend or confirm,Backspace/hto ascend,/to search,sto cycle sort,nto create a new folder,Nto create a new file,Esc/qto dismiss. - Searchable — press
/to enter incremental search; entries are filtered live as you type.Escclears the query; a secondEscdismisses the explorer. - Sortable — press
sto cycle throughName,Size ↓, andExtensionsort modes, or set one programmatically viaFileExplorer::set_sort_mode. - Themeable — every colour is overridable via
Themeandrender_themed. - Dual-pane —
DualPaneowns two independentFileExplorers, manages focus switching (Tab), and supports a single-pane toggle (w).
§Quick start
use tui_file_explorer::{FileExplorer, ExplorerOutcome, SortMode, render};
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
// 1. Create once (e.g. in your App::new).
let mut explorer = FileExplorer::builder(std::env::current_dir().unwrap())
.allow_extension("iso")
.allow_extension("img")
.sort_mode(SortMode::SizeDesc)
.build();
// 2. In your Terminal::draw closure:
// render(&mut explorer, frame, frame.area());
// 3. In your key-handler:
match explorer.handle_key(key) {
ExplorerOutcome::Selected(path) => println!("chosen: {}", path.display()),
ExplorerOutcome::Dismissed => { /* close the overlay */ }
_ => {}
}§Builder / configuration
Use FileExplorer::builder for a more ergonomic construction API:
use tui_file_explorer::{FileExplorer, SortMode};
let explorer = FileExplorer::builder(std::env::current_dir().unwrap())
.allow_extension("rs")
.allow_extension("toml")
.show_hidden(true)
.sort_mode(SortMode::Extension)
.build();§Incremental search
Press / to activate search mode. Subsequent keystrokes append to the
query and the entry list is filtered live (case-insensitive substring
match on the file name). Backspace removes the last character; an
extra Backspace on an empty query deactivates search. Esc clears
the query and deactivates search without dismissing the explorer; a
second Esc (when search is already inactive) dismisses it.
Search state is also accessible programmatically:
use tui_file_explorer::FileExplorer;
let explorer = FileExplorer::new(std::env::current_dir().unwrap(), vec![]);
println!("searching: {}", explorer.is_searching());
println!("query : {}", explorer.search_query());§Sort modes
Press s to cycle through the three sort modes, or set one directly:
use tui_file_explorer::{FileExplorer, SortMode};
let mut explorer = FileExplorer::new(std::env::current_dir().unwrap(), vec![]);
explorer.set_sort_mode(SortMode::SizeDesc); // largest files first
println!("{}", explorer.sort_mode().label()); // "size ↓"§Theming
Every colour is customisable via Theme and render_themed:
use tui_file_explorer::{FileExplorer, Theme, render_themed};
use ratatui::style::Color;
let theme = Theme::default()
.brand(Color::Magenta)
.accent(Color::Cyan)
.dir(Color::LightYellow);
// terminal.draw(|frame| {
// render_themed(&mut explorer, frame, frame.area(), &theme);
// });§Named presets
Twenty well-known editor / terminal colour schemes are available as
associated constructors on Theme, mirroring the catalogue found in
Iced:
use tui_file_explorer::Theme;
let t = Theme::dracula();
let t = Theme::nord();
let t = Theme::catppuccin_mocha();
let t = Theme::tokyo_night();
let t = Theme::gruvbox_dark();
let t = Theme::kanagawa_wave();
let t = Theme::oxocarbon();
// Iterate the full catalogue (name, description, theme):
for (name, desc, _theme) in Theme::all_presets() {
println!("{name} — {desc}");
}The complete 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.
§Key bindings reference
| Key | Action |
|---|---|
↑ / k | Move cursor up |
↓ / j | Move cursor down |
PgUp / PgDn | Jump 10 entries |
Home / g | Jump to top |
End / G | Jump to bottom |
→ / l / Enter | Descend into directory; on a file → moves cursor down, l/Enter confirm |
← / h / Backspace | Ascend to parent directory |
Space | Toggle space-mark on current entry and advance cursor |
/ | Activate incremental search |
s | Cycle sort mode (Name → Size ↓ → Extension) |
. | Toggle hidden (dot-file) entries |
n | Create a new folder (type name → Enter confirm, Esc cancel) |
N | Create a new file (type name → Enter confirm, Esc cancel) |
r | Rename current entry (pre-filled with current name → Enter confirm, Esc cancel) |
Esc | Clear search / cancel mkdir / cancel touch / cancel rename (if active), then dismiss |
q | Dismiss (when search / mkdir / touch / rename is not active) |
§Dual-pane quick start
use tui_file_explorer::{DualPane, DualPaneOutcome, render_dual_pane_themed, Theme};
use crossterm::event::{Event, KeyCode, KeyModifiers, self};
// 1. Create once — left pane defaults to cwd; right pane mirrors it.
let mut dual = DualPane::builder(std::env::current_dir().unwrap())
.right_dir(std::path::PathBuf::from("/tmp"))
.build();
let theme = Theme::default();
// 2. In your Terminal::draw closure:
// terminal.draw(|frame| {
// render_dual_pane_themed(&mut dual, frame, frame.area(), &theme);
// }).unwrap();
// 3. In your event loop:
match dual.handle_key(key) {
DualPaneOutcome::Selected(path) => println!("chosen: {}", path.display()),
DualPaneOutcome::Dismissed => { /* close the overlay */ }
_ => {}
}§Extra key bindings provided by DualPane
| Key | Action |
|---|---|
Tab | Switch focus between left and right pane |
w | Toggle single-pane / dual-pane mode |
Space | Mark current entry (forwarded to active pane) |
All standard FileExplorer bindings continue to work on whichever pane
is currently active.
§Folder and file creation
§New folder — n
Press n to enter mkdir mode. Type the new folder name, then press
Enter to create it (using fs::create_dir_all, so nested paths like
a/b/c work) or Esc to cancel without creating anything. On success
ExplorerOutcome::MkdirCreated is returned and the cursor moves to the
new directory.
§New file — N
Press N (Shift+N) to enter touch mode. Type the new file name (including
extension), then press Enter to create it or Esc to cancel. Parent
directories are created automatically when the name contains /. An
existing file at the target path is left untouched (no truncation). On
success ExplorerOutcome::TouchCreated is returned and the cursor moves
to the new file.
Both modes are also accessible programmatically:
use tui_file_explorer::FileExplorer;
let explorer = FileExplorer::new(std::env::current_dir().unwrap(), vec![]);
println!("mkdir active : {}", explorer.is_mkdir_active());
println!("mkdir input : {}", explorer.mkdir_input());
println!("touch active : {}", explorer.is_touch_active());
println!("touch input : {}", explorer.touch_input());§Module layout
| Module | Contents |
|---|---|
types | FsEntry, ExplorerOutcome, SortMode |
palette | Palette constants (all pub) + Theme builder + 27 named presets |
explorer | FileExplorer, FileExplorerBuilder, entry_icon, fmt_size, load_entries |
dual_pane | DualPane, DualPaneBuilder, DualPaneActive, DualPaneOutcome |
render | [render], render_themed, render_dual_pane, render_dual_pane_themed — pure rendering, no I/O |
Re-exports§
pub use dual_pane::DualPane;pub use dual_pane::DualPaneActive;pub use dual_pane::DualPaneBuilder;pub use dual_pane::DualPaneOutcome;pub use explorer::entry_icon;pub use explorer::fmt_size;pub use explorer::FileExplorer;pub use explorer::FileExplorerBuilder;pub use palette::Theme;pub use render::render;pub use render::render_dual_pane;pub use render::render_dual_pane_themed;pub use render::render_themed;pub use types::ExplorerOutcome;pub use types::FsEntry;pub use types::SortMode;pub use app::App;pub use app::AppOptions;pub use app::ClipOp;pub use app::ClipboardItem;pub use app::CopyProgress;pub use app::Editor;pub use app::Modal;pub use app::Pane;pub use app::Snackbar;pub use fs::copy_dir_all;pub use fs::resolve_output_path;pub use persistence::load_state;pub use persistence::resolve_theme_idx;pub use persistence::save_state;pub use persistence::AppState;pub use ui::draw;pub use ui::render_action_bar;pub use ui::render_copy_progress;pub use ui::render_editor_panel;pub use ui::render_modal;pub use ui::render_options_panel;pub use ui::render_snackbar;pub use ui::render_theme_panel;
Modules§
- app
- Application state for the
tfebinary. - dual_
pane - Dual-pane file-explorer widget.
- explorer
FileExplorerstate machine,FileExplorerBuilder, and filesystem helpers.- fs
- Filesystem helpers for the
tfebinary. - palette
- Default colour palette used by the file-explorer widget.
- persistence
- Persist application state between sessions.
- render
- Ratatui rendering functions for the file-explorer widget.
- types
- Public data types exposed by the
tui-file-explorercrate. - ui
- Terminal UI drawing functions for the
tfebinary.