34 #define G_LOG_DOMAIN "Dialogs.Run"
46 #include <sys/types.h>
63 #define RUN_CACHE_FILE "rofi-3.runcache"
99 static gboolean
exec_cmd(
const char *cmd,
int run_in_term) {
100 GError *error = NULL;
101 if (!cmd || !cmd[0]) {
104 gsize lf_cmd_size = 0;
105 gchar *lf_cmd = g_locale_from_utf8(cmd, -1, NULL, &lf_cmd_size, &error);
107 g_warning(
"Failed to convert command to locale encoding: %s",
117 run_in_term ? &context : NULL)) {
157 static int sort_func(
const void *a,
const void *b, G_GNUC_UNUSED
void *data) {
161 if (astr->
entry == NULL && bstr->
entry == NULL) {
164 if (astr->
entry == NULL) {
167 if (bstr->
entry == NULL) {
177 unsigned int num_favorites) {
180 FILE *inp = fdopen(fd,
"r");
183 size_t buffer_length = 0;
185 while (getline(&buffer, &buffer_length, inp) > 0) {
188 if (buffer[strlen(buffer) - 1] ==
'\n') {
189 buffer[strlen(buffer) - 1] =
'\0';
194 for (
unsigned int j = 0; found == 0 && j < num_favorites; j++) {
195 if (strcasecmp(buffer, retv[j].entry) == 0) {
205 retv = g_realloc(retv, ((*length) + 2) *
sizeof(
RunEntry));
206 retv[(*length)].
entry = g_strdup(buffer);
207 retv[(*length)].
icon = NULL;
212 if (buffer != NULL) {
215 if (fclose(inp) != 0) {
216 g_warning(
"Failed to close stdout off executor script: '%s'",
221 retv[(*length)].
entry = NULL;
222 retv[(*length)].
icon = NULL;
231 GError *error = NULL;
233 unsigned int num_favorites = 0;
236 if (g_getenv(
"PATH") == NULL) {
243 for (
unsigned int i = 0; i < *length; i++) {
244 retv[i].
entry = hretv[i];
249 num_favorites = (*length);
251 path = g_strdup(g_getenv(
"PATH"));
254 gchar *homedir = g_locale_to_utf8(g_get_home_dir(), -1, NULL, &l, &error);
256 g_debug(
"Failed to convert homedir to UTF-8: %s", error->message);
257 for (
unsigned int i = 0; retv[i].
entry != NULL; i++) {
258 g_free(retv[i].entry);
261 g_clear_error(&error);
266 const char *
const sep =
":";
267 char *strtok_savepointer = NULL;
268 for (
const char *dirname = strtok_r(path, sep, &strtok_savepointer);
269 dirname != NULL; dirname = strtok_r(NULL, sep, &strtok_savepointer)) {
271 DIR *dir = opendir(fpath);
272 g_debug(
"Checking path %s for executable.", fpath);
278 gchar *dirn = g_locale_to_utf8(dirname, -1, NULL, &dirn_len, &error);
280 g_debug(
"Failed to convert directory name to UTF-8: %s",
282 g_clear_error(&error);
286 gboolean is_homedir = g_str_has_prefix(dirn, homedir);
289 while ((dent = readdir(dir)) != NULL) {
290 if (dent->d_type != DT_REG && dent->d_type != DT_LNK &&
291 dent->d_type != DT_UNKNOWN) {
295 if (dent->d_name[0] ==
'.') {
299 gchar *full_path = g_build_filename(dirname, dent->d_name, NULL);
300 gboolean b = g_file_test(full_path, G_FILE_TEST_IS_EXECUTABLE);
309 g_filename_to_utf8(dent->d_name, -1, NULL, &name_len, &error);
311 g_debug(
"Failed to convert filename to UTF-8: %s", error->message);
312 g_clear_error(&error);
319 for (
unsigned int j = 0; found == 0 && j < num_favorites; j++) {
320 if (g_strcmp0(name, retv[j].entry) == 0) {
330 retv = g_realloc(retv, ((*length) + 2) *
sizeof(
RunEntry));
331 retv[(*length)].
entry = name;
332 retv[(*length)].
icon = NULL;
334 retv[(*length) + 1].
entry = NULL;
335 retv[(*length) + 1].
icon = NULL;
350 if ((*length) == 0) {
354 if ((*length) > num_favorites) {
355 g_qsort_with_data(&(retv[num_favorites]), (*length) - num_favorites,
360 unsigned int removed = 0;
361 for (
unsigned int index = num_favorites; index < ((*length) - 1); index++) {
362 if (g_strcmp0(retv[index].entry, retv[index + 1].entry) == 0) {
363 g_free(retv[index].entry);
364 retv[index].
entry = NULL;
369 if ((*length) > num_favorites) {
370 g_qsort_with_data(&(retv[num_favorites]), (*length) - num_favorites,
374 (*length) -= removed;
418 unsigned int selected_line) {
440 selected_line, &path);
445 char *arg = g_strdup_printf(
462 if (!
exec_cmd(*input, run_in_term)) {
477 if (selected_line < rmpd->cmd_list_length) {
494 G_GNUC_UNUSED
int *state,
495 G_GNUC_UNUSED GList **list,
int get_entry) {
499 state, list, get_entry);
501 return get_entry ? g_strdup(rmpd->
cmd_list[selected_line].
entry) : NULL;
505 unsigned int index) {
519 g_strdup_printf(
"File complete for: %s\n%s",
524 return g_strdup_printf(
"File complete for: %s",
541 static cairo_surface_t *
_get_icon(
const Mode *sw,
unsigned int selected_line,
547 g_return_val_if_fail(pd->
cmd_list != NULL, NULL);
558 char **str = g_strsplit(dr->
entry,
" ", 2);
572 .cfg_name_key =
"display-run",
581 ._get_completion = NULL,
582 ._preprocess_input = NULL,
583 .private_data = NULL,
ModeMode file_browser_mode_completer(Mode *sw, int mretv, char **input, unsigned int selected_line, char **path)
Mode * create_new_file_browser(void)
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)
char * mode_get_message(const Mode *mode)
void * mode_get_private_data(const Mode *mode)
static int run_token_match(const Mode *sw, rofi_int_matcher **tokens, unsigned int index)
static cairo_surface_t * _get_icon(const Mode *sw, unsigned int selected_line, int height)
static int sort_func(const void *a, const void *b, G_GNUC_UNUSED void *data)
static cairo_surface_t * fallback_icon(RunModePrivateData *pd, int height)
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 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 char * run_get_message(const Mode *sw)
static gboolean exec_cmd(const char *cmd, int run_in_term)
static void delete_entry(const RunEntry *cmd)
static RunEntry * get_apps(unsigned int *length)
static RunEntry * get_apps_external(RunEntry *retv, unsigned int *length, unsigned int num_favorites)
static int run_mode_init(Mode *sw)
unsigned int cmd_list_length
cairo_surface_t * fallback_icon
uint32_t fallback_icon_fetch_uid
char * old_completer_input
char * application_fallback_icon
__mode_get_num_entries _get_num_entries
_mode_token_match _token_match
_mode_get_display_value _get_display_value