Skip to main content

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    /// - `case_sensitive`: Whether case is significant.
126    pub fn levenshtein(
127        needle: *const c_char,
128        needlelen: c_long,
129        haystack: *const c_char,
130        haystacklen: c_long,
131        case_sensitive: c_int,
132    ) -> c_uint;
133
134    /// Convert string to valid UTF-8, replacing invalid parts with replacement character.
135    ///
136    /// - `data`: The unvalidated character array holding possible UTF-8 data
137    /// - `length`: The length of `data`
138    #[link_name = "rofi_force_utf8"]
139    pub fn force_utf8(data: *const c_char, length: isize) -> *const c_char;
140
141    /// Converts latin to UTF-8.
142    #[link_name = "rofi_latin_to_utf8_strdup"]
143    pub fn latin_to_utf8_strdup(input: *const c_char, length: isize) -> *const c_char;
144
145    /// Run Rofi's global sequence alignment algorithm to find the maximum accumulated score by
146    /// aligning `pattern` to `str`.
147    /// It applies when `pattern` is a subsequence of `str`.
148    ///
149    ///  Scoring criteria
150    ///  - Prefer matches at the start of a word, or the start of subwords in
151    ///    CamelCase/camelCase/camel123 words. See WORD_START_SCORE/CAMEL_SCORE.
152    ///  - Non-word characters matter. See NON_WORD_SCORE.
153    ///  - The first characters of words of `pattern` receive bonus because they usually have more
154    ///    significance than the rest. See PATTERN_START_MULTIPLIER/PATTERN_NON_START_MULTIPLIER.
155    ///  - Superfluous characters in `str` will reduce the score (gap penalty). See GAP_SCORE.
156    ///  - Prefer early occurrence of the first character. See LEADING_GAP_SCORE/GAP_SCORE.
157    ///
158    ///  The recurrence of the dynamic programming:
159    ///  - `dp[i][j]`: maximum accumulated score by aligning `pattern[0..i]` to `str[0..j]`
160    ///  - `dp[0][j] = leading_gap_penalty(0, j) + score[j]`
161    ///  - `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))`
162    ///
163    /// The first dimension can be suppressed since we do not need a matching scheme, which reduces
164    /// the space complexity from O(N*M) to O(M)
165    ///
166    /// Returns the sorting weight.
167    ///
168    /// - `pattern`: The user input to match against.
169    /// - `plen`: The length of `pattern`.
170    /// - `str`: The input to match against `pattern`.
171    /// - `slen`: Length of `str`.
172    /// - `case_sensitive`: Whether case is significant.
173    #[link_name = "rofi_scorer_fuzzy_evaluate"]
174    pub fn scorer_fuzzy_evaluate(
175        pattern: *const c_char,
176        plen: c_long,
177        str: *const c_char,
178        slen: c_long,
179        case_sensitive: c_int,
180    ) -> c_int;
181
182    /// Compares the `G_NORMALIZE_ALL_COMPOSE` forms of the two strings.
183    ///
184    /// Returns less than, equal to, or greater than zero if the first `n` characters (not bytes) of
185    /// `a` are found, respectively, to be less than, to match, or be greater than the first `n`
186    /// characters (not bytes) of `b`.
187    ///
188    /// - `a`: First UTF-8 string to compare, non-null.
189    /// - `b`: Second UTF-8 string to compare, non-null.
190    /// - `n`: Maximum number of characters to compare.
191    pub fn utf8_strncmp(a: *const c_char, b: *const c_char, n: usize) -> c_int;
192}
193
194/// The startup notification context of the application to launch.
195#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
196#[repr(C)]
197pub struct RofiHelperExecuteContext {
198    /// The name of the application.
199    pub name: *const c_char,
200    /// The binary name of the application.
201    pub binary: *const c_char,
202    /// The description of the launch.
203    pub description: *const c_char,
204    /// The icon name of the application.
205    pub icon: *const c_char,
206    /// The application ID (desktop file with the `.desktop` suffix).
207    pub app_id: *const c_char,
208    /// The window manager class of the application.
209    pub wmclass: *const c_char,
210    /// The command we run.
211    pub command: *const c_char,
212}
213
214extern "C" {
215    /// Executes the comand.
216    ///
217    /// Returns true when successful, false otherwise.
218    ///
219    /// - `wd`: The working directory.
220    /// - `args`: The argments of the command to exec.
221    /// - `error_precmd`: Prefix to error message command.
222    /// - `error_cmd`: Error message command.
223    /// - `context`: The startup notification context, if any.
224    #[link_name = "helper_execute"]
225    pub fn execute(
226        wd: *const c_char,
227        args: *mut *mut c_char,
228        error_precmd: *const c_char,
229        error_cmd: *const c_char,
230        context: *mut RofiHelperExecuteContext,
231    ) -> glib_sys::gboolean;
232
233    /// Executes the comand.
234    /// If needed memebrs of `context` are null, they will be filled.
235    ///
236    /// Returns true when successful, false otherwise.
237    ///
238    /// - `wd`: The working directory (optional).
239    /// - `cmd`: The command to execute.
240    /// - `run_in_term`: Indicates if the command should be run in a terminal.
241    /// - `context`: The startup notification context, if any.
242    #[link_name = "helper_execute_command"]
243    pub fn execute_command(
244        wd: *const c_char,
245        cmd: *const c_char,
246        run_in_term: glib_sys::gboolean,
247        context: *mut RofiHelperExecuteContext,
248    ) -> glib_sys::gboolean;
249
250    /// Get a cairo surface from an SVG path.
251    ///
252    /// - `param`: The file path.
253    /// - `height`: The wanted height.
254    pub fn cairo_image_surface_create_from_svg(
255        file: *const c_char,
256        height: c_int,
257    ) -> *mut cairo_sys::cairo_surface_t;
258
259    /// Parse ranges.
260    ///
261    /// - `input`: String to parse.
262    /// - `list`: List of ranges.
263    /// - `length`: Length of list.
264    pub fn parse_ranges(input: *mut c_char, list: *mut *mut RofiRangePair, length: *mut c_uint);
265
266    /// Get whether string matching should be case sensitive or insensitive.
267    ///
268    /// - `input`: String to parse.
269    pub fn parse_case_sensitivity(input: *const c_char) -> c_int;
270
271    /// This functions outputs the formatted string to stdout, appends a newline (`\n`)
272    /// character and calls flush on the file descriptor.
273    ///
274    /// - `format`: The format string used. See below for possible syntax.
275    /// - `string`: The selected entry.
276    /// - `selected_line`: The selected line index.
277    /// - `filter`: The entered filter.
278    ///
279    /// Currently the following formats are supported:
280    /// - i: Print the index (0-(N-1))
281    /// - d: Print the index (1-N)
282    /// - s: Print input string.
283    /// - q: Print quoted input string.
284    /// - f: Print the entered filter.
285    /// - F: Print the entered filter, quoted
286    #[link_name = "rofi_output_formatted_line"]
287    pub fn output_formatted_line(
288        format: *const c_char,
289        string: *const c_char,
290        selected_line: c_int,
291        filter: *const c_char,
292    );
293
294    /// Items {key} are replaced by the value if `{key}` is passed as key/value pair, otherwise
295    /// removed from string. If the {key} is in between [] all the text between [] are removed if
296    /// {key} is not found. Otherwise key is replaced and [ & ] removed.
297    ///
298    /// This allows for optional replacement, e.g. `{ssh-client} [-t {title}] -e "{cmd}"` the `-t
299    /// {title}` is only there if {title} is set.
300    ///
301    /// Returns a new string with the keys replaced.
302    ///
303    /// - `string`: The string with elements to be replaced.
304    /// - `...`: Set of {key}, value that will be replaced, terminated by a null.
305    #[link_name = "helper_string_replace_if_exists"]
306    pub fn string_replace_if_exists(string: *mut c_char, ...) -> *mut c_char;
307
308    /// Returns path to theme or copy of filename if not found.
309    ///
310    /// - `file`: File name passed to option.
311    /// - `ext`: null-terminated array of file extensions.
312    /// - `parent_dir`: the file that was used to import this file, or NULL.
313    #[link_name = "helper_get_theme_path"]
314    pub fn get_theme_path(
315        file: NonNull<c_char>,
316        ext: NonNull<*const c_char>,
317        parent_dir: *const c_char,
318    ) -> *mut c_char;
319
320    /// Find the configuration element.
321    /// If not exact, the closest specified element is returned.
322    /// Returns the [`ThemeWidget`](crate::ThemeWidget) if found, otherwise null.
323    ///
324    /// - `name`: The name of the element to find.
325    /// - `state`: The state of the element.
326    /// - `exact`: If the match should be exact, or the parent can be included.
327    #[link_name = "rofi_config_find_widget"]
328    pub fn config_find_widget(
329        name: *const c_char,
330        state: *const c_char,
331        exact: glib_sys::gboolean,
332    ) -> *mut ConfigEntry;
333
334    /// Find the property on the widget.
335    /// If not exact, the parents are searched recursively until match is found.
336    /// Returns the [`Property`] if found, otherwise null.
337    ///
338    /// - `widget`: The widget to find the property on.
339    /// - `type`: The [`PropertyType`] to find.
340    /// - `property`: The property to find.
341    /// - `exact`: If the property should only be found on this widget, or on parents if not found.
342    #[link_name = "rofi_theme_find_property"]
343    pub fn theme_find_property(
344        widget: *mut ConfigEntry,
345        r#type: PropertyType,
346        property: *const c_char,
347        exact: glib_sys::gboolean,
348    ) -> *mut Property;
349
350    /// Get a human-readable string with the current matching method.
351    pub fn helper_get_matching_mode_str() -> *const c_char;
352
353    /// Switch to the next matching method.
354    pub fn helper_select_next_matching_mode();
355
356    /// Switch to the previous matching method.
357    pub fn helper_select_previous_matching_mode();
358}