28#define G_LOG_DOMAIN "Modes.Script"
91 G_GNUC_UNUSED
size_t length) {
92 gchar **extras = g_strsplit(buffer,
"\x1f", -1);
93 gchar **extra = extras;
94 for (; *extra != NULL && *(extra + 1) != NULL; extra += 2) {
96 gchar *value = *(extra + 1);
100 if (strcasecmp(key,
"icon") == 0) {
101 entry->
icon_name = g_strsplit(value,
",", -1);
103 }
else if (strcasecmp(key,
"display") == 0) {
105 }
else if (strcasecmp(key,
"meta") == 0) {
107 }
else if (strcasecmp(key,
"info") == 0) {
109 }
else if (strcasecmp(key,
"nonselectable") == 0) {
110 entry->
nonselectable = g_ascii_strcasecmp(value,
"true") == 0;
112 }
else if (strcasecmp(key,
"permanent") == 0) {
113 entry->
permanent = g_ascii_strcasecmp(value,
"true") == 0;
115 }
else if (strcasecmp(key,
"urgent") == 0) {
116 entry->
urgent = g_ascii_strcasecmp(value,
"true") == 0;
118 }
else if (strcasecmp(key,
"active") == 0) {
119 entry->
active = g_ascii_strcasecmp(value,
"true") == 0;
127 if (*extras != NULL) {
144 g_warning(
"Mode \"%s\" not found, please make sure it's enabled.\n", value);
150 ssize_t length_key = 0;
151 while (length_key < length && line[length_key] !=
'\x1f') {
155 if ((length_key + 1) < length) {
156 line[length_key] =
'\0';
157 char *value = line + length_key + 1;
158 if (strcasecmp(line,
"message") == 0) {
160 pd->
message = strlen(value) ? g_strdup(value) : NULL;
161 }
else if (strcasecmp(line,
"prompt") == 0) {
163 pd->
prompt = g_strdup(value);
165 }
else if (strcasecmp(line,
"markup-rows") == 0) {
166 pd->
do_markup = (strcasecmp(value,
"true") == 0);
167 }
else if (strcasecmp(line,
"urgent") == 0) {
169 }
else if (strcasecmp(line,
"active") == 0) {
171 }
else if (strcasecmp(line,
"delim") == 0) {
173 }
else if (strcasecmp(line,
"no-custom") == 0) {
174 pd->
no_custom = (strcasecmp(value,
"true") == 0);
175 }
else if (strcasecmp(line,
"use-hot-keys") == 0) {
177 }
else if (strcasecmp(line,
"keep-selection") == 0) {
179 }
else if (strcasecmp(line,
"keep-filter") == 0) {
180 pd->
keep_filter = (strcasecmp(value,
"true") == 0);
181 }
else if (strcasecmp(line,
"new-selection") == 0) {
182 pd->
new_selection = (int64_t)g_ascii_strtoll(value, NULL, 0);
183 }
else if (strcasecmp(line,
"data") == 0) {
185 pd->
data = g_strdup(value);
186 }
else if (strcasecmp(line,
"theme") == 0) {
188 g_warning(
"Failed to parse: '%s'", value);
191 }
else if (strcasecmp(line,
"switch-mode") == 0) {
198 unsigned int *length,
int value,
203 GError *error = NULL;
213 char **env = g_get_environ();
215 char *str_value = g_strdup_printf(
"%d", value);
216 env = g_environ_setenv(env,
"ROFI_RETV", str_value, TRUE);
219 str_value = g_strdup_printf(
"%d", (
int)getpid());
220 env = g_environ_setenv(env,
"ROFI_OUTSIDE", str_value, TRUE);
223 if (entry && entry->
info) {
224 env = g_environ_setenv(env,
"ROFI_INFO", entry->
info, TRUE);
227 env = g_environ_setenv(env,
"ROFI_DATA", pd->
data, TRUE);
231 env = g_environ_setenv(env,
"ROFI_INPUT", input, TRUE);
234 if (g_shell_parse_argv(sw->
ed, &argc, &argv, &error)) {
235 argv = g_realloc(argv, (argc + 2) *
sizeof(
char *));
236 argv[argc] = g_strdup(arg);
237 argv[argc + 1] = NULL;
238 g_spawn_async_with_pipes(NULL, argv, env, G_SPAWN_SEARCH_PATH, NULL, NULL,
239 NULL, NULL, &fd, NULL, &error);
243 char *msg = g_strdup_printf(
"Failed to execute: '%s'\nError: '%s'",
244 (
char *)sw->
ed, error->message);
252 FILE *inp = fdopen(fd,
"r");
255 size_t buffer_length = 0;
256 ssize_t read_length = 0;
257 size_t actual_size = 0;
258 while ((read_length = getdelim(&buffer, &buffer_length, pd->
delim, inp)) >
261 if (buffer[read_length - 1] == pd->
delim) {
262 buffer[read_length - 1] =
'\0';
264 if (buffer[0] ==
'\0') {
267 if (actual_size < ((*length) + 2)) {
279 size_t buf_length = strlen(buffer);
282 retv[(*length)].
display = NULL;
283 retv[(*length)].
meta = NULL;
284 retv[(*length)].
info = NULL;
285 retv[(*length)].
active = FALSE;
286 retv[(*length)].
urgent = FALSE;
298 if (buf_length > 0 && (read_length > (ssize_t)buf_length)) {
301 read_length - buf_length);
311 if (fclose(inp) != 0) {
312 g_warning(
"Failed to close stdout off executor script: '%s'",
359 unsigned int length) {
360 for (
unsigned int i = 0; i < length; i++) {
361 g_free(list[i].entry);
363 g_free(list[i].display);
364 g_free(list[i].meta);
365 g_free(list[i].info);
370 unsigned int selected_line) {
374 unsigned int new_length = 0;
382 if (selected_line != UINT32_MAX) {
385 &(rmpd->
cmd_list[selected_line]), *input);
403 3, &(rmpd->
cmd_list[selected_line]), *input);
411 1, &(rmpd->
cmd_list[selected_line]), *input);
431 if (new_list != NULL) {
435 if (keep_selection) {
446 if (keep_filter == FALSE) {
468static inline unsigned int get_index(
unsigned int length,
int index) {
472 if (((
unsigned int)-index) <= length) {
473 return length + index;
479 G_GNUC_UNUSED
int *state,
480 G_GNUC_UNUSED GList **list,
int get_entry) {
486 if (selected_line >=
start && selected_line <=
stop) {
494 if (selected_line >=
start && selected_line <=
stop) {
508 return get_entry ? g_strdup(pd->
cmd_list[selected_line].
display) : NULL;
510 return get_entry ? g_strdup(pd->
cmd_list[selected_line].
entry) : NULL;
515 unsigned int index) {
526 pango_parse_markup(rmpd->
cmd_list[index].
entry, -1, 0, NULL, &esc, NULL,
534 for (
int j = 0; match && tokens[j] != NULL; j++) {
538 if (test == tokens[j]->invert && rmpd->
cmd_list[index].
meta) {
559 unsigned int selected_line,
560 unsigned int height) {
566 g_return_val_if_fail(pd->
cmd_list != NULL, NULL);
574 cairo_surface_t *surface = NULL;
577 gboolean query_done =
580 if (surface != NULL) {
582 }
else if (query_done) {
590 char *current_icon = NULL;
592 int icon_count = g_strv_length(dr->
icon_name);
636 const char *cpath = g_get_user_config_dir();
637 char *script_dir = g_build_filename(cpath,
"rofi",
"scripts", NULL);
638 if (g_file_test(script_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) ==
643 GDir *sd = g_dir_open(script_dir, 0, NULL);
645 const char *file = NULL;
646 while ((file = g_dir_read_name(sd)) != NULL) {
647 char *sp = g_build_filename(cpath,
"rofi",
"scripts", file, NULL);
677 Mode *sw = g_malloc0(
sizeof(*sw));
693 Mode *sw = g_malloc0(
sizeof(*sw));
694 unsigned int index = 0;
695 const char *
const sep =
":";
696 char **tokens = g_strsplit(str, sep, 2);
698 index = g_strv_length(tokens);
699 sw->
name = g_strdup(tokens[0]);
720 "The script command '%s' has %u options, but needs 2: <name>:<script>.",
730 return strchr(token,
':') != NULL;
736 printf(
" • %s%s%s (%s)\n", is_term ? (
color_bold) :
"",
guint display_scale(void)
const char * icon_name[NUM_FILE_TYPES]
void parse_ranges(char *input, rofi_range_pair **list, unsigned int *length)
char helper_parse_char(const char *arg)
char * rofi_expand_path(const char *input)
int helper_token_match(rofi_int_matcher *const *tokens, const char *input)
char * rofi_force_utf8(const gchar *data, ssize_t length)
gboolean rofi_icon_fetcher_get_ex(const uint32_t uid, cairo_surface_t **surface)
uint32_t rofi_icon_fetcher_query(const char *name, const int size)
void * mode_get_private_data(const Mode *mode)
void rofi_clear_error_messages(void)
int mode_lookup(const char *name)
void script_mode_gather_user_scripts(void)
gboolean script_mode_is_valid(const char *token)
void script_user_list(gboolean is_term)
void script_mode_cleanup(void)
Mode * script_mode_parse_setup(const char *str)
int rofi_view_error_dialog(const char *msg, int markup)
RofiViewState * rofi_view_get_active(void)
void rofi_view_set_selected_line(RofiViewState *state, unsigned int selected_line)
struct rofi_int_matcher_t rofi_int_matcher
static void script_mode_destroy(Mode *sw)
static void script_switcher_free(Mode *sw)
static void parse_header_entry(Mode *sw, char *line, ssize_t length)
static DmenuScriptEntry * execute_executor(Mode *sw, char *arg, unsigned int *length, int value, DmenuScriptEntry *entry, char *input)
static ModeMode script_mode_result(Mode *sw, int mretv, char **input, unsigned int selected_line)
static cairo_surface_t * script_get_icon(const Mode *sw, unsigned int selected_line, unsigned int height)
void dmenuscript_parse_entry_extras(G_GNUC_UNUSED Mode *sw, DmenuScriptEntry *entry, char *buffer, G_GNUC_UNUSED size_t length)
static char * script_get_message(const Mode *sw)
ScriptUser * user_scripts
static int script_mode_has_user_script(char const *const user)
static void script_switch_mode(Mode *sw, char *value)
static void script_mode_free_entry_list(DmenuScriptEntry *list, unsigned int length)
static void script_mode_reset_highlight(Mode *sw)
static char * _get_display_value(const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **list, int get_entry)
static int script_mode_init(Mode *sw)
static int script_token_match(const Mode *sw, rofi_int_matcher **tokens, unsigned int index)
static unsigned int script_mode_get_num_entries(const Mode *sw)
struct rofi_range_pair * urgent_list
struct rofi_range_pair * active_list
unsigned int num_urgent_list
unsigned int cmd_list_length
unsigned int num_active_list
DmenuScriptEntry * cmd_list
__mode_get_num_entries _get_num_entries
_mode_preprocess_input _preprocess_input
_mode_token_match _token_match
_mode_get_display_value _get_display_value
_mode_get_completion _get_completion
_mode_get_message _get_message
gboolean rofi_theme_parse_string(const char *string)