rofi_plugin_sys/helper.rs
1//! Helper utilities.
2//!
3//! This corresponds to `helper.h`.
4
5use {
6 crate::{ConfigEntry, Property, PropertyType, RofiIntMatcher, RofiRangePair},
7 ::std::{
8 os::raw::{c_char, c_int, c_long, c_uint},
9 ptr::NonNull,
10 },
11};
12
13extern "C" {
14 /// Parses a string into arguments, replacing keys with values.
15 ///
16 /// Returns true if successful, false if it failed.
17 ///
18 /// - `string`: The input string.
19 /// - `output`: Pointer to 2-dimensional array with parsed string.
20 /// - `length`: Length of 2-dimensional array.
21 /// - `...`: Key, value parse. Replace the string key with value.
22 #[link_name = "helper_parse_setup"]
23 pub fn parse_setup(string: *mut c_char, output: *mut *mut *mut c_char, length: *mut c_int, ...);
24
25 /// Tokenize the string on spaces.
26 ///
27 /// Returns a newly allocated array of matching objects.
28 #[link_name = "helper_tokenize"]
29 pub fn tokenize(input: *const c_char, case_sensitive: c_int) -> *mut *mut RofiIntMatcher;
30
31 /// Frees the array of matching objects.
32 #[link_name = "helper_tokenize_free"]
33 pub fn tokenize_free(tokens: *mut *mut RofiIntMatcher);
34
35 /// Parse command line argument `key` to character.
36 /// This supports character escaping.
37 ///
38 /// Returns true if the key was found and `val` was set.
39 ///
40 /// - `key`: The key to search for.
41 /// - `val`: Pointer to the string to set to the key value (if found).
42 pub fn find_arg_char(key: *const c_char, val: *mut c_char) -> c_int;
43
44 /// Parse command line argument `key` to unsigned int.
45 ///
46 /// Returns true if key was found and `val` was set.
47 ///
48 /// - `key`: The key to search for.
49 /// - `val`: Pointer to the string to set to the key value (if found).
50 pub fn find_arg_uint(key: *const c_char, val: *mut c_uint) -> c_int;
51
52 /// Parse command line argument `key` to int.
53 ///
54 /// Returns true if key was found and `val` was set.
55 ///
56 /// - `key`: The key to search for.
57 /// - `val`: Pointer to the string to set to the key value (if found).
58 pub fn find_arg_int(key: *const c_char, val: *mut c_int) -> c_int;
59
60 /// Parse command line argument `key` to string.
61 ///
62 /// Returns true if key was found and `val` was set.
63 ///
64 /// - `key`: The key to search for.
65 /// - `val`: Pointer to the string to set to the key value (if found).
66 pub fn find_arg_str(key: *const c_char, val: *mut *mut c_char) -> c_int;
67
68 /// Parse all command line options `key` to string vector.
69 ///
70 /// Returns a string vector which the user must free.
71 pub fn find_arg_strv(key: *const c_char) -> *mut *const c_char;
72
73 /// Check if key is passed as argument.
74 ///
75 /// Returns position of string or -1 if not found.
76 pub fn find_arg(key: *const c_char) -> c_int;
77
78 /// Tokenized match, match tokens to line input.
79 ///
80 /// Returns true when matches, false otherwise.
81 ///
82 /// - `tokens`: List of input tokens to match.
83 /// - `input`: The entry to match against.
84 #[link_name = "helper_token_match"]
85 pub fn token_match(tokens: *const *mut RofiIntMatcher, input: *const c_char) -> c_int;
86
87 /// Execute cmd using `config.run_command` and outputs the result (stdout) to the opened file
88 /// descriptor.
89 ///
90 /// Returns a valid file descriptor on success, or -1 on failure.
91 pub fn execute_generator(cmd: *const c_char) -> c_int;
92
93 /// Returns file descriptor (or -1 when failed).
94 ///
95 /// - `pidfile`: The pidfile to create.
96 /// - `kill`: Try killing running instance.
97 pub fn create_pid_file(pidfile: *const c_char, kill: glib_sys::gboolean) -> c_int;
98
99 /// Remove pid file.
100 pub fn remove_pid_file(fd: c_int);
101
102 /// Do some input validation, especially the first few could break things. It is good to catch
103 /// them beforehand.
104 ///
105 /// This function exits the program with 1 when it finds an invalid configuration.
106 pub fn config_sanity_check() -> c_int;
107
108 /// Parses a string into a character.
109 #[link_name = "helper_parse_char"]
110 pub fn parse_char(arg: *const c_char) -> c_char;
111
112 /// Set the application arguments.
113 pub fn cmd_set_arguments(argc: c_int, argv: *mut *mut c_char);
114
115 /// Expand path, both `~` and `~<user>`.
116 #[link_name = "rofi_expand_path"]
117 pub fn expand_path(input: *const c_char) -> *const c_char;
118
119 /// UTF-8 aware levenshtein distance calculation.
120 ///
121 /// - `needle`: The string to match weight off
122 /// - `needlelen`: The length of the needle
123 /// - `haystack`: The string to match against
124 /// - `haystacklen`: The length of the haystack
125 pub fn levenshtein(
126 needle: *const c_char,
127 needlelen: c_long,
128 haystack: *const c_char,
129 haystacklen: c_long,
130 ) -> c_uint;
131
132 /// Convert string to valid UTF-8, replacing invalid parts with replacement character.
133 ///
134 /// - `data`: The unvalidated character array holding possible UTF-8 data
135 /// - `length`: The length of `data`
136 #[link_name = "rofi_force_utf8"]
137 pub fn force_utf8(data: *const c_char, length: isize) -> *const c_char;
138
139 /// Converts latin to UTF-8.
140 #[link_name = "rofi_latin_to_utf8_strdup"]
141 pub fn latin_to_utf8_strdup(input: *const c_char, length: isize) -> *const c_char;
142
143 /// Run Rofi's global sequence alignment algorithm to find the maximum accumulated score by
144 /// aligning `pattern` to `str`.
145 /// It applies when `pattern` is a subsequence of `str`.
146 ///
147 /// Scoring criteria
148 /// - Prefer matches at the start of a word, or the start of subwords in
149 /// CamelCase/camelCase/camel123 words. See WORD_START_SCORE/CAMEL_SCORE.
150 /// - Non-word characters matter. See NON_WORD_SCORE.
151 /// - The first characters of words of `pattern` receive bonus because they usually have more
152 /// significance than the rest. See PATTERN_START_MULTIPLIER/PATTERN_NON_START_MULTIPLIER.
153 /// - Superfluous characters in `str` will reduce the score (gap penalty). See GAP_SCORE.
154 /// - Prefer early occurrence of the first character. See LEADING_GAP_SCORE/GAP_SCORE.
155 ///
156 /// The recurrence of the dynamic programming:
157 /// - `dp[i][j]`: maximum accumulated score by aligning `pattern[0..i]` to `str[0..j]`
158 /// - `dp[0][j] = leading_gap_penalty(0, j) + score[j]`
159 /// - `dp[i][j] = max(dp[i-1][j-1] + CONSECUTIVE_SCORE, max(dp[i-1][k] + gap_penalty(k+1, j) + score[j] : k < j))`
160 ///
161 /// The first dimension can be suppressed since we do not need a matching scheme, which reduces
162 /// the space complexity from O(N*M) to O(M)
163 ///
164 /// Returns the sorting weight.
165 ///
166 /// - `pattern`: The user input to match against.
167 /// - `plen`: The length of `pattern`.
168 /// - `str`: The input to match against `pattern`.
169 /// - `slen`: Length of `str`.
170 #[link_name = "rofi_scorer_fuzzy_evaluate"]
171 pub fn scorer_fuzzy_evaluate(
172 pattern: *const c_char,
173 plen: c_long,
174 str: *const c_char,
175 slen: c_long,
176 ) -> c_int;
177
178 /// Compares the `G_NORMALIZE_ALL_COMPOSE` forms of the two strings.
179 ///
180 /// Returns less than, equal to, or greater than zero if the first `n` characters (not bytes) of
181 /// `a` are found, respectively, to be less than, to match, or be greater than the first `n`
182 /// characters (not bytes) of `b`.
183 ///
184 /// - `a`: First UTF-8 string to compare, non-null.
185 /// - `b`: Second UTF-8 string to compare, non-null.
186 /// - `n`: Maximum number of characters to compare.
187 pub fn utf8_strncmp(a: *const c_char, b: *const c_char, n: usize) -> c_int;
188}
189
190/// The startup notification context of the application to launch.
191#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
192#[repr(C)]
193pub struct RofiHelperExecuteContext {
194 /// The name of the application.
195 pub name: *const c_char,
196 /// The binary name of the application.
197 pub binary: *const c_char,
198 /// The description of the launch.
199 pub description: *const c_char,
200 /// The icon name of the application.
201 pub icon: *const c_char,
202 /// The application ID (desktop file with the `.desktop` suffix).
203 pub app_id: *const c_char,
204 /// The window manager class of the application.
205 pub wmclass: *const c_char,
206 /// The command we run.
207 pub command: *const c_char,
208}
209
210extern "C" {
211 /// Executes the comand.
212 ///
213 /// Returns true when successful, false otherwise.
214 ///
215 /// - `wd`: The working directory.
216 /// - `args`: The argments of the command to exec.
217 /// - `error_precmd`: Prefix to error message command.
218 /// - `error_cmd`: Error message command.
219 /// - `context`: The startup notification context, if any.
220 #[link_name = "helper_execute"]
221 pub fn execute(
222 wd: *const c_char,
223 args: *mut *mut c_char,
224 error_precmd: *const c_char,
225 error_cmd: *const c_char,
226 context: *mut RofiHelperExecuteContext,
227 ) -> glib_sys::gboolean;
228
229 /// Executes the comand.
230 /// If needed memebrs of `context` are null, they will be filled.
231 ///
232 /// Returns true when successful, false otherwise.
233 ///
234 /// - `wd`: The working directory (optional).
235 /// - `cmd`: The command to execute.
236 /// - `run_in_term`: Indicates if the command should be run in a terminal.
237 /// - `context`: The startup notification context, if any.
238 #[link_name = "helper_execute_command"]
239 pub fn execute_command(
240 wd: *const c_char,
241 cmd: *const c_char,
242 run_in_term: glib_sys::gboolean,
243 context: *mut RofiHelperExecuteContext,
244 ) -> glib_sys::gboolean;
245
246 /// Get a cairo surface from an SVG path.
247 ///
248 /// - `param`: The file path.
249 /// - `height`: The wanted height.
250 pub fn cairo_image_surface_create_from_svg(
251 file: *const c_char,
252 height: c_int,
253 ) -> *mut cairo_sys::cairo_surface_t;
254
255 /// Parse ranges.
256 ///
257 /// - `input`: String to parse.
258 /// - `list`: List of ranges.
259 /// - `length`: Length of list.
260 pub fn parse_ranges(input: *mut c_char, list: *mut *mut RofiRangePair, length: *mut c_uint);
261
262 /// This functions outputs the formatted string to stdout, appends a newline (`\n`)
263 /// character and calls flush on the file descriptor.
264 ///
265 /// - `format`: The format string used. See below for possible syntax.
266 /// - `string`: The selected entry.
267 /// - `selected_line`: The selected line index.
268 /// - `filter`: The entered filter.
269 ///
270 /// Currently the following formats are supported:
271 /// - i: Print the index (0-(N-1))
272 /// - d: Print the index (1-N)
273 /// - s: Print input string.
274 /// - q: Print quoted input string.
275 /// - f: Print the entered filter.
276 /// - F: Print the entered filter, quoted
277 #[link_name = "rofi_output_formatted_line"]
278 pub fn output_formatted_line(
279 format: *const c_char,
280 string: *const c_char,
281 selected_line: c_int,
282 filter: *const c_char,
283 );
284
285 /// Items {key} are replaced by the value if `{key}` is passed as key/value pair, otherwise
286 /// removed from string. If the {key} is in between [] all the text between [] are removed if
287 /// {key} is not found. Otherwise key is replaced and [ & ] removed.
288 ///
289 /// This allows for optional replacement, e.g. `{ssh-client} [-t {title}] -e "{cmd}"` the `-t
290 /// {title}` is only there if {title} is set.
291 ///
292 /// Returns a new string with the keys replaced.
293 ///
294 /// - `string`: The string with elements to be replaced.
295 /// - `...`: Set of {key}, value that will be replaced, terminated by a null.
296 #[link_name = "helper_string_replace_if_exists"]
297 pub fn string_replace_if_exists(string: *mut c_char, ...) -> *mut c_char;
298
299 /// Returns path to theme or copy of filename if not found.
300 ///
301 /// - `file`: File name passed to option.
302 /// - `ext`: null-terminated array of file extensions.
303 /// - `parent_dir`: the file that was used to import this file, or NULL.
304 #[link_name = "helper_get_theme_path"]
305 pub fn get_theme_path(
306 file: NonNull<c_char>,
307 ext: NonNull<*const c_char>,
308 parent_dir: *const c_char,
309 ) -> *mut c_char;
310
311 /// Find the configuration element.
312 /// If not exact, the closest specified element is returned.
313 /// Returns the [`ThemeWidget`](crate::ThemeWidget) if found, otherwise null.
314 ///
315 /// - `name`: The name of the element to find.
316 /// - `state`: The state of the element.
317 /// - `exact`: If the match should be exact, or the parent can be included.
318 #[link_name = "rofi_config_find_widget"]
319 pub fn config_find_widget(
320 name: *const c_char,
321 state: *const c_char,
322 exact: glib_sys::gboolean,
323 ) -> *mut ConfigEntry;
324
325 /// Find the property on the widget.
326 /// If not exact, the parents are searched recursively until match is found.
327 /// Returns the [`Property`] if found, otherwise null.
328 ///
329 /// - `widget`: The widget to find the property on.
330 /// - `type`: The [`PropertyType`] to find.
331 /// - `property`: The property to find.
332 /// - `exact`: If the property should only be found on this widget, or on parents if not found.
333 #[link_name = "rofi_theme_find_property"]
334 pub fn theme_find_property(
335 widget: *mut ConfigEntry,
336 r#type: PropertyType,
337 property: *const c_char,
338 exact: glib_sys::gboolean,
339 ) -> *mut Property;
340}