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
|
use just_enough_vcs_cli::subcmd::cmd::JVCommandContext;
use just_enough_vcs_cli::utils::display::md;
use just_enough_vcs_cli::{
subcmd::{errors::CmdProcessError, processer::jv_cmd_process},
utils::env::current_locales,
};
use rust_i18n::{set_locale, t};
rust_i18n::i18n!("resources/locales/jvn", fallback = "en");
macro_rules! special_flag {
($args:expr, $flag:expr) => {{
let flag = $flag;
let found = $args.iter().any(|arg| arg == flag);
$args.retain(|arg| arg != flag);
found
}};
}
macro_rules! special_argument {
($args:expr, $flag:expr) => {{
let flag = $flag;
let mut value: Option<String> = None;
let mut i = 0;
while i < $args.len() {
if $args[i] == flag {
if i + 1 < $args.len() {
value = Some($args[i + 1].clone());
$args.remove(i + 1);
$args.remove(i);
} else {
value = None;
$args.remove(i);
}
break;
}
i += 1;
}
value
}};
}
#[tokio::main]
async fn main() {
// Collect arguments
let mut args: Vec<String> = std::env::args().skip(1).collect();
// Init i18n
let lang = special_argument!(args, "--lang").unwrap_or(current_locales());
set_locale(&lang);
// Init colored
#[cfg(windows)]
colored::control::set_virtual_terminal(true).unwrap();
let no_error_logs = special_flag!(args, "--no-error-logs");
let quiet = special_flag!(args, "--quiet") || special_flag!(args, "-q");
let help = special_flag!(args, "--help") || special_flag!(args, "-h");
let confirmed = special_flag!(args, "--confirm") || special_flag!(args, "-C");
// Process commands
let render_result = match jv_cmd_process(args, JVCommandContext { help, confirmed }).await {
Ok(result) => result,
Err(e) => {
if !no_error_logs {
match e {
CmdProcessError::Prepare(cmd_prepare_error) => {
eprintln!(
"{}",
md(t!("process_error.prepare_error", error = cmd_prepare_error))
);
}
CmdProcessError::Execute(cmd_execute_error) => {
eprintln!(
"{}",
md(t!("process_error.execute_error", error = cmd_execute_error))
);
}
CmdProcessError::Render(cmd_render_error) => {
eprintln!(
"{}",
md(t!("process_error.render_error", error = cmd_render_error))
);
}
CmdProcessError::Error(error) => {
eprintln!("{}", md(t!("process_error.other", error = error)));
}
CmdProcessError::NoNodeFound(node) => {
eprintln!("{}", md(t!("process_error.no_node_found", node = node)));
}
CmdProcessError::NoMatchingCommand => {
eprintln!("{}", md(t!("process_error.no_matching_command")));
}
CmdProcessError::AmbiguousCommand(nodes) => {
let nodes_list = nodes
.iter()
.enumerate()
.map(|(i, node)| format!("{}. {}", i + 1, node))
.collect::<Vec<String>>()
.join("\n");
eprintln!(
"{}",
md(t!("process_error.ambiguous_command", nodes = nodes_list))
);
}
CmdProcessError::ParseError(help) => {
if help.trim().len() < 1 {
eprintln!("{}", md(t!("process_error.parse_error")));
} else {
eprintln!("{}", help)
}
}
}
}
std::process::exit(1);
}
};
// Print
if !quiet {
print!("{}", render_result);
}
}
|