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}