fm/modes/utils/
line_display.rs

1use ratatui::layout::Rect;
2
3use crate::app::Status;
4use crate::io::MenuFirstLine;
5use crate::modes::{
6    InputCompleted, InputSimple, MarkAction, Menu, Navigate, NeedConfirmation, PasswordKind,
7    PasswordUsage,
8};
9
10/// Used by different kind of menu to display informations about the current menu.
11/// Most of the time it's a few lines describing the menu actions.
12pub trait LineDisplay {
13    /// Returns a displayable representation of the object as a vector of `String`s
14    fn line_display(&self, status: &Status, rect: &Rect) -> Vec<String>;
15}
16
17impl LineDisplay for Menu {
18    fn line_display(&self, status: &Status, rect: &Rect) -> Vec<String> {
19        match self {
20            Self::Navigate(mode) => mode.line_display(status, rect),
21            Self::InputSimple(mode) => mode.line_display(status, rect),
22            Self::InputCompleted(mode) => mode.line_display(status, rect),
23            Self::NeedConfirmation(mode) => mode.line_display(status, rect),
24            Self::Nothing => vec![],
25        }
26    }
27}
28
29impl LineDisplay for NeedConfirmation {
30    fn line_display(&self, _status: &Status, _: &Rect) -> Vec<String> {
31        vec![self.to_string(), " (y/n)".to_owned()]
32    }
33}
34
35impl LineDisplay for Navigate {
36    fn line_display(&self, _status: &Status, _: &Rect) -> Vec<String> {
37        match self {
38            Self::Marks(MarkAction::Jump) => {
39                vec!["Jump to...".to_owned()]
40            }
41            Self::Marks(MarkAction::New) => {
42                vec!["Save mark...".to_owned()]
43            }
44            _ => {
45                vec![Menu::Navigate(*self).to_string()]
46            }
47        }
48    }
49}
50
51impl LineDisplay for InputCompleted {
52    fn line_display(&self, status: &Status, _: &Rect) -> Vec<String> {
53        let tab = status.current_tab();
54        let mut completion_strings = vec![tab.menu_mode.to_string(), status.menu.input.string()];
55        if let Some(completion) = status
56            .menu
57            .completion
58            .complete_input_string(&status.menu.input.string())
59        {
60            completion_strings.push(completion.to_owned());
61        }
62        if matches!(*self, Self::Exec) {
63            for path in &status.menu.flagged.content {
64                completion_strings.push(format!(" {path}", path = path.display()));
65            }
66        }
67        completion_strings
68    }
69}
70
71impl LineDisplay for InputSimple {
72    fn line_display(&self, status: &Status, rect: &Rect) -> Vec<String> {
73        match self {
74            Self::Password(_, PasswordUsage::CRYPTSETUP(PasswordKind::CRYPTSETUP)) => {
75                vec![
76                    PasswordKind::CRYPTSETUP.to_string(),
77                    status.menu.input.password(),
78                ]
79            }
80            Self::Password(..) => {
81                vec![PasswordKind::SUDO.to_string(), status.menu.input.password()]
82            }
83            _ => {
84                let presentation = self.to_string();
85                let used_space = presentation.len() + MenuFirstLine::LEFT_MARGIN as usize + 1;
86                let avail = (rect.width as usize).saturating_sub(used_space);
87                vec![presentation, status.menu.input.scrolled_string(avail)]
88            }
89        }
90    }
91}