Skip to main content

FileExplorer

Struct FileExplorer 

Source
pub struct FileExplorer { /* private fields */ }
Expand description

A file explorer that allows browsing and selecting files and directories.

The FileExplorer struct represents a file explorer widget that can be used to navigate through the file system. You can obtain a renderable widget from it with the widget method. It provides methods for handling user input from crossterm, termion and termwiz or your own backend (depending on what feature is enabled).

§Examples

Creating a new FileExplorer widget:

let file_explorer = FileExplorer::new().unwrap();
let widget = file_explorer.widget();

Handling user input:

let mut file_explorer = FileExplorer::new().unwrap();
let event = get_event(); // Get the event from the terminal (with crossterm, termion or termwiz)
file_explorer.handle(event).unwrap();

Accessing information about the current file selected and/or the current working directory:

let file_explorer = FileExplorer::new().unwrap();

let current_file = file_explorer.current();
let current_working_directory = file_explorer.cwd();
println!("Current Directory: {}", current_working_directory.display());
println!("Name: {}", current_file.name);

Implementations§

Source§

impl FileExplorer

Source

pub fn new() -> Result<FileExplorer>

Creates a new instance of FileExplorer.

This method initializes a FileExplorer with the current working directory. By default, hidden files are not shown.

You can use the FileExplorerBuilder to create a FileExplorer with a custom working directory, theme, and other options. See its documentation for more information.

§Errors

Will return Err if the current working directory can not be listed. See current_dir for more information.

§Examples

Suppose you have this tree file and your current working directory is /Documents:

/
├── .git
└── Documents  <- current working directory
    ├── passport.png
    └── resume.pdf

You can create a new FileExplorer like this:

let file_explorer = FileExplorer::new().unwrap();
assert_eq!(file_explorer.cwd().display().to_string(), "/Documents");
Source

pub const fn widget(&self) -> impl WidgetRef + '_

Build a ratatui widget to render the file explorer. The widget can then be rendered with Frame::render_widget or FrameExt::render_widget_ref.

§Examples
use ratatui::{Terminal, backend::CrosstermBackend, widgets::FrameExt as _};
use ratatui_explorer::FileExplorer;

let mut file_explorer = FileExplorer::new().unwrap();

let mut terminal = Terminal::new(CrosstermBackend::new(std::io::stdout())).unwrap();

loop {
    terminal.draw(|f| {
        let widget = file_explorer.widget(); // Get the widget to render the file explorer
        f.render_widget_ref(widget, f.area());
    }).unwrap();

    // ...
}
Source

pub fn handle<I: Into<Input>>(&mut self, input: I) -> Result<()>

Handles input from user and updates the state of the file explorer. The different inputs are interpreted as follows:

  • Up: Move the selection up.
  • Down: Move the selection down.
  • Left: Move to the parent directory.
  • Right: Move to the selected directory.
  • Home: Select the first entry.
  • End: Select the last entry.
  • PageUp: Scroll the selection up.
  • PageDown: Scroll the selection down.
  • ToggleShowHidden: Toggle between showing hidden files or not.
  • None: Do nothing.

Input implement From<Event> for Event from crossterm, termion and termwiz (InputEvent in the latter). Here, the default bindings.

§Errors

Will return Err if the new current working directory can not be listed.

§Examples

Suppose you have this tree file, with passport.png selected inside file_explorer:

/
├── .git
└── Documents
    ├── passport.png  <- selected
    └── resume.pdf

You can handle input like this:

let mut file_explorer = FileExplorer::new().unwrap();
file_explorer.set_show_hidden(true);

/* user select `password.png` */

file_explorer.handle(Input::Down).unwrap();
assert_eq!(file_explorer.current().name, "resume.pdf");

file_explorer.handle(Input::Up).unwrap();
file_explorer.handle(Input::Up).unwrap();
assert_eq!(file_explorer.current().name, "../");

file_explorer.handle(Input::Left).unwrap();
assert_eq!(file_explorer.cwd().display().to_string(), "/");

file_explorer.handle(Input::Right).unwrap();
assert_eq!(file_explorer.cwd().display().to_string(), "/.git");
Source

pub fn set_cwd<P: Into<PathBuf>>(&mut self, cwd: P) -> Result<()>

Sets the current working directory of the file explorer.

§Errors

Will return Err if the directory cwd can not be listed.

§Examples
let mut file_explorer = FileExplorer::new().unwrap();

file_explorer.set_cwd("/Documents").unwrap();
assert_eq!(file_explorer.cwd().display().to_string(), "/Documents");
Source

pub fn set_working_file<P: Into<PathBuf>>( &mut self, working_file: P, ) -> Result<()>

Same as set_cwd but will pre-select the file in the working directory.

This method set the working directory to the parent directory of the provided file and select the file in the file explorer. You can also select a directory (eg. select /Documents inside /).

§Examples

Suppose you have this tree file:

/
├── .git
└── Documents
    ├── passport.png
    └── resume.pdf

You can create a new FileExplorer selecting passport.png like this:

let mut file_explorer = FileExplorer::new().unwrap();
file_explorer.set_working_file("/Documents/passport.png").unwrap();

assert_eq!(file_explorer.cwd().display().to_string(), "/Documents");
assert_eq!(file_explorer.current().path.display().to_string(), "/Documents/passport.png");
Source

pub fn set_show_hidden(&mut self, show_hidden: bool) -> Result<()>

Sets whether hidden files should be shown in the file explorer.

§Errors

Will return Err if the current working directory can not be listed.

§Examples

Suppose you have this tree file:

/
├── .git
└── Documents
    ├── passport.png
    └── resume.pdf
let mut file_explorer = FileExplorerBuilder::build_with_working_dir("/").unwrap();
assert_eq!(file_explorer.files().len(), 1); // Only /Documents is shown

file_explorer.set_show_hidden(true).unwrap();
assert_eq!(file_explorer.files().len(), 2); // /Documents and /.git are shown
Source

pub fn set_filter_map( &mut self, f: impl Fn(File) -> Option<File> + Send + Sync + 'static, ) -> Result<()>

Filters and maps the files in the FileExplorer.

If not set, all files are shown. Hidden files are filtered before this filter will be apply.

To remove the filter, use remove_filter_map.

§Errors

Will return Err if the current working directory can not be listed.

§Examples:
const SUPPORTED_FORMATS: [&str; 2] = ["wav", "mp3"];

// A file explorer for browsing my favorite musics
let mut music_file_explorer = FileExplorer::new().unwrap();
music_file_explorer.set_filter_map(|file| {
    let keep = match file.path.extension() {
        Some(extension) => {
            let extension = extension.to_str().unwrap_or_default();
            SUPPORTED_FORMATS.contains(&extension)
        }
        None => file.is_dir,
    };

    if keep { Some(file) } else { None }
}).unwrap();

// My old terminal only display ASCII :(
let mut ascii_file_explorer = FileExplorer::new().unwrap();
ascii_file_explorer.set_filter_map(|mut file| {
    file.name = file.name.chars()
        .map(|c| if c.is_ascii() { c } else { '_' })
        .collect();

    Some(file)
}).unwrap();
Source

pub fn remove_filter_map( &mut self, ) -> Result<Option<Arc<dyn Fn(File) -> Option<File> + Send + Sync + 'static>>>

Removes the current filter and returns it if it exists.

§Errors

Will return Err if the current working directory can not be listed.

§Examples
let mut file_explorer = FileExplorer::new().unwrap();
file_explorer.set_filter_map(|file| if file.is_dir { Some(file) } else { None }).unwrap();

 /* Only directories are shown */

let filter = file_explorer.remove_filter_map().unwrap();

/* All files and directories are shown again */
Source

pub fn set_theme(&mut self, theme: Theme)

Sets the theme of the file explorer.

§Examples
let mut file_explorer = FileExplorer::new().unwrap();

file_explorer.set_theme(Theme::default().add_default_title());
Source

pub fn set_selected_idx(&mut self, selected: usize)

Sets the selected file or directory index inside the current Vec of files and directories in the file explorer.

The file explorer add the parent directory at the beginning of the Vec of files, so setting the selected index to 0 will select the parent directory (if the current working directory not the root directory).

§Panics

Panics if selected is greater or equal to the number of files (plus the parent directory if it exist) in the current working directory.

§Examples

Suppose you have this tree file, with passport.png selected inside file_explorer:

/
├── .git
└── Documents
    ├── passport.png  <- selected (index 1)
    └── resume.pdf

You can set the selected index like this:

let mut file_explorer = FileExplorer::new().unwrap();

/* user select `password.png` */

// Because the file explorer add the parent directory at the beginning
// of the `Vec` of files, index 0 is indeed the parent directory.
file_explorer.set_selected_idx(0);
assert_eq!(file_explorer.current().path.display().to_string(), "/");

file_explorer.set_selected_idx(1);
assert_eq!(file_explorer.current().path.display().to_string(), "/Documents/passport.png");

#[test]
#[should_panic]
fn index_out_of_bound() {
   let mut file_explorer = FileExplorer::new().unwrap();
   file_explorer.set_selected_idx(3);
}
Source

pub fn current(&self) -> &File

Returns the current file or directory selected.

§Examples

Suppose you have this tree file, with passport.png selected inside file_explorer:

/
├── .git
└── Documents
    ├── passport.png  <- selected
    └── resume.pdf

You can get the current file like this:

let file_explorer = FileExplorer::new().unwrap();

/* user select `password.png` */

let file = file_explorer.current();
assert_eq!(file.name, "passport.png");
Source

pub const fn cwd(&self) -> &PathBuf

Returns the current working directory of the file explorer.

§Examples

Suppose you have this tree file, with passport.png selected inside file_explorer:

/
├── .git
└── Documents
    ├── passport.png  <- selected
    └── resume.pdf

You can get the current working directory like this:

let file_explorer = FileExplorer::new().unwrap();

/* user select `password.png` */

let cwd = file_explorer.cwd();
assert_eq!(cwd.display().to_string(), "/Documents");
Source

pub const fn show_hidden(&self) -> bool

Indicates whether hidden files are currently visible in the file explorer.

§Examples

You can get the current value like this:

let mut file_explorer = FileExplorer::new().unwrap();

// By default, hidden files are not shown.
assert_eq!(file_explorer.show_hidden(), false);

file_explorer.set_show_hidden(true);
assert_eq!(file_explorer.show_hidden(), true);
Source

pub const fn files(&self) -> &Vec<File>

Returns the a Vec of files and directories in the current working directory of the file explorer, plus the parent directory if it exist.

§Examples

Suppose you have this tree file, with passport.png selected inside file_explorer:

/
├── .git
└── Documents
    ├── passport.png  <- selected
    └── resume.pdf

You can get the Vec of files and directories like this:

let file_explorer = FileExplorer::new().unwrap();

/* user select `password.png` */

let files = file_explorer.files();
assert_eq!(files.len(), 3); // 2 files and 1 parent directory
Source

pub const fn selected_idx(&self) -> usize

Returns the index of the selected file or directory in the current Vec of files and directories in the current working directory of the file explorer.

§Examples

Suppose you have this tree file, with passport.png selected inside file_explorer:

/
├── .git
└── Documents
    ├── passport.png  <- selected (index 1)
    └── resume.pdf

You can get the selected index like this:

let file_explorer = FileExplorer::new().unwrap();

/* user select `password.png` */

let selected_idx = file_explorer.selected_idx();

// Because the file explorer add the parent directory at the beginning
// of the `Vec` of files, the selected index will be 1.
assert_eq!(selected_idx, 1);
Source

pub const fn theme(&self) -> &Theme

Returns the theme of the file explorer.

§Examples
let file_explorer = FileExplorer::new().unwrap();

assert_eq!(file_explorer.theme(), &Theme::new());
Source

pub fn with_theme(theme: Theme) -> Result<FileExplorer>

👎Deprecated since 0.3.0:

Use FileExplorerBuilder::build_with_theme instead

Trait Implementations§

Source§

impl Clone for FileExplorer

Source§

fn clone(&self) -> FileExplorer

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for FileExplorer

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for FileExplorer

Source§

impl Hash for FileExplorer

Source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for FileExplorer

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.