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 (depending on what feature is enabled).
§Examples
Creating a new FileExplorer widget:
use fpicker::FileExplorer;
let file_explorer = FileExplorer::new().unwrap();
let widget = file_explorer.widget();Handling user input:
use fpicker::FileExplorer;
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:
use fpicker::FileExplorer;
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
impl FileExplorer
Sourcepub fn new() -> Result<FileExplorer>
pub fn new() -> Result<FileExplorer>
Creates a new instance of FileExplorer.
This method initializes a FileExplorer with the current working directory.
§Examples
Suppose you have this tree file and your current working directory is /Documents:
/
├── .git
└── Documents <- current working directory
├── passport.png
└── resume.pdfYou can create a new FileExplorer like this:
use fpicker::FileExplorer;
let file_explorer = FileExplorer::new().unwrap();
assert_eq!(file_explorer.cwd().display().to_string(), "/Documents");Sourcepub fn with_theme(theme: Theme) -> Result<FileExplorer>
pub fn with_theme(theme: Theme) -> Result<FileExplorer>
Creates a new instance of FileExplorer with a specific theme.
This method initializes a FileExplorer with the current working directory.
§Examples
use fpicker::{FileExplorer, Theme};
let file_explorer = FileExplorer::with_theme(Theme::default().add_default_title()).unwrap();Examples found in repository?
11fn main() -> io::Result<()> {
12 enable_raw_mode()?;
13 stdout().execute(EnterAlternateScreen)?;
14
15 let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
16
17 // Create a new file explorer with the default theme and title.
18 let theme = Theme::default().add_default_title();
19 let mut file_explorer = FileExplorer::with_theme(theme)?;
20
21 let mut selected_paths = vec![];
22
23 loop {
24 // Render the file explorer widget.
25 terminal.draw(|f| {
26 f.render_widget(&file_explorer.widget(), f.area());
27 })?;
28
29 // Read the next event from the terminal.
30 let event = read()?;
31 if let Event::Key(key) = event {
32 if key.code == KeyCode::Char('q') {
33 // Collect selected file paths.
34 selected_paths = file_explorer
35 .selected_files()
36 .iter()
37 .map(|file| file.path().display().to_string())
38 .collect();
39 break;
40 }
41 }
42 // Handle the event in the file explorer.
43 file_explorer.handle(&event)?;
44 }
45
46 // Restore the terminal to normal mode.
47 disable_raw_mode()?;
48 stdout().execute(LeaveAlternateScreen)?;
49
50 // Print the selected file paths to stdout.
51 for path in selected_paths {
52 println!("{}", path);
53 }
54
55 // Return exit code 0 explicitly.
56 process::exit(0);
57}More examples
15fn main() -> io::Result<()> {
16 enable_raw_mode()?;
17 stdout().execute(EnterAlternateScreen)?;
18
19 let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
20
21 // Create a new file explorer with the light theme.
22 let mut dark_theme = false;
23 let mut file_explorer = FileExplorer::with_theme(get_light_theme())?;
24
25 loop {
26 // Render the file explorer widget.
27 terminal.draw(|f| {
28 f.render_widget(&file_explorer.widget(), f.area());
29 })?;
30
31 // Read the next event from the terminal.
32 let event = read()?;
33 // If the user presses `Ctrl + s`, switch the theme.
34 // If the user presses `Ctrl + q`, quit the application.
35 if let Event::Key(key) = event {
36 if key.modifiers == crossterm::event::KeyModifiers::CONTROL {
37 match key.code {
38 KeyCode::Char('s') => {
39 dark_theme = !dark_theme;
40 if dark_theme {
41 file_explorer.set_theme(get_dark_theme());
42 } else {
43 file_explorer.set_theme(get_light_theme());
44 }
45 }
46 KeyCode::Char('q') => {
47 break;
48 }
49 _ => {}
50 }
51 }
52 }
53 // Handle the event in the file explorer.
54 file_explorer.handle(&event)?;
55 }
56
57 disable_raw_mode()?;
58 stdout().execute(LeaveAlternateScreen)?;
59 Ok(())
60}17fn main() -> io::Result<()> {
18 enable_raw_mode()?;
19 stdout().execute(EnterAlternateScreen)?;
20
21 let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
22 let layout = Layout::vertical([
23 Constraint::Ratio(4, 5), // Main file explorer and content area
24 Constraint::Ratio(1, 5), // Bottom window for selected file paths
25 ]);
26
27 // Inner layout for the top section
28 let top_layout = Layout::horizontal([Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)]);
29
30 // Create a new file explorer with the default theme and title.
31 let theme = get_theme();
32 let mut file_explorer = FileExplorer::with_theme(theme)?;
33
34 loop {
35 // Get the content of the current selected file (if it's indeed a file).
36 let file_content = get_file_content(file_explorer.current().path())?;
37 let selected_files: String = file_explorer
38 .selected_files()
39 .iter()
40 .map(|file| file.path().display().to_string())
41 .collect::<Vec<String>>()
42 .join("\n");
43
44 // Render the file explorer widget, file content, and selected file paths.
45 terminal.draw(|f| {
46 let chunks = layout.split(f.area());
47 let top_chunks = top_layout.split(chunks[0]);
48
49 // Top section
50 f.render_widget(&file_explorer.widget(), top_chunks[0]);
51 f.render_widget(
52 Paragraph::new(file_content).block(
53 Block::default()
54 .borders(Borders::ALL)
55 .border_type(BorderType::Double),
56 ),
57 top_chunks[1],
58 );
59
60 // Bottom section
61 f.render_widget(
62 Paragraph::new(selected_files.clone()).block(
63 Block::default()
64 .borders(Borders::ALL)
65 .title("q:Quit, c: copy selected file contents to clipboard, p: copy paths to clipboard"),
66 ),
67 chunks[1],
68 );
69 })?;
70
71 // Read the next event from the terminal.
72 let event = read()?;
73 if let Event::Key(key) = event {
74 match key.code {
75 KeyCode::Char('q') => break, // Quit the application
76 KeyCode::Char('c') => {
77 // Copy selected file paths to clipboard
78 if let Ok(mut clipboard) = ClipboardContext::new() {
79 if let Err(err) = clipboard.set_contents(get_selected_files_content(
80 &file_explorer.selected_files(),
81 )) {
82 eprintln!("Failed to copy to clipboard: {}", err);
83 }
84 } else {
85 eprintln!("Clipboard not available.");
86 }
87 }
88 KeyCode::Char('p') => {
89 // Copy selected file paths to clipboard
90 if let Ok(mut clipboard) = ClipboardContext::new() {
91 if let Err(err) = clipboard.set_contents(selected_files.clone()) {
92 eprintln!("Failed to copy to clipboard: {}", err);
93 }
94 } else {
95 eprintln!("Clipboard not available.");
96 }
97 }
98 _ => {}
99 }
100 }
101 // Handle the event in the file explorer.
102 file_explorer.handle(&event)?;
103 }
104
105 disable_raw_mode()?;
106 stdout().execute(LeaveAlternateScreen)?;
107 // Print the selected file paths to stdout.
108 for file in file_explorer.selected_files() {
109 println!("{}", file.path().display());
110 }
111 Ok(())
112}Sourcepub const fn widget(&self) -> impl WidgetRef + '_
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.
§Examples
use ratatui::{Terminal, backend::CrosstermBackend};
use fpicker::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(&widget, f.area());
}).unwrap();
// ...
}Examples found in repository?
11fn main() -> io::Result<()> {
12 enable_raw_mode()?;
13 stdout().execute(EnterAlternateScreen)?;
14
15 let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
16
17 // Create a new file explorer with the default theme and title.
18 let theme = Theme::default().add_default_title();
19 let mut file_explorer = FileExplorer::with_theme(theme)?;
20
21 let mut selected_paths = vec![];
22
23 loop {
24 // Render the file explorer widget.
25 terminal.draw(|f| {
26 f.render_widget(&file_explorer.widget(), f.area());
27 })?;
28
29 // Read the next event from the terminal.
30 let event = read()?;
31 if let Event::Key(key) = event {
32 if key.code == KeyCode::Char('q') {
33 // Collect selected file paths.
34 selected_paths = file_explorer
35 .selected_files()
36 .iter()
37 .map(|file| file.path().display().to_string())
38 .collect();
39 break;
40 }
41 }
42 // Handle the event in the file explorer.
43 file_explorer.handle(&event)?;
44 }
45
46 // Restore the terminal to normal mode.
47 disable_raw_mode()?;
48 stdout().execute(LeaveAlternateScreen)?;
49
50 // Print the selected file paths to stdout.
51 for path in selected_paths {
52 println!("{}", path);
53 }
54
55 // Return exit code 0 explicitly.
56 process::exit(0);
57}More examples
15fn main() -> io::Result<()> {
16 enable_raw_mode()?;
17 stdout().execute(EnterAlternateScreen)?;
18
19 let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
20
21 // Create a new file explorer with the light theme.
22 let mut dark_theme = false;
23 let mut file_explorer = FileExplorer::with_theme(get_light_theme())?;
24
25 loop {
26 // Render the file explorer widget.
27 terminal.draw(|f| {
28 f.render_widget(&file_explorer.widget(), f.area());
29 })?;
30
31 // Read the next event from the terminal.
32 let event = read()?;
33 // If the user presses `Ctrl + s`, switch the theme.
34 // If the user presses `Ctrl + q`, quit the application.
35 if let Event::Key(key) = event {
36 if key.modifiers == crossterm::event::KeyModifiers::CONTROL {
37 match key.code {
38 KeyCode::Char('s') => {
39 dark_theme = !dark_theme;
40 if dark_theme {
41 file_explorer.set_theme(get_dark_theme());
42 } else {
43 file_explorer.set_theme(get_light_theme());
44 }
45 }
46 KeyCode::Char('q') => {
47 break;
48 }
49 _ => {}
50 }
51 }
52 }
53 // Handle the event in the file explorer.
54 file_explorer.handle(&event)?;
55 }
56
57 disable_raw_mode()?;
58 stdout().execute(LeaveAlternateScreen)?;
59 Ok(())
60}17fn main() -> io::Result<()> {
18 enable_raw_mode()?;
19 stdout().execute(EnterAlternateScreen)?;
20
21 let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
22 let layout = Layout::vertical([
23 Constraint::Ratio(4, 5), // Main file explorer and content area
24 Constraint::Ratio(1, 5), // Bottom window for selected file paths
25 ]);
26
27 // Inner layout for the top section
28 let top_layout = Layout::horizontal([Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)]);
29
30 // Create a new file explorer with the default theme and title.
31 let theme = get_theme();
32 let mut file_explorer = FileExplorer::with_theme(theme)?;
33
34 loop {
35 // Get the content of the current selected file (if it's indeed a file).
36 let file_content = get_file_content(file_explorer.current().path())?;
37 let selected_files: String = file_explorer
38 .selected_files()
39 .iter()
40 .map(|file| file.path().display().to_string())
41 .collect::<Vec<String>>()
42 .join("\n");
43
44 // Render the file explorer widget, file content, and selected file paths.
45 terminal.draw(|f| {
46 let chunks = layout.split(f.area());
47 let top_chunks = top_layout.split(chunks[0]);
48
49 // Top section
50 f.render_widget(&file_explorer.widget(), top_chunks[0]);
51 f.render_widget(
52 Paragraph::new(file_content).block(
53 Block::default()
54 .borders(Borders::ALL)
55 .border_type(BorderType::Double),
56 ),
57 top_chunks[1],
58 );
59
60 // Bottom section
61 f.render_widget(
62 Paragraph::new(selected_files.clone()).block(
63 Block::default()
64 .borders(Borders::ALL)
65 .title("q:Quit, c: copy selected file contents to clipboard, p: copy paths to clipboard"),
66 ),
67 chunks[1],
68 );
69 })?;
70
71 // Read the next event from the terminal.
72 let event = read()?;
73 if let Event::Key(key) = event {
74 match key.code {
75 KeyCode::Char('q') => break, // Quit the application
76 KeyCode::Char('c') => {
77 // Copy selected file paths to clipboard
78 if let Ok(mut clipboard) = ClipboardContext::new() {
79 if let Err(err) = clipboard.set_contents(get_selected_files_content(
80 &file_explorer.selected_files(),
81 )) {
82 eprintln!("Failed to copy to clipboard: {}", err);
83 }
84 } else {
85 eprintln!("Clipboard not available.");
86 }
87 }
88 KeyCode::Char('p') => {
89 // Copy selected file paths to clipboard
90 if let Ok(mut clipboard) = ClipboardContext::new() {
91 if let Err(err) = clipboard.set_contents(selected_files.clone()) {
92 eprintln!("Failed to copy to clipboard: {}", err);
93 }
94 } else {
95 eprintln!("Clipboard not available.");
96 }
97 }
98 _ => {}
99 }
100 }
101 // Handle the event in the file explorer.
102 file_explorer.handle(&event)?;
103 }
104
105 disable_raw_mode()?;
106 stdout().execute(LeaveAlternateScreen)?;
107 // Print the selected file paths to stdout.
108 for file in file_explorer.selected_files() {
109 println!("{}", file.path().display());
110 }
111 Ok(())
112}Sourcepub fn handle<I: Into<Input>>(&mut self, input: I) -> Result<()>
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.None: Do nothing.
Input implement From<Event>
for Event of crossterm,
termion
and termwiz (InputEvent in this case).
§Examples
Suppose you have this tree file, with passport.png selected inside file_explorer:
/
├── .git
└── Documents
├── passport.png <- selected
└── resume.pdfYou can handle input like this:
use fpicker::{FileExplorer, Input};
let mut file_explorer = FileExplorer::new().unwrap();
/* 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(), "Documents");
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(), "/Documents");Examples found in repository?
11fn main() -> io::Result<()> {
12 enable_raw_mode()?;
13 stdout().execute(EnterAlternateScreen)?;
14
15 let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
16
17 // Create a new file explorer with the default theme and title.
18 let theme = Theme::default().add_default_title();
19 let mut file_explorer = FileExplorer::with_theme(theme)?;
20
21 let mut selected_paths = vec![];
22
23 loop {
24 // Render the file explorer widget.
25 terminal.draw(|f| {
26 f.render_widget(&file_explorer.widget(), f.area());
27 })?;
28
29 // Read the next event from the terminal.
30 let event = read()?;
31 if let Event::Key(key) = event {
32 if key.code == KeyCode::Char('q') {
33 // Collect selected file paths.
34 selected_paths = file_explorer
35 .selected_files()
36 .iter()
37 .map(|file| file.path().display().to_string())
38 .collect();
39 break;
40 }
41 }
42 // Handle the event in the file explorer.
43 file_explorer.handle(&event)?;
44 }
45
46 // Restore the terminal to normal mode.
47 disable_raw_mode()?;
48 stdout().execute(LeaveAlternateScreen)?;
49
50 // Print the selected file paths to stdout.
51 for path in selected_paths {
52 println!("{}", path);
53 }
54
55 // Return exit code 0 explicitly.
56 process::exit(0);
57}More examples
15fn main() -> io::Result<()> {
16 enable_raw_mode()?;
17 stdout().execute(EnterAlternateScreen)?;
18
19 let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
20
21 // Create a new file explorer with the light theme.
22 let mut dark_theme = false;
23 let mut file_explorer = FileExplorer::with_theme(get_light_theme())?;
24
25 loop {
26 // Render the file explorer widget.
27 terminal.draw(|f| {
28 f.render_widget(&file_explorer.widget(), f.area());
29 })?;
30
31 // Read the next event from the terminal.
32 let event = read()?;
33 // If the user presses `Ctrl + s`, switch the theme.
34 // If the user presses `Ctrl + q`, quit the application.
35 if let Event::Key(key) = event {
36 if key.modifiers == crossterm::event::KeyModifiers::CONTROL {
37 match key.code {
38 KeyCode::Char('s') => {
39 dark_theme = !dark_theme;
40 if dark_theme {
41 file_explorer.set_theme(get_dark_theme());
42 } else {
43 file_explorer.set_theme(get_light_theme());
44 }
45 }
46 KeyCode::Char('q') => {
47 break;
48 }
49 _ => {}
50 }
51 }
52 }
53 // Handle the event in the file explorer.
54 file_explorer.handle(&event)?;
55 }
56
57 disable_raw_mode()?;
58 stdout().execute(LeaveAlternateScreen)?;
59 Ok(())
60}17fn main() -> io::Result<()> {
18 enable_raw_mode()?;
19 stdout().execute(EnterAlternateScreen)?;
20
21 let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
22 let layout = Layout::vertical([
23 Constraint::Ratio(4, 5), // Main file explorer and content area
24 Constraint::Ratio(1, 5), // Bottom window for selected file paths
25 ]);
26
27 // Inner layout for the top section
28 let top_layout = Layout::horizontal([Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)]);
29
30 // Create a new file explorer with the default theme and title.
31 let theme = get_theme();
32 let mut file_explorer = FileExplorer::with_theme(theme)?;
33
34 loop {
35 // Get the content of the current selected file (if it's indeed a file).
36 let file_content = get_file_content(file_explorer.current().path())?;
37 let selected_files: String = file_explorer
38 .selected_files()
39 .iter()
40 .map(|file| file.path().display().to_string())
41 .collect::<Vec<String>>()
42 .join("\n");
43
44 // Render the file explorer widget, file content, and selected file paths.
45 terminal.draw(|f| {
46 let chunks = layout.split(f.area());
47 let top_chunks = top_layout.split(chunks[0]);
48
49 // Top section
50 f.render_widget(&file_explorer.widget(), top_chunks[0]);
51 f.render_widget(
52 Paragraph::new(file_content).block(
53 Block::default()
54 .borders(Borders::ALL)
55 .border_type(BorderType::Double),
56 ),
57 top_chunks[1],
58 );
59
60 // Bottom section
61 f.render_widget(
62 Paragraph::new(selected_files.clone()).block(
63 Block::default()
64 .borders(Borders::ALL)
65 .title("q:Quit, c: copy selected file contents to clipboard, p: copy paths to clipboard"),
66 ),
67 chunks[1],
68 );
69 })?;
70
71 // Read the next event from the terminal.
72 let event = read()?;
73 if let Event::Key(key) = event {
74 match key.code {
75 KeyCode::Char('q') => break, // Quit the application
76 KeyCode::Char('c') => {
77 // Copy selected file paths to clipboard
78 if let Ok(mut clipboard) = ClipboardContext::new() {
79 if let Err(err) = clipboard.set_contents(get_selected_files_content(
80 &file_explorer.selected_files(),
81 )) {
82 eprintln!("Failed to copy to clipboard: {}", err);
83 }
84 } else {
85 eprintln!("Clipboard not available.");
86 }
87 }
88 KeyCode::Char('p') => {
89 // Copy selected file paths to clipboard
90 if let Ok(mut clipboard) = ClipboardContext::new() {
91 if let Err(err) = clipboard.set_contents(selected_files.clone()) {
92 eprintln!("Failed to copy to clipboard: {}", err);
93 }
94 } else {
95 eprintln!("Clipboard not available.");
96 }
97 }
98 _ => {}
99 }
100 }
101 // Handle the event in the file explorer.
102 file_explorer.handle(&event)?;
103 }
104
105 disable_raw_mode()?;
106 stdout().execute(LeaveAlternateScreen)?;
107 // Print the selected file paths to stdout.
108 for file in file_explorer.selected_files() {
109 println!("{}", file.path().display());
110 }
111 Ok(())
112}Sourcepub fn set_cwd<P: Into<PathBuf>>(&mut self, cwd: P) -> Result<()>
pub fn set_cwd<P: Into<PathBuf>>(&mut self, cwd: P) -> Result<()>
Sets the current working directory of the file explorer.
§Examples
use fpicker::FileExplorer;
let mut file_explorer = FileExplorer::new().unwrap();
file_explorer.set_cwd("/Documents").unwrap();
assert_eq!(file_explorer.cwd().display().to_string(), "/Documents");Sourcepub fn selected_files(&self) -> &Vec<File>
pub fn selected_files(&self) -> &Vec<File>
Examples found in repository?
11fn main() -> io::Result<()> {
12 enable_raw_mode()?;
13 stdout().execute(EnterAlternateScreen)?;
14
15 let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
16
17 // Create a new file explorer with the default theme and title.
18 let theme = Theme::default().add_default_title();
19 let mut file_explorer = FileExplorer::with_theme(theme)?;
20
21 let mut selected_paths = vec![];
22
23 loop {
24 // Render the file explorer widget.
25 terminal.draw(|f| {
26 f.render_widget(&file_explorer.widget(), f.area());
27 })?;
28
29 // Read the next event from the terminal.
30 let event = read()?;
31 if let Event::Key(key) = event {
32 if key.code == KeyCode::Char('q') {
33 // Collect selected file paths.
34 selected_paths = file_explorer
35 .selected_files()
36 .iter()
37 .map(|file| file.path().display().to_string())
38 .collect();
39 break;
40 }
41 }
42 // Handle the event in the file explorer.
43 file_explorer.handle(&event)?;
44 }
45
46 // Restore the terminal to normal mode.
47 disable_raw_mode()?;
48 stdout().execute(LeaveAlternateScreen)?;
49
50 // Print the selected file paths to stdout.
51 for path in selected_paths {
52 println!("{}", path);
53 }
54
55 // Return exit code 0 explicitly.
56 process::exit(0);
57}More examples
17fn main() -> io::Result<()> {
18 enable_raw_mode()?;
19 stdout().execute(EnterAlternateScreen)?;
20
21 let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
22 let layout = Layout::vertical([
23 Constraint::Ratio(4, 5), // Main file explorer and content area
24 Constraint::Ratio(1, 5), // Bottom window for selected file paths
25 ]);
26
27 // Inner layout for the top section
28 let top_layout = Layout::horizontal([Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)]);
29
30 // Create a new file explorer with the default theme and title.
31 let theme = get_theme();
32 let mut file_explorer = FileExplorer::with_theme(theme)?;
33
34 loop {
35 // Get the content of the current selected file (if it's indeed a file).
36 let file_content = get_file_content(file_explorer.current().path())?;
37 let selected_files: String = file_explorer
38 .selected_files()
39 .iter()
40 .map(|file| file.path().display().to_string())
41 .collect::<Vec<String>>()
42 .join("\n");
43
44 // Render the file explorer widget, file content, and selected file paths.
45 terminal.draw(|f| {
46 let chunks = layout.split(f.area());
47 let top_chunks = top_layout.split(chunks[0]);
48
49 // Top section
50 f.render_widget(&file_explorer.widget(), top_chunks[0]);
51 f.render_widget(
52 Paragraph::new(file_content).block(
53 Block::default()
54 .borders(Borders::ALL)
55 .border_type(BorderType::Double),
56 ),
57 top_chunks[1],
58 );
59
60 // Bottom section
61 f.render_widget(
62 Paragraph::new(selected_files.clone()).block(
63 Block::default()
64 .borders(Borders::ALL)
65 .title("q:Quit, c: copy selected file contents to clipboard, p: copy paths to clipboard"),
66 ),
67 chunks[1],
68 );
69 })?;
70
71 // Read the next event from the terminal.
72 let event = read()?;
73 if let Event::Key(key) = event {
74 match key.code {
75 KeyCode::Char('q') => break, // Quit the application
76 KeyCode::Char('c') => {
77 // Copy selected file paths to clipboard
78 if let Ok(mut clipboard) = ClipboardContext::new() {
79 if let Err(err) = clipboard.set_contents(get_selected_files_content(
80 &file_explorer.selected_files(),
81 )) {
82 eprintln!("Failed to copy to clipboard: {}", err);
83 }
84 } else {
85 eprintln!("Clipboard not available.");
86 }
87 }
88 KeyCode::Char('p') => {
89 // Copy selected file paths to clipboard
90 if let Ok(mut clipboard) = ClipboardContext::new() {
91 if let Err(err) = clipboard.set_contents(selected_files.clone()) {
92 eprintln!("Failed to copy to clipboard: {}", err);
93 }
94 } else {
95 eprintln!("Clipboard not available.");
96 }
97 }
98 _ => {}
99 }
100 }
101 // Handle the event in the file explorer.
102 file_explorer.handle(&event)?;
103 }
104
105 disable_raw_mode()?;
106 stdout().execute(LeaveAlternateScreen)?;
107 // Print the selected file paths to stdout.
108 for file in file_explorer.selected_files() {
109 println!("{}", file.path().display());
110 }
111 Ok(())
112}Sourcepub fn set_theme(&mut self, theme: Theme)
pub fn set_theme(&mut self, theme: Theme)
Sets the theme of the file explorer.
§Examples
use fpicker::{FileExplorer, Theme};
let mut file_explorer = FileExplorer::new().unwrap();
file_explorer.set_theme(Theme::default().add_default_title());Examples found in repository?
15fn main() -> io::Result<()> {
16 enable_raw_mode()?;
17 stdout().execute(EnterAlternateScreen)?;
18
19 let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
20
21 // Create a new file explorer with the light theme.
22 let mut dark_theme = false;
23 let mut file_explorer = FileExplorer::with_theme(get_light_theme())?;
24
25 loop {
26 // Render the file explorer widget.
27 terminal.draw(|f| {
28 f.render_widget(&file_explorer.widget(), f.area());
29 })?;
30
31 // Read the next event from the terminal.
32 let event = read()?;
33 // If the user presses `Ctrl + s`, switch the theme.
34 // If the user presses `Ctrl + q`, quit the application.
35 if let Event::Key(key) = event {
36 if key.modifiers == crossterm::event::KeyModifiers::CONTROL {
37 match key.code {
38 KeyCode::Char('s') => {
39 dark_theme = !dark_theme;
40 if dark_theme {
41 file_explorer.set_theme(get_dark_theme());
42 } else {
43 file_explorer.set_theme(get_light_theme());
44 }
45 }
46 KeyCode::Char('q') => {
47 break;
48 }
49 _ => {}
50 }
51 }
52 }
53 // Handle the event in the file explorer.
54 file_explorer.handle(&event)?;
55 }
56
57 disable_raw_mode()?;
58 stdout().execute(LeaveAlternateScreen)?;
59 Ok(())
60}Sourcepub fn set_selected_idx(&mut self, selected: usize)
pub fn set_selected_idx(&mut self, selected: usize)
Sets the selected file or directory index inside the current Vec of files
and directories if 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 2)
└── resume.pdfYou can set the selected index like this:
use fpicker::FileExplorer;
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`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html) 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");
#[test]
#[should_panic]
fn index_out_of_bound() {
let mut file_explorer = FileExplorer::new().unwrap();
file_explorer.set_selected_idx(4);
}Sourcepub fn current(&self) -> &File
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.pdfYou can get the current file like this:
use fpicker::FileExplorer;
let file_explorer = FileExplorer::new().unwrap();
/* user select `password.png` */
let file = file_explorer.current();
assert_eq!(file.name(), "passport.png");Examples found in repository?
17fn main() -> io::Result<()> {
18 enable_raw_mode()?;
19 stdout().execute(EnterAlternateScreen)?;
20
21 let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
22 let layout = Layout::vertical([
23 Constraint::Ratio(4, 5), // Main file explorer and content area
24 Constraint::Ratio(1, 5), // Bottom window for selected file paths
25 ]);
26
27 // Inner layout for the top section
28 let top_layout = Layout::horizontal([Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)]);
29
30 // Create a new file explorer with the default theme and title.
31 let theme = get_theme();
32 let mut file_explorer = FileExplorer::with_theme(theme)?;
33
34 loop {
35 // Get the content of the current selected file (if it's indeed a file).
36 let file_content = get_file_content(file_explorer.current().path())?;
37 let selected_files: String = file_explorer
38 .selected_files()
39 .iter()
40 .map(|file| file.path().display().to_string())
41 .collect::<Vec<String>>()
42 .join("\n");
43
44 // Render the file explorer widget, file content, and selected file paths.
45 terminal.draw(|f| {
46 let chunks = layout.split(f.area());
47 let top_chunks = top_layout.split(chunks[0]);
48
49 // Top section
50 f.render_widget(&file_explorer.widget(), top_chunks[0]);
51 f.render_widget(
52 Paragraph::new(file_content).block(
53 Block::default()
54 .borders(Borders::ALL)
55 .border_type(BorderType::Double),
56 ),
57 top_chunks[1],
58 );
59
60 // Bottom section
61 f.render_widget(
62 Paragraph::new(selected_files.clone()).block(
63 Block::default()
64 .borders(Borders::ALL)
65 .title("q:Quit, c: copy selected file contents to clipboard, p: copy paths to clipboard"),
66 ),
67 chunks[1],
68 );
69 })?;
70
71 // Read the next event from the terminal.
72 let event = read()?;
73 if let Event::Key(key) = event {
74 match key.code {
75 KeyCode::Char('q') => break, // Quit the application
76 KeyCode::Char('c') => {
77 // Copy selected file paths to clipboard
78 if let Ok(mut clipboard) = ClipboardContext::new() {
79 if let Err(err) = clipboard.set_contents(get_selected_files_content(
80 &file_explorer.selected_files(),
81 )) {
82 eprintln!("Failed to copy to clipboard: {}", err);
83 }
84 } else {
85 eprintln!("Clipboard not available.");
86 }
87 }
88 KeyCode::Char('p') => {
89 // Copy selected file paths to clipboard
90 if let Ok(mut clipboard) = ClipboardContext::new() {
91 if let Err(err) = clipboard.set_contents(selected_files.clone()) {
92 eprintln!("Failed to copy to clipboard: {}", err);
93 }
94 } else {
95 eprintln!("Clipboard not available.");
96 }
97 }
98 _ => {}
99 }
100 }
101 // Handle the event in the file explorer.
102 file_explorer.handle(&event)?;
103 }
104
105 disable_raw_mode()?;
106 stdout().execute(LeaveAlternateScreen)?;
107 // Print the selected file paths to stdout.
108 for file in file_explorer.selected_files() {
109 println!("{}", file.path().display());
110 }
111 Ok(())
112}Sourcepub const fn cwd(&self) -> &PathBuf
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.pdfYou can get the current working directory like this:
use fpicker::FileExplorer;
let file_explorer = FileExplorer::new().unwrap();
/* user select `password.png` */
let cwd = file_explorer.cwd();
assert_eq!(cwd.display().to_string(), "/Documents");Sourcepub const fn files(&self) -> &Vec<File>
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.pdfYou can get the Vec of files and directories like this:
use fpicker::FileExplorer;
let file_explorer = FileExplorer::new().unwrap();
/* user select `password.png` */
let files = file_explorer.files();
assert_eq!(files.len(), 4); // 3 files/directory and the parent directorySourcepub const fn selected_idx(&self) -> usize
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 2)
└── resume.pdfYou can get the selected index like this:
use fpicker::FileExplorer;
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`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html) of files, the selected index will be 2.
assert_eq!(selected_idx, 2);Trait Implementations§
Source§impl Clone for FileExplorer
impl Clone for FileExplorer
Source§fn clone(&self) -> FileExplorer
fn clone(&self) -> FileExplorer
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for FileExplorer
impl Debug for FileExplorer
Source§impl Hash for FileExplorer
impl Hash for FileExplorer
Source§impl PartialEq for FileExplorer
impl PartialEq for FileExplorer
impl Eq for FileExplorer
impl StructuralPartialEq for FileExplorer
Auto Trait Implementations§
impl Freeze for FileExplorer
impl !RefUnwindSafe for FileExplorer
impl !Send for FileExplorer
impl !Sync for FileExplorer
impl Unpin for FileExplorer
impl !UnwindSafe for FileExplorer
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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