hyprshell_config_lib/
explain.rs

1use 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_path: &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 config_path_display = config_path.display();
20    let mut builder = format!(
21        "{bold}{green}Config is valid{reset} ({config_path_display})\n{bold}Explanation{reset} ({blue}blue{reset} are keys, {bold}{blue}bold blue{reset} keys can be configured in config):{reset}\n",
22    );
23
24    if let Some(windows) = &config.windows {
25        if let Some(overview) = &windows.overview {
26            let _ = builder.write_str(&format!(
27                "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\
28                You can also use the {blue}arrow keys{reset} to navigate the workspaces. Use {blue}Esc{reset} to close the overview.\n",
29                overview.modifier,
30                overview.key,
31            ));
32            let _ = builder.write_str(&format!(
33                "After opening the Overview the {bold}Launcher{reset} is available:\n"
34            ));
35            if let Some(_applications) = overview.launcher.plugins.applications.as_ref() {
36                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"));
37            }
38            if overview.launcher.plugins.terminal.is_some() {
39                let _ = builder.write_str(&format!(
40                    "\t- Press {blue}Ctrl{reset} + {blue}t{reset} to run the typed command in a terminal.\n"
41                ));
42            }
43            if overview.launcher.plugins.shell.is_some() {
44                let _ = builder.write_str(&format!(
45                    "\t- Press {blue}Ctrl{reset} + {blue}r{reset} to run the typed command in the background.\n",
46                ));
47            }
48            if let Some(engines) = &overview.launcher.plugins.websearch {
49                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",
50                                                      engines.engines.iter().map(|e| e.name.to_string()).collect::<Vec<_>>().join(", ")));
51            }
52            if overview.launcher.plugins.calc.is_some() {
53                let _ =   builder.write_str(
54                    "\t- Typing a mathematical expression will calculate it and display the result in the launcher.\n",
55                );
56            }
57            if overview.launcher.plugins.path.is_some() {
58                let _ = builder.write_str(
59                    "\t- Paths (starting with ~ or /) can be open in default file-manager.\n",
60                );
61            }
62            if overview.launcher.plugins.actions.is_some() {
63                let _ = builder.write_str(
64                    "\t- Type Reboot/Shutdown/etc. to run corresponding commands. Type `actions` to see all available ones.\n",
65                );
66            }
67        } else {
68            let _ = builder.write_str(&format!("{italic}<Overview move disabled>{reset}\n"));
69        }
70    }
71
72    builder.push('\n');
73
74    if let Some(windows) = &config.windows {
75        if let Some(switch) = &windows.switch {
76            let _ = builder.write_str(&format!(
77                "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",
78                switch.modifier,
79                switch.modifier,
80                switch.modifier,
81            ));
82        } else {
83            let _ = builder.write_str(&format!("{italic}<Switch mode disabled>{reset}\n"));
84        }
85    }
86
87    builder
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93    use crate::structs::*;
94    use std::path::PathBuf;
95
96    fn create_test_config() -> Config {
97        Config {
98            windows: Some(Windows {
99                overview: Some(Overview::default()),
100                switch: Some(Switch::default()),
101                ..Default::default()
102            }),
103            ..Default::default()
104        }
105    }
106
107    #[test]
108    fn test_explain_with_overview() {
109        const CONFIG: &str = r"Config is valid (/test/config.ron)
110Explanation (blue are keys, bold blue keys can be configured in config):
111Use Super + super_l to open the Overview. Use tab and grave / shift + tab to select a different window, press return to switch
112You can also use the arrow keys to navigate the workspaces. Use Esc to close the overview.
113After opening the Overview the Launcher is available:
114	- 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.
115	- Press Ctrl + t to run the typed command in a terminal.
116	- Press Ctrl + <key> to search the typed text in any of the configured SearchEngines: Google, Wikipedia.
117	- Typing a mathematical expression will calculate it and display the result in the launcher.
118	- Paths (starting with ~ or /) can be open in default file-manager.
119	- Type Reboot/Shutdown/etc. to run corresponding commands. Type `actions` to see all available ones.
120
121Press 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.
122";
123        let config = create_test_config();
124        let path = PathBuf::from("/test/config.ron");
125        let result = explain(&config, &path, false);
126        assert_eq!(result, CONFIG);
127    }
128
129    #[test]
130    fn test_explain_without_overview() {
131        const CONFIG: &str = r"Config is valid (/test/config.ron)
132Explanation (blue are keys, bold blue keys can be configured in config):
133<Overview move disabled>
134
135Press 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.
136";
137        let mut config = create_test_config();
138        config.windows.as_mut().unwrap().overview = None;
139        let path = PathBuf::from("/test/config.ron");
140        let result = explain(&config, &path, false);
141        assert_eq!(result, CONFIG);
142    }
143
144    #[test]
145    fn test_explain_without_switch() {
146        const CONFIG: &str = r"Config is valid (/test/config.ron)
147Explanation (blue are keys, bold blue keys can be configured in config):
148Use Super + super_l to open the Overview. Use tab and grave / shift + tab to select a different window, press return to switch
149You can also use the arrow keys to navigate the workspaces. Use Esc to close the overview.
150After opening the Overview the Launcher is available:
151	- 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.
152	- Press Ctrl + t to run the typed command in a terminal.
153	- Press Ctrl + <key> to search the typed text in any of the configured SearchEngines: Google, Wikipedia.
154	- Typing a mathematical expression will calculate it and display the result in the launcher.
155	- Paths (starting with ~ or /) can be open in default file-manager.
156	- Type Reboot/Shutdown/etc. to run corresponding commands. Type `actions` to see all available ones.
157
158<Switch mode disabled>
159";
160        let mut config = create_test_config();
161        config.windows.as_mut().unwrap().switch = None;
162        let path = PathBuf::from("/test/config.ron");
163        let result = explain(&config, &path, false);
164        assert_eq!(result, CONFIG);
165    }
166
167    #[test]
168    fn test_explain_without_plugins() {
169        const CONFIG: &str = r"Config is valid (/test/config.ron)
170Explanation (blue are keys, bold blue keys can be configured in config):
171Use Super + super_l to open the Overview. Use tab and grave / shift + tab to select a different window, press return to switch
172You can also use the arrow keys to navigate the workspaces. Use Esc to close the overview.
173After opening the Overview the Launcher is available:
174
175Press 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.
176";
177        let mut config = create_test_config();
178        config
179            .windows
180            .as_mut()
181            .unwrap()
182            .overview
183            .as_mut()
184            .unwrap()
185            .launcher
186            .plugins = Plugins {
187            applications: None,
188            terminal: None,
189            shell: None,
190            websearch: None,
191            calc: None,
192            path: None,
193            actions: None,
194        };
195        let path = PathBuf::from("/test/config.ron");
196        let result = explain(&config, &path, false);
197        assert_eq!(result, CONFIG);
198    }
199}