hyprshell_config_lib/
explain.rs1use crate::Config;
2use std::fmt::Write;
3use std::path::Path;
4
5const BOLD: &str = "\x1b[1m";
6const ITALIC: &str = "\x1b[3m";
7const BLUE: &str = "\x1b[34m";
8const GREEN: &str = "\x1b[32m";
9const RESET: &str = "\x1b[0m";
10
11#[must_use]
12pub fn explain(config: &Config, config_file: Option<&Path>, enable_color: bool) -> String {
13 let (bold, italic, blue, green, reset) = if enable_color {
14 (BOLD, ITALIC, BLUE, GREEN, RESET)
15 } else {
16 ("", "", "", "", "")
17 };
18
19 let mut builder = config_file.map_or_else(String::new, |config_file| {
20 let config_file_display = config_file.display();
21 format!(
22 "{bold}{green}Config is valid{reset} ({config_file_display})\n{bold}Explanation{reset} ({blue}blue{reset} are keys, {bold}{blue}bold blue{reset} keys can be configured in config):{reset}\n",
23 )
24 });
25
26 if let Some(windows) = &config.windows {
27 if let Some(overview) = &windows.overview {
28 let _ = builder.write_str(&format!(
29 "Use {bold}{blue}{}{reset} + {bold}{blue}{}{reset} to open the Overview. Use {blue}tab{reset} and {blue}grave{reset} / {blue}shift{reset} + {blue}tab{reset} to select a different window, press {blue}return{reset} to switch\n\
30 You can also use the {blue}arrow keys{reset} or {bold}{blue}{}{reset} + vim keys to navigate the workspaces. Use {blue}Esc{reset} to close the overview.\n",
31 overview.modifier,
32 overview.key,
33 overview.launcher.launch_modifier
34 ));
35 let _ = builder.write_str(&format!(
36 "After opening the Overview the {bold}Launcher{reset} is available:\n"
37 ));
38 let mut any_plugin = false;
39 if let Some(_applications) = overview.launcher.plugins.applications.as_ref() {
40 any_plugin = true;
41 let _ = builder.write_str(&format!("\t- Start typing to search through applications (sorted by how often they were opened). Press {blue}return{reset} to launch the first app, use {blue}Ctrl{reset} + {blue}1{reset}/{blue}2{reset}/{blue}3{reset}/... to open the second, third, etc.\n"));
42 }
43 if overview.launcher.plugins.terminal.is_some() {
44 any_plugin = true;
45 let _ = builder.write_str(&format!(
46 "\t- Press {blue}Ctrl{reset} + {blue}t{reset} to run the typed command in a terminal.\n"
47 ));
48 }
49 if overview.launcher.plugins.shell.is_some() {
50 any_plugin = true;
51 let _ = builder.write_str(&format!(
52 "\t- Press {blue}Ctrl{reset} + {blue}r{reset} to run the typed command in the background.\n",
53 ));
54 }
55 if let Some(engines) = &overview.launcher.plugins.websearch {
56 any_plugin = true;
57 let _ = builder.write_str(&format!("\t- Press {blue}Ctrl{reset} + {bold}{blue}<key>{reset} to search the typed text in any of the configured SearchEngines: {}.\n",
58 engines.engines.iter().map(|e| e.name.to_string()).collect::<Vec<_>>().join(", ")));
59 }
60 if overview.launcher.plugins.calc.is_some() {
61 any_plugin = true;
62 let _ = builder.write_str(
63 "\t- Typing a mathematical expression will calculate it and display the result in the launcher.\n",
64 );
65 }
66 if overview.launcher.plugins.path.is_some() {
67 any_plugin = true;
68 let _ = builder.write_str(
69 "\t- Paths (starting with ~ or /) can be open in default file-manager.\n",
70 );
71 }
72 if overview.launcher.plugins.actions.is_some() {
73 any_plugin = true;
74 let _ = builder.write_str(
75 "\t- Type Reboot/Shutdown/etc. to run corresponding commands. Type `actions` to see all available ones.\n",
76 );
77 }
78 if !any_plugin {
79 let _ = builder.write_str(&format!(
80 "{italic}\t<No plugins enabled in launcher>{reset}\n"
81 ));
82 }
83 } else {
84 let _ = builder.write_str(&format!("{italic}<Overview disabled>{reset}\n"));
85 }
86 builder.push('\n');
87
88 if let Some(switch) = &windows.switch {
89 let _ = builder.write_str(&format!(
90 "Press {bold}{blue}{}{reset} + {blue}tab{reset} and hold {bold}{blue}{}{reset} to view recently used applications. Press {blue}tab{reset} and {blue}grave{reset} / {blue}shift{reset} + {blue}tab{reset} to select a different window, release {bold}{blue}{}{reset} to close the window.\n",
91 switch.modifier,
92 switch.modifier,
93 switch.modifier,
94 ));
95 } else {
96 let _ = builder.write_str(&format!("{italic}<Switch mode disabled>{reset}\n"));
97 }
98 } else {
99 let _ = builder.write_str(&format!("{italic}<Windows disabled>{reset}\n"));
100 }
101
102 builder
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108 use crate::structs::*;
109 use std::path::PathBuf;
110
111 fn create_test_config() -> Config {
112 Config {
113 windows: Some(Windows {
114 overview: Some(Overview::default()),
115 switch: Some(Switch::default()),
116 ..Default::default()
117 }),
118 ..Default::default()
119 }
120 }
121
122 #[test_log::test]
123 #[test_log(default_log_filter = "trace")]
124 fn test_explain_with_overview() {
125 const CONFIG: &str = r"Config is valid (/test/config.ron)
126Explanation (blue are keys, bold blue keys can be configured in config):
127Use Super + Super_L to open the Overview. Use tab and grave / shift + tab to select a different window, press return to switch
128You can also use the arrow keys or Ctrl + vim keys to navigate the workspaces. Use Esc to close the overview.
129After opening the Overview the Launcher is available:
130 - Start typing to search through applications (sorted by how often they were opened). Press return to launch the first app, use Ctrl + 1/2/3/... to open the second, third, etc.
131 - Press Ctrl + t to run the typed command in a terminal.
132 - Press Ctrl + <key> to search the typed text in any of the configured SearchEngines: Google, Wikipedia.
133 - Typing a mathematical expression will calculate it and display the result in the launcher.
134 - Paths (starting with ~ or /) can be open in default file-manager.
135 - Type Reboot/Shutdown/etc. to run corresponding commands. Type `actions` to see all available ones.
136
137Press Alt + tab and hold Alt to view recently used applications. Press tab and grave / shift + tab to select a different window, release Alt to close the window.
138";
139 let mut config = create_test_config();
140 let a = config.windows.as_mut().unwrap();
141 a.overview.as_mut().unwrap().launcher.plugins.calc = Some(());
142 let path = PathBuf::from("/test/config.ron");
143 let result = explain(&config, Some(&path), false);
144 assert_eq!(result, CONFIG);
145 }
146
147 #[test_log::test]
148 #[test_log(default_log_filter = "trace")]
149 fn test_explain_without_overview() {
150 const CONFIG: &str = r"Config is valid (/test/config.ron)
151Explanation (blue are keys, bold blue keys can be configured in config):
152<Overview disabled>
153
154Press Alt + tab and hold Alt to view recently used applications. Press tab and grave / shift + tab to select a different window, release Alt to close the window.
155";
156 let mut config = create_test_config();
157 config
158 .windows
159 .as_mut()
160 .expect("config option missing")
161 .overview = None;
162 let path = PathBuf::from("/test/config.ron");
163 let result = explain(&config, Some(&path), false);
164 assert_eq!(result, CONFIG);
165 }
166
167 #[test_log::test]
168 #[test_log(default_log_filter = "trace")]
169 fn test_explain_without_switch() {
170 const CONFIG: &str = r"Config is valid (/test/config.ron)
171Explanation (blue are keys, bold blue keys can be configured in config):
172Use Super + Super_L to open the Overview. Use tab and grave / shift + tab to select a different window, press return to switch
173You can also use the arrow keys or Ctrl + vim keys to navigate the workspaces. Use Esc to close the overview.
174After opening the Overview the Launcher is available:
175 - Start typing to search through applications (sorted by how often they were opened). Press return to launch the first app, use Ctrl + 1/2/3/... to open the second, third, etc.
176 - Press Ctrl + t to run the typed command in a terminal.
177 - Press Ctrl + <key> to search the typed text in any of the configured SearchEngines: Google, Wikipedia.
178 - Paths (starting with ~ or /) can be open in default file-manager.
179 - Type Reboot/Shutdown/etc. to run corresponding commands. Type `actions` to see all available ones.
180
181<Switch mode disabled>
182";
183 let mut config = create_test_config();
184 config
185 .windows
186 .as_mut()
187 .expect("config option missing")
188 .switch = None;
189 let path = PathBuf::from("/test/config.ron");
190 let result = explain(&config, Some(&path), false);
191 assert_eq!(result, CONFIG);
192 }
193
194 #[test_log::test]
195 #[test_log(default_log_filter = "trace")]
196 fn test_explain_without_plugins() {
197 const CONFIG: &str = r"Use Super + Super_L to open the Overview. Use tab and grave / shift + tab to select a different window, press return to switch
198You can also use the arrow keys or Ctrl + vim keys to navigate the workspaces. Use Esc to close the overview.
199After opening the Overview the Launcher is available:
200 <No plugins enabled in launcher>
201
202Press Alt + tab and hold Alt to view recently used applications. Press tab and grave / shift + tab to select a different window, release Alt to close the window.
203";
204 let mut config = create_test_config();
205 config
206 .windows
207 .as_mut()
208 .expect("config option missing")
209 .overview
210 .as_mut()
211 .expect("config option missing")
212 .launcher
213 .plugins = Plugins {
214 applications: None,
215 terminal: None,
216 shell: None,
217 websearch: None,
218 calc: None,
219 path: None,
220 actions: None,
221 };
222 let result = explain(&config, None, false);
223 assert_eq!(result, CONFIG);
224 }
225}