Johannes Weißl
2011-05-04 01:10:02 UTC
commands are :run and :shell
---
command_mode.c | 19 +++++++++++++-
load_dir.h | 13 ++++++++++
misc.c | 8 ++++++
misc.h | 1 +
tabexp_file.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++--------
tabexp_file.h | 2 +
6 files changed, 103 insertions(+), 13 deletions(-)
diff --git a/command_mode.c b/command_mode.c
index 99d8f4e..3fcceb2 100644
--- a/command_mode.c
+++ b/command_mode.c
@@ -1968,6 +1968,11 @@ static int filter_directories(const char *name, const struct stat *s)
return S_ISDIR(s->st_mode);
}
+static int filter_executable_files(const char *name, const struct stat *s)
+{
+ return S_ISREG(s->st_mode) && (s->st_mode & 0111);
+}
+
static int filter_any(const char *name, const struct stat *s)
{
return 1;
@@ -2030,6 +2035,16 @@ static void expand_add(const char *str)
}
}
+static void expand_program_paths(const char *str)
+{
+ if (str == NULL)
+ str = "";
+ if (str[0] == '~' || strchr(str, '/'))
+ expand_files(str);
+ else
+ expand_env_path(str, filter_executable_files);
+}
+
static void expand_load_save(const char *str)
{
int flag = parse_flags(&str, "lp");
@@ -2453,13 +2468,13 @@ struct command commands[] = {
{ "push", cmd_push, 1,-1, expand_commands, 0, 0 },
{ "quit", cmd_quit, 0, 1, NULL, 0, 0 },
{ "refresh", cmd_refresh, 0, 0, NULL, 0, 0 },
- { "run", cmd_run, 1,-1, NULL, 0, CMD_UNSAFE },
+ { "run", cmd_run, 1,-1, expand_program_paths, 0, CMD_UNSAFE },
{ "save", cmd_save, 0, 1, expand_load_save, 0, CMD_UNSAFE },
{ "search-next", cmd_search_next,0, 0, NULL, 0, 0 },
{ "search-prev", cmd_search_prev,0, 0, NULL, 0, 0 },
{ "seek", cmd_seek, 1, 1, NULL, 0, 0 },
{ "set", cmd_set, 1, 1, expand_options, 0, 0 },
- { "shell", cmd_shell, 1,-1, NULL, 0, CMD_UNSAFE },
+ { "shell", cmd_shell, 1,-1, expand_program_paths, 0, CMD_UNSAFE },
{ "showbind", cmd_showbind, 1, 1, expand_unbind_args, 0, 0 },
{ "shuffle", cmd_reshuffle, 0, 0, NULL, 0, 0 },
{ "source", cmd_source, 1, 1, expand_files, 0, CMD_UNSAFE },
diff --git a/load_dir.h b/load_dir.h
index 7a44e01..0363a8c 100644
--- a/load_dir.h
+++ b/load_dir.h
@@ -69,4 +69,17 @@ static inline void ptr_array_sort(struct ptr_array *array,
qsort(array->ptrs, count, sizeof(void *), cmp);
}
+static inline void ptr_array_unique(struct ptr_array *array,
+ int (*cmp)(const void *a, const void *b))
+{
+ void **ptrs = array->ptrs;
+ int i, j = 0;
+
+ for (i = 1; i < array->count; i++) {
+ if (cmp(&ptrs[i-1], &ptrs[i]) != 0)
+ ptrs[j++] = ptrs[i];
+ }
+ array->count = j;
+}
+
#endif
diff --git a/misc.c b/misc.c
index 6b4df37..98a1e8e 100644
--- a/misc.c
+++ b/misc.c
@@ -77,6 +77,14 @@ int strptrcmp(const void *a, const void *b)
return strcmp(as, bs);
}
+int strptrcoll(const void *a, const void *b)
+{
+ const char *as = *(char **)a;
+ const char *bs = *(char **)b;
+
+ return strcoll(as, bs);
+}
+
const char *escape(const char *str)
{
static char *buf = NULL;
diff --git a/misc.h b/misc.h
index ce01f46..159e5cf 100644
--- a/misc.h
+++ b/misc.h
@@ -25,6 +25,7 @@ extern const char *user_name;
char **get_words(const char *text);
int strptrcmp(const void *a, const void *b);
+int strptrcoll(const void *a, const void *b);
int misc_init(void);
const char *escape(const char *str);
const char *unescape(const char *str);
diff --git a/tabexp_file.c b/tabexp_file.c
index 53f574d..87371e2 100644
--- a/tabexp_file.c
+++ b/tabexp_file.c
@@ -73,20 +73,15 @@ static char *get_full_dir_name(const char *dir)
return full;
}
-/*
- * load all directory entries from directory 'dir' starting with 'start' and
- * filtered with 'filter'
- */
-static void tabexp_load_dir(const char *dirname, const char *start,
+static void load_dir(struct ptr_array *array,
+ const char *dirname, const char *start,
int (*filter)(const char *, const struct stat *))
{
int start_len = strlen(start);
struct directory dir;
- PTR_ARRAY(array);
- const char *name;
char *full_dir_name;
+ const char *name;
- /* tabexp is reseted */
full_dir_name = get_full_dir_name(dirname);
if (!full_dir_name)
return;
@@ -118,9 +113,25 @@ static void tabexp_load_dir(const char *dirname, const char *start,
} else {
str = xstrdup(name);
}
- ptr_array_add(&array, str);
+ ptr_array_add(array, str);
}
dir_close(&dir);
+out:
+ free(full_dir_name);
+}
+
+/*
+ * load all directory entries from directory 'dir' starting with 'start' and
+ * filtered with 'filter'
+ */
+static void tabexp_load_dir(const char *dirname, const char *start,
+ int (*filter)(const char *, const struct stat *))
+{
+ PTR_ARRAY(array);
+
+ /* tabexp is reseted */
+ load_dir(&array, dirname, start, filter);
+
if (array.count) {
ptr_array_sort(&array, strptrcmp);
@@ -128,8 +139,37 @@ static void tabexp_load_dir(const char *dirname, const char *start,
tabexp.tails = array.ptrs;
tabexp.count = array.count;
}
-out:
- free(full_dir_name);
+}
+
+static void tabexp_load_env_path(const char *env_path, const char *start,
+ int (*filter)(const char *, const struct stat *))
+{
+ char *path = xstrdup(env_path);
+ PTR_ARRAY(array);
+ char cwd[1024];
+ char *p = path, *n;
+
+ /* tabexp is reseted */
+ do {
+ n = strchr(p, ':');
+ if (n)
+ *n = '\0';
+ if (strcmp(p, "") == 0 && getcwd(cwd, sizeof(cwd)))
+ p = cwd;
+ load_dir(&array, p, start, filter);
+ p = n + 1;
+ } while (n);
+
+ if (array.count) {
+ ptr_array_sort(&array, strptrcoll);
+ ptr_array_unique(&array, strptrcmp);
+
+ tabexp.head = xstrdup("");
+ tabexp.tails = array.ptrs;
+ tabexp.count = array.count;
+ }
+
+ free(path);
}
void expand_files_and_dirs(const char *src,
@@ -164,3 +204,14 @@ void expand_files_and_dirs(const char *src,
}
}
}
+
+void expand_env_path(const char *src,
+ int (*filter)(const char *name, const struct stat *s))
+{
+ const char *env_path = getenv("PATH");
+
+ if (!env_path || strcmp(env_path, "") == 0)
+ return;
+
+ tabexp_load_env_path(env_path, src, filter);
+}
diff --git a/tabexp_file.h b/tabexp_file.h
index 9e8e10e..cbd0967 100644
--- a/tabexp_file.h
+++ b/tabexp_file.h
@@ -23,5 +23,7 @@
void expand_files_and_dirs(const char *src,
int (*filter)(const char *name, const struct stat *s));
+void expand_env_path(const char *src,
+ int (*filter)(const char *name, const struct stat *s));
#endif
---
command_mode.c | 19 +++++++++++++-
load_dir.h | 13 ++++++++++
misc.c | 8 ++++++
misc.h | 1 +
tabexp_file.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++--------
tabexp_file.h | 2 +
6 files changed, 103 insertions(+), 13 deletions(-)
diff --git a/command_mode.c b/command_mode.c
index 99d8f4e..3fcceb2 100644
--- a/command_mode.c
+++ b/command_mode.c
@@ -1968,6 +1968,11 @@ static int filter_directories(const char *name, const struct stat *s)
return S_ISDIR(s->st_mode);
}
+static int filter_executable_files(const char *name, const struct stat *s)
+{
+ return S_ISREG(s->st_mode) && (s->st_mode & 0111);
+}
+
static int filter_any(const char *name, const struct stat *s)
{
return 1;
@@ -2030,6 +2035,16 @@ static void expand_add(const char *str)
}
}
+static void expand_program_paths(const char *str)
+{
+ if (str == NULL)
+ str = "";
+ if (str[0] == '~' || strchr(str, '/'))
+ expand_files(str);
+ else
+ expand_env_path(str, filter_executable_files);
+}
+
static void expand_load_save(const char *str)
{
int flag = parse_flags(&str, "lp");
@@ -2453,13 +2468,13 @@ struct command commands[] = {
{ "push", cmd_push, 1,-1, expand_commands, 0, 0 },
{ "quit", cmd_quit, 0, 1, NULL, 0, 0 },
{ "refresh", cmd_refresh, 0, 0, NULL, 0, 0 },
- { "run", cmd_run, 1,-1, NULL, 0, CMD_UNSAFE },
+ { "run", cmd_run, 1,-1, expand_program_paths, 0, CMD_UNSAFE },
{ "save", cmd_save, 0, 1, expand_load_save, 0, CMD_UNSAFE },
{ "search-next", cmd_search_next,0, 0, NULL, 0, 0 },
{ "search-prev", cmd_search_prev,0, 0, NULL, 0, 0 },
{ "seek", cmd_seek, 1, 1, NULL, 0, 0 },
{ "set", cmd_set, 1, 1, expand_options, 0, 0 },
- { "shell", cmd_shell, 1,-1, NULL, 0, CMD_UNSAFE },
+ { "shell", cmd_shell, 1,-1, expand_program_paths, 0, CMD_UNSAFE },
{ "showbind", cmd_showbind, 1, 1, expand_unbind_args, 0, 0 },
{ "shuffle", cmd_reshuffle, 0, 0, NULL, 0, 0 },
{ "source", cmd_source, 1, 1, expand_files, 0, CMD_UNSAFE },
diff --git a/load_dir.h b/load_dir.h
index 7a44e01..0363a8c 100644
--- a/load_dir.h
+++ b/load_dir.h
@@ -69,4 +69,17 @@ static inline void ptr_array_sort(struct ptr_array *array,
qsort(array->ptrs, count, sizeof(void *), cmp);
}
+static inline void ptr_array_unique(struct ptr_array *array,
+ int (*cmp)(const void *a, const void *b))
+{
+ void **ptrs = array->ptrs;
+ int i, j = 0;
+
+ for (i = 1; i < array->count; i++) {
+ if (cmp(&ptrs[i-1], &ptrs[i]) != 0)
+ ptrs[j++] = ptrs[i];
+ }
+ array->count = j;
+}
+
#endif
diff --git a/misc.c b/misc.c
index 6b4df37..98a1e8e 100644
--- a/misc.c
+++ b/misc.c
@@ -77,6 +77,14 @@ int strptrcmp(const void *a, const void *b)
return strcmp(as, bs);
}
+int strptrcoll(const void *a, const void *b)
+{
+ const char *as = *(char **)a;
+ const char *bs = *(char **)b;
+
+ return strcoll(as, bs);
+}
+
const char *escape(const char *str)
{
static char *buf = NULL;
diff --git a/misc.h b/misc.h
index ce01f46..159e5cf 100644
--- a/misc.h
+++ b/misc.h
@@ -25,6 +25,7 @@ extern const char *user_name;
char **get_words(const char *text);
int strptrcmp(const void *a, const void *b);
+int strptrcoll(const void *a, const void *b);
int misc_init(void);
const char *escape(const char *str);
const char *unescape(const char *str);
diff --git a/tabexp_file.c b/tabexp_file.c
index 53f574d..87371e2 100644
--- a/tabexp_file.c
+++ b/tabexp_file.c
@@ -73,20 +73,15 @@ static char *get_full_dir_name(const char *dir)
return full;
}
-/*
- * load all directory entries from directory 'dir' starting with 'start' and
- * filtered with 'filter'
- */
-static void tabexp_load_dir(const char *dirname, const char *start,
+static void load_dir(struct ptr_array *array,
+ const char *dirname, const char *start,
int (*filter)(const char *, const struct stat *))
{
int start_len = strlen(start);
struct directory dir;
- PTR_ARRAY(array);
- const char *name;
char *full_dir_name;
+ const char *name;
- /* tabexp is reseted */
full_dir_name = get_full_dir_name(dirname);
if (!full_dir_name)
return;
@@ -118,9 +113,25 @@ static void tabexp_load_dir(const char *dirname, const char *start,
} else {
str = xstrdup(name);
}
- ptr_array_add(&array, str);
+ ptr_array_add(array, str);
}
dir_close(&dir);
+out:
+ free(full_dir_name);
+}
+
+/*
+ * load all directory entries from directory 'dir' starting with 'start' and
+ * filtered with 'filter'
+ */
+static void tabexp_load_dir(const char *dirname, const char *start,
+ int (*filter)(const char *, const struct stat *))
+{
+ PTR_ARRAY(array);
+
+ /* tabexp is reseted */
+ load_dir(&array, dirname, start, filter);
+
if (array.count) {
ptr_array_sort(&array, strptrcmp);
@@ -128,8 +139,37 @@ static void tabexp_load_dir(const char *dirname, const char *start,
tabexp.tails = array.ptrs;
tabexp.count = array.count;
}
-out:
- free(full_dir_name);
+}
+
+static void tabexp_load_env_path(const char *env_path, const char *start,
+ int (*filter)(const char *, const struct stat *))
+{
+ char *path = xstrdup(env_path);
+ PTR_ARRAY(array);
+ char cwd[1024];
+ char *p = path, *n;
+
+ /* tabexp is reseted */
+ do {
+ n = strchr(p, ':');
+ if (n)
+ *n = '\0';
+ if (strcmp(p, "") == 0 && getcwd(cwd, sizeof(cwd)))
+ p = cwd;
+ load_dir(&array, p, start, filter);
+ p = n + 1;
+ } while (n);
+
+ if (array.count) {
+ ptr_array_sort(&array, strptrcoll);
+ ptr_array_unique(&array, strptrcmp);
+
+ tabexp.head = xstrdup("");
+ tabexp.tails = array.ptrs;
+ tabexp.count = array.count;
+ }
+
+ free(path);
}
void expand_files_and_dirs(const char *src,
@@ -164,3 +204,14 @@ void expand_files_and_dirs(const char *src,
}
}
}
+
+void expand_env_path(const char *src,
+ int (*filter)(const char *name, const struct stat *s))
+{
+ const char *env_path = getenv("PATH");
+
+ if (!env_path || strcmp(env_path, "") == 0)
+ return;
+
+ tabexp_load_env_path(env_path, src, filter);
+}
diff --git a/tabexp_file.h b/tabexp_file.h
index 9e8e10e..cbd0967 100644
--- a/tabexp_file.h
+++ b/tabexp_file.h
@@ -23,5 +23,7 @@
void expand_files_and_dirs(const char *src,
int (*filter)(const char *name, const struct stat *s));
+void expand_env_path(const char *src,
+ int (*filter)(const char *name, const struct stat *s));
#endif
--
1.7.5
1.7.5