rsnaker/graphics/menus/retro_parameter_table/
customized_with_edit.rs1use crate::game_logic::game_options::{get_parameter_range, GameOptions, ONLY_FOR_CLI_PARAMETERS};
2use crate::graphics::menus::retro_parameter_table::generic_logic::{
3 get_default_action_input, ActionInputs, CellValue, FooterData, GenericMenu, RowData,
4 TableParameterAction,
5};
6use clap::CommandFactory;
7use crossterm::event::KeyCode;
8use ratatui::DefaultTerminal;
9
10pub fn setup_and_run_cli_table_parameters(
11 terminal: &mut DefaultTerminal,
12 options: &mut GameOptions,
13) {
14 let current_preset = options.load;
15 let data: Vec<RowData> = load_parameter_cli_in_table(options);
16 let mut actions = get_default_action_input();
17 actions.push(ActionInputs {
18 key: vec![KeyCode::Char('x'), KeyCode::Char('X')],
19 action: vec![
20 TableParameterAction::ApplyAndSave(options),
21 TableParameterAction::Quit,
22 ],
23 });
24 for i in 1..=7u16 {
26 let key_char = char::from_digit(u32::from(i), 10).unwrap();
30
31 actions.push(ActionInputs {
32 key: vec![
34 KeyCode::Char(key_char),
35 KeyCode::Char(key_char.to_ascii_uppercase()),
36 ],
37 action: vec![TableParameterAction::LoadPreset(i, |preset| {
39 let footer_updated_data = Some(parameters_cli_get_footer_data(Some(preset)));
40 if let Ok(game_options_from_preset) =
42 &mut GameOptions::load_from_toml_preset(preset)
43 {
44 (
45 Some(load_parameter_cli_in_table(game_options_from_preset)),
46 footer_updated_data,
47 )
48 } else {
49 (None, footer_updated_data)
51 }
52 })],
53 });
54 }
55 GenericMenu::new(
57 data,
58 ¶meters_cli_get_headers(),
59 parameters_cli_get_footer_data(current_preset),
60 current_preset,
61 )
62 .run(actions, terminal);
63}
64
65#[must_use]
66fn load_parameter_cli_in_table(options: &mut GameOptions) -> Vec<RowData> {
67 let cmd = GameOptions::command();
68 let mut rows = vec![];
69 let mut arg_value;
70 for arg in cmd.get_arguments().filter(|arg| {
73 !ONLY_FOR_CLI_PARAMETERS
74 .iter()
75 .any(|arg_pattern| arg.get_long().unwrap().contains(arg_pattern))
76 }) {
77 let mut all_value_for_this_arg = vec![];
79 let pv_bool_enum = arg.get_possible_values();
82 if pv_bool_enum.is_empty() {
83 if let Some(range) = get_parameter_range(arg.get_long().unwrap()) {
84 all_value_for_this_arg.extend(range.map(|i| i.to_string()));
85 } else {
86 all_value_for_this_arg.extend(GameOptions::emojis_iterator());
90 add_unique_symbol(&mut all_value_for_this_arg, options.head_symbol.clone());
92 add_unique_symbol(&mut all_value_for_this_arg, options.body_symbol.clone());
93 }
94 } else {
95 all_value_for_this_arg
97 .extend(pv_bool_enum.into_iter().map(|v| v.get_name().to_string()));
98 }
99 let mut index = 0;
103 if let Some(default_value) = options
105 .to_structured_toml()
106 .get(&arg.get_long().unwrap().replace('-', "_"))
107 {
108 let mut default_str = default_value.to_string();
109 if default_str.contains('"') {
111 default_str = default_str.split('"').collect::<Vec<&str>>()[1].to_string();
112 }
113 index = all_value_for_this_arg
114 .iter()
115 .position(|v| v == &default_str)
116 .unwrap_or(0);
117 }
118 let arg_name = "--".to_string() + arg.get_long().unwrap();
120 arg_value = CellValue::new_with_options(arg_name, all_value_for_this_arg, index);
121
122 rows.push(RowData::new(vec![
123 arg_value,
124 CellValue::new(arg.get_long().unwrap().to_string()),
125 CellValue::new(
126 arg.get_help()
127 .unwrap_or_else(|| {
128 panic!("Missing help for argument: {}", arg.get_long().unwrap())
129 })
130 .to_string(),
131 ),
132 ]));
133 }
134 rows
135}
136#[must_use]
137fn parameters_cli_get_headers() -> Vec<String> {
138 vec![
139 "🎯 Value".to_string(),
140 "📋 Parameter".to_string(),
141 "📝 Description / super power".to_string(),
142 ]
143}
144#[must_use]
146pub fn parameters_cli_get_footer_data(current_preset: Option<u16>) -> Vec<FooterData> {
147 vec![
148 FooterData {
149 symbol: "Esc".into(),
150 text: "Quit".into(),
151 value: None,
152 },
153 FooterData {
154 symbol: "x".into(),
155 text: "Quit & Save".into(),
156 value: None,
157 },
158 FooterData {
159 symbol: "↕".into(),
160 text: "Move".into(),
161 value: None,
162 },
163 FooterData {
164 symbol: "← →".into(),
165 text: "Change value".into(),
166 value: None,
167 },
168 FooterData {
169 symbol: "1-7".into(),
170 text: "Load".into(),
171 value: current_preset,
172 },
173 ]
174}
175
176fn add_unique_symbol(collection: &mut Vec<String>, symbol: String) {
177 if !collection.contains(&symbol) {
178 collection.push(symbol);
179 }
180}