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            // TODO add action explain
63            // if overview.launcher.plugins.actions.is_some() {
64            //     let _ = builder.write_str(
65            //         "\t- Type Reboot/Shutdown/etc. to perform system actions. Type `actions` to see all available ones \n",
66            //     );
67            // }
68        } else {
69            let _ = builder.write_str(&format!("{italic}<Overview move disabled>{reset}\n"));
70        }
71    }
72
73    builder.push('\n');
74
75    if let Some(windows) = &config.windows {
76        if let Some(switch) = &windows.switch {
77            let _ = builder.write_str(&format!(
78                "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",
79                switch.modifier,
80                switch.modifier,
81                switch.modifier,
82            ));
83        } else {
84            let _ = builder.write_str(&format!("{italic}<Switch mode disabled>{reset}\n"));
85        }
86    }
87
88    builder
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94    use crate::structs::*;
95    use std::path::PathBuf;
96
97    fn create_test_config() -> Config {
98        Config {
99            windows: Some(Windows {
100                overview: Some(Overview::default()),
101                switch: Some(Switch::default()),
102                ..Default::default()
103            }),
104            ..Default::default()
105        }
106    }
107
108    #[test]
109    fn test_explain_with_overview() {
110        const CONFIG: &str = r"Config is valid (/test/config.ron)
111Explanation (blue are keys, bold blue keys can be configured in config):
112Use Super + super_l to open the Overview. Use tab and grave / shift + tab to select a different window, press return to switch
113You can also use the arrow keys to navigate the workspaces. Use Esc to close the overview.
114After opening the Overview the Launcher is available:
115	- 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.
116	- Press Ctrl + t to run the typed command in a terminal.
117	- Press Ctrl + <key> to search the typed text in any of the configured SearchEngines: Google, Wikipedia.
118	- Typing a mathematical expression will calculate it and display the result in the launcher.
119	- Paths (starting with ~ or /) can be open in default file-manager.
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
157<Switch mode disabled>
158";
159        let mut config = create_test_config();
160        config.windows.as_mut().unwrap().switch = None;
161        let path = PathBuf::from("/test/config.ron");
162        let result = explain(&config, &path, false);
163        assert_eq!(result, CONFIG);
164    }
165
166    #[test]
167    fn test_explain_without_plugins() {
168        const CONFIG: &str = r"Config is valid (/test/config.ron)
169Explanation (blue are keys, bold blue keys can be configured in config):
170Use Super + super_l to open the Overview. Use tab and grave / shift + tab to select a different window, press return to switch
171You can also use the arrow keys to navigate the workspaces. Use Esc to close the overview.
172After opening the Overview the Launcher is available:
173
174Press 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.
175";
176        let mut config = create_test_config();
177        config
178            .windows
179            .as_mut()
180            .unwrap()
181            .overview
182            .as_mut()
183            .unwrap()
184            .launcher
185            .plugins = Plugins {
186            applications: None,
187            terminal: None,
188            shell: None,
189            websearch: None,
190            calc: None,
191            path: None,
192        };
193        let path = PathBuf::from("/test/config.ron");
194        let result = explain(&config, &path, false);
195        assert_eq!(result, CONFIG);
196    }
197}