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
use super::*;
use crate::app;
use crate::output;
use crate::output::Output;
use std::collections::HashMap;
use rustyline::{Config, Editor};
pub struct Cli;
impl Action for Cli
{
fn usage<'a,'b>(&'a self) -> App<'b,'b>
{
SubCommand::with_name("cli")
.about("interactive command line client")
}
fn call(&mut self,hero: &Hero,_: &ArgMatches) -> Result<Vec<Output>>
{
let subcommands = vec!
[ Dump::new_action()
, Roll::new_action()
, Tracker::new_action("health",hero.health,hero.health)
, Tracker::new_action("astral",hero.astral,hero.astral)
, Tracker::new_action("stamina",hero.stamina,hero.stamina)
];
let mut subcommands: HashMap<String,Box<dyn Action>> = subcommands.into_iter()
.map(|command|
{
(command.usage().get_name().to_owned(),command)
})
.collect();
let mut rl = Editor::<()>::with_config(Config::builder()
.max_history_size(1024*512)
.history_ignore_dups(false)
.history_ignore_space(true)
.auto_add_history(true)
.tab_stop(4)
.build());
for line in rl.iter("% ")
{
let words = line
.map_err(|err| err.into())
.and_then(|line| Ok(shell_words::split(&line)?));
if let Ok(ref args) = words
{
if args.eq(&["exit"])
{
break;
}
}
let result: Result<Vec<_>> = words
.and_then(|words|
{
let app = app().subcommands(subcommands.values().map(|command| command.usage()));
Ok(app.get_matches_from_safe(std::iter::once(String::new()).chain(words))?)
})
.and_then(|matches|
{
let (command, args) = matches.subcommand();
let command = subcommands.get_mut(command).unwrap_or_else(|| unreachable!());
let args = args.unwrap_or_else(|| unreachable!());
let formatter: Box<dyn output::Formatter> = matches.value_of("format").unwrap().parse::<output::Format>()?.into();
let result = command.call(&hero,&args)?.into_iter()
.map(|result| formatter.format(&result))
.collect();
Ok(result)
});
match result
{
Ok(outputs) =>
{
for output in outputs
{
println!("{}",output)
}
},
Err(error) => eprintln!("{}", error.description()),
}
}
Ok(vec![])
}
}