34#define G_LOG_DOMAIN "Modes.Run"
64#define RUN_CACHE_FILE "rofi-4.runcache"
104static gboolean
exec_cmd(
const char *cmd,
int run_in_term,
const char *orig) {
105 GError *error = NULL;
106 if (!cmd || !cmd[0]) {
109 gsize lf_cmd_size = 0;
110 gchar *lf_cmd = g_locale_from_utf8(cmd, -1, NULL, &lf_cmd_size, &error);
112 g_warning(
"Failed to convert command to locale encoding: %s",
120 char *hist = g_strdup_printf(
"%s\x1f%s", orig, cmd);
123 run_in_term ? &context : NULL)) {
150 char *hist = g_strdup_printf(
"%s\x1f%s", cmd->
entry, cmd->
exec);
166static int sort_func(
const void *a,
const void *b, G_GNUC_UNUSED
void *data) {
170 if (astr->
entry == NULL && bstr->
entry == NULL) {
173 if (astr->
entry == NULL) {
176 if (bstr->
entry == NULL) {
186 unsigned int num_favorites) {
189 FILE *inp = fdopen(fd,
"r");
192 size_t buffer_length = 0;
194 while (getline(&buffer, &buffer_length, inp) > 0) {
197 if (buffer[strlen(buffer) - 1] ==
'\n') {
198 buffer[strlen(buffer) - 1] =
'\0';
203 for (
unsigned int j = 0; found == 0 && j < num_favorites; j++) {
204 if (strcasecmp(buffer, retv[j].entry) == 0) {
214 retv = g_realloc(retv, ((*length) + 2) *
sizeof(
RunEntry));
215 retv[(*length)].
entry = g_strdup(buffer);
216 retv[(*length)].
exec = g_shell_quote(buffer);
218 retv[(*length)].
icon = NULL;
224 if (buffer != NULL) {
227 if (fclose(inp) != 0) {
228 g_warning(
"Failed to close stdout off executor script: '%s'",
233 retv[(*length)].
entry = NULL;
234 retv[(*length)].
exec = NULL;
236 retv[(*length)].
icon = NULL;
246 GError *error = NULL;
248 unsigned int num_favorites = 0;
251 if (g_getenv(
"PATH") == NULL) {
258 for (
unsigned int i = 0; i < *length; i++) {
259 gchar **rs = g_strsplit(hretv[i],
"\x1f", 2);
260 retv[i].
entry = rs[0];
261 retv[i].
exec = rs[1];
262 if (retv[i].exec == NULL) {
263 retv[i].
exec = g_strdup(rs[0]);
271 num_favorites = (*length);
273 path = g_strdup(g_getenv(
"PATH"));
276 gchar *homedir = g_locale_to_utf8(g_get_home_dir(), -1, NULL, &l, &error);
278 g_debug(
"Failed to convert homedir to UTF-8: %s", error->message);
279 for (
unsigned int i = 0; retv[i].
entry != NULL; i++) {
280 g_free(retv[i].entry);
281 g_free(retv[i].exec);
284 g_clear_error(&error);
289 const char *
const sep =
":";
290 char *strtok_savepointer = NULL;
291 for (
const char *dirname = strtok_r(path, sep, &strtok_savepointer);
292 dirname != NULL; dirname = strtok_r(NULL, sep, &strtok_savepointer)) {
294 DIR *dir = opendir(fpath);
295 g_debug(
"Checking path %s for executable.", fpath);
301 gchar *dirn = g_locale_to_utf8(dirname, -1, NULL, &dirn_len, &error);
303 g_debug(
"Failed to convert directory name to UTF-8: %s",
305 g_clear_error(&error);
309 gboolean is_homedir = g_str_has_prefix(dirn, homedir);
312 while ((dent = readdir(dir)) != NULL) {
313 if (dent->d_type != DT_REG && dent->d_type != DT_LNK &&
314 dent->d_type != DT_UNKNOWN) {
318 if (dent->d_name[0] ==
'.') {
322 gchar *full_path = g_build_filename(dirname, dent->d_name, NULL);
323 gboolean b = g_file_test(full_path, G_FILE_TEST_IS_EXECUTABLE);
332 g_filename_to_utf8(dent->d_name, -1, NULL, &name_len, &error);
334 g_debug(
"Failed to convert filename to UTF-8: %s", error->message);
335 g_clear_error(&error);
342 for (
unsigned int j = 0; found == 0 && j < num_favorites; j++) {
343 if (g_strcmp0(name, retv[j].entry) == 0) {
353 retv = g_realloc(retv, ((*length) + 2) *
sizeof(
RunEntry));
354 retv[(*length)].
entry = name;
355 retv[(*length)].
exec = g_shell_quote(name);
357 retv[(*length)].
icon = NULL;
360 retv[(*length) + 1].
entry = NULL;
361 retv[(*length) + 1].
exec = NULL;
363 retv[(*length) + 1].
icon = NULL;
375 if (
config.run_list_command != NULL &&
config.run_list_command[0] !=
'\0') {
379 if ((*length) == 0) {
383 if ((*length) > num_favorites) {
384 g_qsort_with_data(&(retv[num_favorites]), (*length) - num_favorites,
389 unsigned int removed = 0;
390 for (
unsigned int index = num_favorites; index < ((*length) - 1); index++) {
391 if (g_strcmp0(retv[index].entry, retv[index + 1].entry) == 0) {
392 g_free(retv[index].entry);
393 retv[index].
entry = NULL;
394 g_free(retv[index].exec);
395 retv[index].
exec = NULL;
400 if ((*length) > num_favorites) {
401 g_qsort_with_data(&(retv[num_favorites]), (*length) - num_favorites,
405 (*length) -= removed;
452 unsigned int selected_line) {
481 char *epath = g_shell_quote(path);
482 char *arg = g_strdup_printf(
"%s %s", earg, epath);
501 if (!
exec_cmd(*input, run_in_term, *input)) {
516 if (selected_line < rmpd->cmd_list_length) {
538 G_GNUC_UNUSED
int *state,
539 G_GNUC_UNUSED GList **list,
int get_entry) {
543 state, list, get_entry);
545 return get_entry ? g_strdup(rmpd->
cmd_list[selected_line].
entry) : NULL;
549 unsigned int index) {
563 g_strdup_printf(
"File complete for: %s\n%s",
568 return g_strdup_printf(
"File complete for: %s",
574static cairo_surface_t *
_get_icon(
const Mode *sw,
unsigned int selected_line,
575 unsigned int height) {
581 g_return_val_if_fail(pd->
cmd_list != NULL, NULL);
590 char **str = g_strsplit(dr->
entry,
" ", 2);
604 .cfg_name_key =
"display-run",
613 ._get_completion = NULL,
614 ._preprocess_input = NULL,
615 .private_data = NULL,
guint display_scale(void)
static cairo_surface_t * _get_icon(const Mode *sw, unsigned int selected_line, unsigned int height)
static char * _get_display_value(const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **attr_list, int get_entry)
gboolean helper_execute_command(const char *wd, const char *cmd, gboolean run_in_term, RofiHelperExecuteContext *context)
int execute_generator(const char *cmd)
char * rofi_expand_path(const char *input)
int helper_token_match(rofi_int_matcher *const *tokens, const char *input)
void history_set(const char *filename, const char *entry)
void history_remove(const char *filename, const char *entry)
char ** history_get_list(const char *filename, unsigned int *length)
cairo_surface_t * rofi_icon_fetcher_get(const uint32_t uid)
uint32_t rofi_icon_fetcher_query(const char *name, const int size)
void mode_destroy(Mode *mode)
int mode_init(Mode *mode)
Mode * mode_create(const Mode *mode)
ModeMode mode_completer_result(Mode *mode, int menu_retv, char **input, unsigned int selected_line, char **path)
void * mode_get_private_data(const Mode *mode)
char * mode_get_message(const Mode *mode)
const Mode * rofi_get_completer(void)
static int run_token_match(const Mode *sw, rofi_int_matcher **tokens, unsigned int index)
static RunEntry * get_apps(unsigned int *length)
static gboolean exec_cmd(const char *cmd, int run_in_term, const char *orig)
static int sort_func(const void *a, const void *b, G_GNUC_UNUSED void *data)
static char * run_get_message(const Mode *sw)
static cairo_surface_t * _get_icon(const Mode *sw, unsigned int selected_line, unsigned int height)
static RunEntry * get_apps_external(RunEntry *retv, unsigned int *length, unsigned int num_favorites)
static void run_mode_destroy(Mode *sw)
static unsigned int run_mode_get_num_entries(const Mode *sw)
static ModeMode run_mode_result(Mode *sw, int mretv, char **input, unsigned int selected_line)
static void delete_entry(const RunEntry *cmd)
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 run_mode_init(Mode *sw)
struct rofi_int_matcher_t rofi_int_matcher
unsigned int cmd_list_length
char * old_completer_input
__mode_get_num_entries _get_num_entries
_mode_token_match _token_match
_mode_get_display_value _get_display_value