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
|
use std::io;
use crossterm::{Terminal, ClearType};
use termimad::{Area, MadView};
use crate::app::{AppState, AppStateCmdResult};
use crate::app_context::AppContext;
use crate::commands::{Action, Command};
use crate::conf::Conf;
use crate::help_content;
use crate::screens::Screen;
use crate::status::Status;
use crate::task_sync::TaskLifetime;
use crate::verb_store::PrefixSearchResult;
use crate::verbs::VerbExecutor;
/// an application state dedicated to help
pub struct HelpState {
view: MadView,
}
impl HelpState {
pub fn new(screen: &Screen, con: &AppContext) -> HelpState {
let area = Area::uninitialized(); // will be fixed at drawing time
Terminal::new().clear(ClearType::All).unwrap();
let markdown = help_content::build_markdown(con);
let view = MadView::from(markdown, area, screen.skin.to_mad_skin());
HelpState { view }
}
fn resize_area(&mut self, screen: &Screen) {
let mut area = Area::new(0, 0, screen.w, screen.h - 2);
area.pad_for_max_width(100);
self.view.resize(&area);
}
}
impl AppState for HelpState {
fn apply(
&mut self,
cmd: &mut Command,
screen: &mut Screen,
con: &AppContext,
) -> io::Result<AppStateCmdResult> {
self.resize_area(screen);
Ok(match &cmd.action {
Action::Back => AppStateCmdResult::PopState,
Action::Verb(invocation) => match con.verb_store.search(&invocation.key) {
PrefixSearchResult::Match(verb) => {
self.execute_verb(verb, &invocation, screen, con)?
}
_ => AppStateCmdResult::verb_not_found(&invocation.key),
},
Action::MoveSelection(dy) => {
self.view.try_scroll_lines(*dy);
AppStateCmdResult::Keep
}
Action::ScrollPage(dp) => {
self.view.try_scroll_pages(*dp);
AppStateCmdResult::Keep
}
Action::Refresh => AppStateCmdResult::RefreshState,
Action::Quit => AppStateCmdResult::Quit,
_ => AppStateCmdResult::Keep,
})
}
fn refresh(&mut self, _screen: &Screen, _con: &AppContext) -> Command {
Command::new()
}
fn has_pending_tasks(&self) -> bool {
false
}
fn do_pending_task(&mut self, _screen: &mut Screen, _tl: &TaskLifetime) {
unreachable!();
}
fn display(&mut self, screen: &mut Screen, _con: &AppContext) -> io::Result<()> {
self.resize_area(screen);
self.view.write()
}
fn write_status(&self, screen: &mut Screen, cmd: &Command, con: &AppContext) -> io::Result<()> {
match &cmd.action {
Action::VerbEdit(invocation) => match con.verb_store.search(&invocation.key) {
PrefixSearchResult::NoMatch => screen.write_status_err("No matching verb)"),
PrefixSearchResult::Match(verb) => {
if let Some(err) = verb.match_error(invocation) {
screen.write_status_err(&err)
} else {
screen.write_status_text(
&format!(
"Hit <enter> to {} : {}",
&verb.invocation.key,
&verb.description_for(Conf::default_location(), &invocation.args)
)
.to_string(),
)
}
}
PrefixSearchResult::TooManyMatches => {
screen.write_status_text("Type a verb then <enter> to execute it")
}
},
_ => screen
.write_status_text("Hit <esc> to get back to the tree, or a space to start a verb"),
}
}
fn write_flags(&self, _screen: &mut Screen, _con: &AppContext) -> io::Result<()> {
Ok(())
}
}
|