summaryrefslogtreecommitdiffstats
path: root/src/app/cmd_result.rs
blob: ff7b46276f7a8873009f2ef50cf188d7953582fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use {
    super::*,
    crate::{
        browser::BrowserState,
        command::Sequence,
        errors::TreeBuildError,
        launchable::Launchable,
        verb::Internal,
    },
    std::fmt,
};

/// Either left or right
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum HDir {
    Left,
    Right,
}

/// the symbolic reference to the panel to close
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PanelReference {
    Active,
    Leftest,
    Rightest,
    Id(PanelId),
    Preview,
}

/// Result of applying a command to a state
pub enum CmdResult {
    ApplyOnPanel {
        id: PanelId,
    },
    ClosePanel {
        validate_purpose: bool,
        panel_ref: PanelReference,
    },
    DisplayError(String),
    ExecuteSequence {
        sequence: Sequence,
    },
    HandleInApp(Internal), // command must be handled at the app level
    Keep,
    Launch(Box<Launchable>),
    NewPanel {
        state: Box<dyn PanelState>,
        purpose: PanelPurpose,
        direction: HDir,
    },
    NewState {
        state: Box<dyn PanelState>,
        message: Option<&'static str>, // explaining why there's a new state
    },
    PopStateAndReapply, // the state asks the command be executed on a previous state
    PopState,
    Quit,
    RefreshState {
        clear_cache: bool,
    },
}

impl CmdResult {
    pub fn verb_not_found(text: &str) -> CmdResult {
        CmdResult::DisplayError(format!("verb not found: {:?}", &text))
    }
    pub fn from_optional_state(
        os: Result<BrowserState, TreeBuildError>,
        message: Option<&'static str>,
        in_new_panel: bool,
    ) -> CmdResult {
        match os {
            Ok(os) => {
                if in_new_panel {
                    CmdResult::NewPanel { // TODO keep the message ?
                        state: Box::new(os),
                        purpose: PanelPurpose::None,
                        direction: HDir::Right,
                    }
                } else {
                    CmdResult::NewState {
                        state: Box::new(os),
                        message,
                    }
                }
            }
            Err(TreeBuildError::Interrupted) => CmdResult::Keep,
            Err(e) => CmdResult::error(e.to_string()),
        }
    }
    pub fn new_state(state: Box<dyn PanelState>) -> Self {
        Self::NewState { state, message: None }
    }
    pub fn error<S: Into<String>>(message: S) -> Self {
        Self::DisplayError(message.into())
    }
}

impl From<Launchable> for CmdResult {
    fn from(launchable: Launchable) -> Self {
        CmdResult::Launch(Box::new(launchable))
    }
}

impl fmt::Debug for CmdResult {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{}",
            match self {
                CmdResult::ApplyOnPanel { .. } => "ApplyOnPanel",
                CmdResult::ClosePanel {
                    validate_purpose: false, ..
                } => "CancelPanel",
                CmdResult::ClosePanel {
                    validate_purpose: true, ..
                } => "OkPanel",
                CmdResult::DisplayError(_) => "DisplayError",
                CmdResult::ExecuteSequence{ .. } => "ExecuteSequence",
                CmdResult::Keep => "Keep",
                CmdResult::Launch(_) => "Launch",
                CmdResult::NewState { .. } => "NewState",
                CmdResult::NewPanel { .. } => "NewPanel",
                CmdResult::PopStateAndReapply => "PopStateAndReapply",
                CmdResult::PopState => "PopState",
                CmdResult::HandleInApp(_) => "HandleInApp",
                CmdResult::Quit => "Quit",
                CmdResult::RefreshState { .. } => "RefreshState",
            }
        )
    }
}