demo/
demo.rs

1use crossterm::{
2    event::{self, Event, KeyCode, KeyModifiers},
3    execute,
4    terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
5};
6use std::io::{self, Result};
7use tui::{
8    backend::{Backend, CrosstermBackend},
9    widgets::{Block, Borders},
10    Frame, Terminal,
11};
12
13use tui_file_dialog::{bind_keys, FileDialog};
14
15struct App {
16    // 1. Add the `FileDialog` to the tui app.
17    file_dialog: FileDialog,
18}
19
20impl App {
21    pub fn new(file_dialog: FileDialog) -> Self {
22        Self { file_dialog }
23    }
24}
25
26fn main() -> Result<()> {
27    enable_raw_mode()?;
28    let mut stdout = io::stdout();
29    execute!(stdout, EnterAlternateScreen)?;
30    let backend = CrosstermBackend::new(stdout);
31    let mut terminal = Terminal::new(backend)?;
32
33    let res = run_app(&mut terminal, App::new(FileDialog::new(60, 40)?));
34
35    disable_raw_mode()?;
36    execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
37    terminal.show_cursor()?;
38
39    if let Err(err) = res {
40        println!("{:?}", err)
41    }
42
43    Ok(())
44}
45
46fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> io::Result<()> {
47    loop {
48        terminal.draw(|f| ui(f, &mut app))?;
49
50        // 2. Use the `bind_keys` macro to overwrite key bindings, when the file dialog is open.
51        // The first argument of the macro is the expression that should be used to access the file
52        // dialog.
53        bind_keys!(
54            app.file_dialog,
55            if let Event::Key(key) = event::read()? {
56                match key.code {
57                    KeyCode::Char('o') if key.modifiers == KeyModifiers::CONTROL => {
58                        app.file_dialog.open()
59                    }
60                    KeyCode::Char('q') | KeyCode::Esc => {
61                        return Ok(());
62                    }
63                    _ => {}
64                }
65            }
66        )
67    }
68}
69
70fn ui<B: Backend>(f: &mut Frame<B>, app: &mut App) {
71    let block = Block::default()
72        .title(format!(
73            "Selected file: {}",
74            app.file_dialog
75                .selected_file
76                .as_ref()
77                .map_or("None".to_string(), |f| f.to_string_lossy().to_string())
78        ))
79        .borders(Borders::ALL);
80    f.render_widget(block, f.size());
81
82    // 3. Call the draw function of the file dialog in order to render it.
83    app.file_dialog.draw(f);
84}