This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch master
in repository efm2.
View the commit online.
commit f90da544ec3410d1f7670a905d11b231f023005f
Author: Carsten Haitzler (Rasterman) <[email protected]>
AuthorDate: Sat Feb 7 21:19:19 2026 +0000
typebuf - cd - tab completion works
i can tab complete abs and relativer paths with cd.
---
src/backends/default/open.c | 87 +++++++++++++++++++++++-
src/efm/efm_back_end.c | 9 ++-
src/efm/efm_typebuf.c | 156 ++++++++++++++++++--------------------------
src/efm/efm_typebuf.h | 1 +
src/efm/meson.build | 1 +
src/shared/util.c | 74 +++++++++++++++++++++
src/shared/util.h | 8 +++
7 files changed, 242 insertions(+), 94 deletions(-)
diff --git a/src/backends/default/open.c b/src/backends/default/open.c
index 47d9fed..4f69e4d 100644
--- a/src/backends/default/open.c
+++ b/src/backends/default/open.c
@@ -22,6 +22,7 @@
#include "meta.h"
#include "thumb_check.h"
#include "esc.h"
+#include "util.h"
typedef struct
{
@@ -1361,7 +1362,8 @@ _typebuf_cd(const char *dest)
if ((!mondir) || (!dest) || (!dest[0])) goto done;
strbuf2 = eina_strbuf_new();
if (!strbuf2) goto done;
- eina_strbuf_append_printf(strbuf2, "%s/%s", mondir, dest);
+ if (dest[0] != '/') eina_strbuf_append_printf(strbuf2, "%s/%s", mondir, dest);
+ else eina_strbuf_append(strbuf2, dest);
fprintf(stderr, "XXX: GO TO [%s]\n", eina_strbuf_string_get(strbuf2));
path = ecore_file_realpath(eina_strbuf_string_get(strbuf2));
eina_strbuf_free(strbuf2);
@@ -1376,6 +1378,78 @@ done:
eina_strbuf_free(strbuf);
}
+static Eina_Bool
+_complete_last_arg_path_cmd(char **args, Eina_Strbuf *cmd, const char *cmd_arg)
+{
+ Eina_Strbuf *buf = eina_strbuf_new();
+ Eina_Bool ret = EINA_FALSE;
+ int i;
+
+ fprintf(stderr, "GGG: complete cd args\n");
+ if (!buf) return ret;
+ for (i = 0; args[i]; i++)
+ {
+ if (args[i + 1])
+ { // other args - just append them
+ eina_strbuf_append(buf, args[i]);
+ eina_strbuf_append(buf, " ");
+ }
+ else
+ { // last arg
+ Eina_Strbuf *buf2 = eina_strbuf_new();
+ const char *mondir;
+ char *tmps, *comp = NULL;
+
+ mondir = ecore_file_monitor_path_get(mon);
+ if (!strncmp(args[i], "../", 3))
+ {
+ tmps = ecore_file_dir_get(mondir);
+ if (tmps)
+ {
+ fprintf(stderr, "GGG: parent[%s]\n", tmps);
+ eina_strbuf_append(buf2, tmps);
+ eina_strbuf_append(buf2, "/");
+ eina_strbuf_append(buf2, args[i] + 3);
+ fprintf(stderr, "GGG: input[%s]\n",
+ eina_strbuf_string_get(buf2));
+ comp
+ = util_complete(eina_strbuf_string_get(buf2), COMPLETE_ANY);
+ free(tmps);
+ }
+ }
+ else if (args[i][0] == '/')
+ {
+ eina_strbuf_append(buf2, args[i]);
+ fprintf(stderr, "GGG: input[%s]\n", eina_strbuf_string_get(buf2));
+ comp = util_complete(eina_strbuf_string_get(buf2), COMPLETE_ANY);
+ }
+ else
+ {
+ eina_strbuf_append(buf2, mondir);
+ eina_strbuf_append(buf2, "/");
+ if (!strncmp(args[i], "./", 2))
+ eina_strbuf_append(buf2, args[i] + 2);
+ else eina_strbuf_append(buf2, args[i]);
+ fprintf(stderr, "GGG: input[%s]\n", eina_strbuf_string_get(buf2));
+ comp = util_complete(eina_strbuf_string_get(buf2), COMPLETE_ANY);
+ }
+ fprintf(stderr, "GGG: comp=[%s]\n", comp);
+ if (comp)
+ {
+ eina_strbuf_append(buf, comp);
+ free(comp);
+ ret = EINA_TRUE;
+ }
+ else eina_strbuf_append(buf, args[i]);
+ eina_strbuf_free(buf2);
+ }
+ }
+ cmd_strbuf_append(cmd, cmd_arg, eina_strbuf_string_get(buf));
+ fprintf(stderr, "GGG: set typebuf [%s]\n", eina_strbuf_string_get(buf));
+ eina_strbuf_free(buf);
+ return ret;
+}
+
void
do_handle_cmd(Cmd *c)
{
@@ -1720,6 +1794,7 @@ do_handle_cmd(Cmd *c)
else if (!strcmp(args[0], "cd"))
{
_cmd_typebuf_icon_send("std:folder");
+ fprintf(stderr, "GGG: cd op=[%s]\n", op);
if ((op) && (!strcmp(op, "run")))
{
if (args[1]) _typebuf_cd(args[1]);
@@ -1729,6 +1804,16 @@ do_handle_cmd(Cmd *c)
cmd_strbuf_print_consume(strbuf);
}
}
+ else if ((op) && (!strcmp(op, "complete")))
+ {
+ if (args[1])
+ {
+ Eina_Strbuf *strbuf = cmd_strbuf_new("typebuf-set");
+ if (_complete_last_arg_path_cmd(args, strbuf, "string"))
+ cmd_strbuf_print_consume(strbuf);
+ else eina_strbuf_free(strbuf);
+ }
+ }
}
else
{
diff --git a/src/efm/efm_back_end.c b/src/efm/efm_back_end.c
index 2a05b5a..bfd4e93 100644
--- a/src/efm/efm_back_end.c
+++ b/src/efm/efm_back_end.c
@@ -662,7 +662,14 @@ _cb_thread_notify(void *data, Ecore_Thread *th EINA_UNUSED, void *msg)
{
const char *icon = cmd_key_find(c, "icon");
- typebuf_icon(sd, icon);
+ if (icon) typebuf_icon(sd, icon);
+ CMD_DONE;
+ }
+ else if (!strcmp(c->command, "typebuf-set"))
+ {
+ const char *string = cmd_key_find(c, "string");
+
+ if (string) typebuf_set(sd, string);
CMD_DONE;
}
diff --git a/src/efm/efm_typebuf.c b/src/efm/efm_typebuf.c
index 266f2e3..7222059 100644
--- a/src/efm/efm_typebuf.c
+++ b/src/efm/efm_typebuf.c
@@ -1,6 +1,7 @@
#define EFL_BETA_API_SUPPORT 1
#include "efm_typebuf.h"
#include "efm_util.h"
+#include "util.h"
static int
_typebuf_command_detect(const char *str)
@@ -113,10 +114,10 @@ _typebuf_cmd_send(Smart_Data *sd, const char *op)
int cpos = elm_entry_cursor_pos_get(sd->o_typebuf);
if ((!s)
- || ((sd->typebuf.prevcmd.line)
- && (!strcmp(s, sd->typebuf.prevcmd.line))
+ || ((sd->typebuf.prevcmd.line) && (!strcmp(s, sd->typebuf.prevcmd.line))
&& (sd->typebuf.prevcmd.cursor_pos == cpos)
- && (!!strcmp(op, "run"))))
+ && (!!strcmp(op, "run"))
+ && (!!strcmp(op, "complete"))))
{
if (buf) eina_strbuf_free(buf);
return;
@@ -161,69 +162,6 @@ _has_glob(const char *glob)
return EINA_FALSE;
}
-static int
-_cb_complete_dir_sort(char *f1, char *f2)
-{
- return strcmp(f1, f2);
-}
-
-static char *
-_complete_dir(const char *str)
-{
- Eina_Iterator *it;
- Eina_File_Direct_Info *info;
- size_t len = strlen(str);
- char *dir = ecore_file_dir_get(str);
- char *ret = NULL, *s, *s1, *s2;
- Eina_List *opts = NULL, *l;
-
- if (!dir) return NULL;
- it = eina_file_direct_ls(dir);
- if (!it) goto done;
- EINA_ITERATOR_FOREACH(it, info)
- { // walk dir and find files that match partial start string
- if ((!strncmp(str, info->path, len))
- && ((info->type == EINA_FILE_DIR) || (info->type == EINA_FILE_LNK)))
- {
- if (ecore_file_is_dir(info->path))
- { // completion must be a dir (resolves a symlink too)
- Eina_Strbuf *buf = eina_strbuf_new();
-
- if (buf)
- {
- eina_strbuf_append(buf, info->path);
- eina_strbuf_append(buf, "/");
- ret = strdup(eina_strbuf_string_get(buf));
- // add this path to our options for complete
- opts = eina_list_append(opts, ret);
- eina_strbuf_free(buf);
- }
- }
- }
- }
- eina_iterator_free(it);
-done:
- free(dir);
- opts = eina_list_sort(opts, 0, (Eina_Compare_Cb)_cb_complete_dir_sort);
- // take first result in sorted list
- ret = opts->data;
- // walk all options and find initial string that is common
- len = strlen(ret); // common lengthis length of first stre we found - this
- // ultimately len will be the shortest common lenght
- EINA_LIST_FOREACH(opts, l, s)
- {
- // walk first string and this string until they are not the same
- for (s1 = ret, s2 = l->data; (*s1 == *s2) && (*s1) && (*s2); s1++, s2++);
- // if string walked is less than current len = shorten it
- if ((s1 - ret) < len) len = s1 - ret;
- }
- ret[len] = 0; // truncate returned string to min common length
- opts->data = ""
- // free out tmp list of options
- EINA_LIST_FREE(opts, s) free(s);
- return ret;
-}
-
////////////////
static Eina_Bool
_has_path_full(const char *str)
@@ -266,7 +204,7 @@ _path_full_complete(Smart_Data *sd, const char *str)
char *complete;
if (!_has_path_full(str)) return EINA_FALSE;
- complete = _complete_dir(str);
+ complete = util_complete(str, COMPLETE_DIR);
if (complete)
{
_path_full_hilight(sd, complete);
@@ -288,6 +226,7 @@ _path_full_run(Smart_Data *sd, const char *str)
static Eina_Bool
_has_path_relative(const char *str)
{
+ if (eina_fnmatch("./*", str, EINA_FNMATCH_CASEFOLD)) return EINA_TRUE;
return eina_fnmatch("../*", str, EINA_FNMATCH_CASEFOLD);
}
@@ -296,24 +235,27 @@ _path_relative_hilight(Smart_Data *sd, const char *str)
{
Eina_Strbuf *buf = eina_strbuf_new();
const char *s;
+ Eina_Bool append = EINA_FALSE;
if (!buf) return;
// we know str already has "../" at the start
- if (str[0] && str[1] && str[2])
+ if (!strncmp(str, "../", 3)) eina_strbuf_append(buf, "<hilight>../</>");
+ else if (!strncmp(str, "./", 2)) eina_strbuf_append(buf, "<hilight>./</>");
+ for (s = str; *s; s++) // skip the ./ or ../
{
- eina_strbuf_append(buf, "<hilight>..</>");
- for (s = str + 2; *s; s++) // skip the ../
+ if (*s == '/')
{
- if (*s == '/')
+ if (!append) append = EINA_TRUE;
+ else
{
eina_strbuf_append(buf, "<hilight>");
eina_strbuf_append_char(buf, *s);
eina_strbuf_append(buf, "</>");
}
- else eina_strbuf_append_char(buf, *s);
}
- elm_entry_entry_set(sd->o_typebuf, eina_strbuf_string_get(buf));
+ else if (append) eina_strbuf_append_char(buf, *s);
}
+ elm_entry_entry_set(sd->o_typebuf, eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
}
@@ -329,18 +271,29 @@ static Eina_Bool
_path_relative_complete(Smart_Data *sd, const char *str)
{
Eina_Strbuf *buf;
- char *tmps;
+ char *tmps = NULL;
if (!_has_path_relative(str)) return EINA_FALSE;
- // str starts with ../ so find parent
- tmps = _path_parent(sd->config.path);
- if (!tmps) return EINA_TRUE;
- buf = eina_strbuf_new();
- if (!buf) goto done;
- eina_strbuf_append(buf, tmps);
- eina_strbuf_append(buf, str + 3);
- free(tmps);
- tmps = _complete_dir(eina_strbuf_string_get(buf));
+ // str starts with ./ or ../ so find parent
+ if (!strncmp(str, "../", 3))
+ {
+ tmps = _path_parent(sd->config.path);
+ if (!tmps) return EINA_TRUE;
+ buf = eina_strbuf_new();
+ if (!buf) goto done;
+ eina_strbuf_append(buf, tmps);
+ eina_strbuf_append(buf, str + 3);
+ free(tmps);
+ }
+ else if (!strncmp(str, "./", 2))
+ {
+ buf = eina_strbuf_new();
+ if (!buf) goto done;
+ eina_strbuf_append(buf, sd->config.path);
+ eina_strbuf_append(buf, str + 2);
+ }
+ else return EINA_FALSE;
+ tmps = util_complete(eina_strbuf_string_get(buf), COMPLETE_DIR);
eina_strbuf_free(buf);
if (tmps)
{
@@ -356,21 +309,32 @@ static Eina_Bool
_path_relative_run(Smart_Data *sd, const char *str)
{
Eina_Strbuf *buf;
- char *tmps;
+ char *tmps = NULL;
const char *path;
if (!_has_path_relative(str)) return EINA_FALSE;
- tmps = _path_parent(sd->config.path);
- if (!tmps) return EINA_TRUE;
- buf = eina_strbuf_new();
- if (!buf) goto done;
- eina_strbuf_append(buf, tmps);
- eina_strbuf_append(buf, str + 3);
+ if (!strncmp(str, "../", 3))
+ {
+ tmps = _path_parent(sd->config.path);
+ if (!tmps) return EINA_TRUE;
+ buf = eina_strbuf_new();
+ if (!buf) goto done;
+ eina_strbuf_append(buf, tmps);
+ eina_strbuf_append(buf, str + 3);
+ free(tmps);
+ }
+ else if (!strncmp(str, "./", 2))
+ {
+ buf = eina_strbuf_new();
+ if (!buf) goto done;
+ eina_strbuf_append(buf, sd->config.path);
+ eina_strbuf_append(buf, str + 2);
+ }
+ else return EINA_FALSE;
path = eina_strbuf_string_get(buf);
if (ecore_file_is_dir(path)) efm_path_set(sd->o_smart, path);
eina_strbuf_free(buf);
done:
- free(tmps);
return EINA_TRUE;
}
@@ -450,7 +414,7 @@ _path_user_complete(Smart_Data *sd, const char *str)
if (!resolve) goto done;
src = ""
if (!src) goto done;
- complete = _complete_dir(src);
+ complete = util_complete(src, COMPLETE_DIR);
// while home resolved + complete match strings...
for (s1 = resolve, s2 = complete; (*s1) && (*s2) && (*s1 == *s2);
s1++, s2++);
@@ -834,3 +798,11 @@ typebuf_icon(Smart_Data *sd, const char *icon)
eina_stringshare_replace(&sd->typebuf.icon, NULL);
}
}
+
+void
+typebuf_set(Smart_Data *sd, const char *str)
+{
+ _typebuf_command_clear(sd, str);
+ elm_entry_cursor_end_set(sd->o_typebuf);
+ _typebuf_format(sd);
+}
diff --git a/src/efm/efm_typebuf.h b/src/efm/efm_typebuf.h
index c0dbae6..4203ac8 100644
--- a/src/efm/efm_typebuf.h
+++ b/src/efm/efm_typebuf.h
@@ -8,5 +8,6 @@
void typebuf_del(Smart_Data *sd);
void typebuf_add(Smart_Data *sd, Evas_Event_Key_Down *ev);
void typebuf_icon(Smart_Data *sd, const char *icon);
+void typebuf_set(Smart_Data *sd, const char *str);
#endif
\ No newline at end of file
diff --git a/src/efm/meson.build b/src/efm/meson.build
index 2854f2c..04552ef 100644
--- a/src/efm/meson.build
+++ b/src/efm/meson.build
@@ -8,6 +8,7 @@ executable('efm', [
'../shared/cmd.c',
'../shared/esc.c',
'../shared/mimeapps.c',
+ '../shared/util.c',
'efm.c',
'sort.c',
'bitmap.c',
diff --git a/src/shared/util.c b/src/shared/util.c
index f9871ae..ea3cf16 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -1,5 +1,6 @@
#include "util.h"
#include "efm_config.h"
+#include <Ecore_File.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
@@ -70,4 +71,77 @@ util_modtime_valid(Util_Modtime t)
if ((t.sec == mt.sec) && (t.nsec == mt.nsec)) return EINA_FALSE;
return EINA_TRUE;
+}
+
+static int
+_cb_complete_dir_sort(char *f1, char *f2)
+{
+ return strcmp(f1, f2);
+}
+
+static Eina_Bool
+_complete_file_type(const char *file, Complete_Type type)
+{
+ if (type == COMPLETE_ANY) return EINA_TRUE;
+ if ((type == COMPLETE_DIR) && (ecore_file_is_dir(file))) return EINA_TRUE;
+ if ((type == COMPLETE_FILE) && (!ecore_file_is_dir(file))) return EINA_TRUE;
+ return EINA_FALSE;
+}
+
+char *
+util_complete(const char *str, Complete_Type type)
+{
+ Eina_Iterator *it;
+ Eina_File_Direct_Info *info;
+ size_t len = strlen(str);
+ char *dir = ecore_file_dir_get(str);
+ char *ret = NULL, *s, *s1, *s2;
+ Eina_List *opts = NULL, *l;
+
+ fprintf(stderr, "COMPLETE: [%s]\n", str);
+ if (!dir) return NULL;
+ it = eina_file_direct_ls(dir);
+ if (!it) goto done;
+ EINA_ITERATOR_FOREACH(it, info)
+ { // walk dir and find files that match partial start string
+ if (!strncmp(str, info->path, len))
+ {
+ if (_complete_file_type(info->path, type))
+ { // completion must be a dir (resolves a symlink too)
+ Eina_Strbuf *buf = eina_strbuf_new();
+
+ if (buf)
+ {
+ eina_strbuf_append(buf, info->path);
+ eina_strbuf_append(buf, "/");
+ ret = strdup(eina_strbuf_string_get(buf));
+ // add this path to our options for complete
+ opts = eina_list_append(opts, ret);
+ eina_strbuf_free(buf);
+ }
+ }
+ }
+ }
+ eina_iterator_free(it);
+done:
+ free(dir);
+ if (!opts) return NULL;
+ opts = eina_list_sort(opts, 0, (Eina_Compare_Cb)_cb_complete_dir_sort);
+ // take first result in sorted list
+ ret = opts->data;
+ // walk all options and find initial string that is common
+ len = strlen(ret); // common lengthis length of first stre we found - this
+ // ultimately len will be the shortest common lenght
+ EINA_LIST_FOREACH(opts, l, s)
+ {
+ // walk first string and this string until they are not the same
+ for (s1 = ret, s2 = l->data; (*s1 == *s2) && (*s1) && (*s2); s1++, s2++);
+ // if string walked is less than current len = shorten it
+ if ((size_t)(s1 - ret) < len) len = s1 - ret;
+ }
+ ret[len] = 0; // truncate returned string to min common length
+ opts->data = ""
+ // free out tmp list of options
+ EINA_LIST_FREE(opts, s) free(s);
+ return ret;
}
\ No newline at end of file
diff --git a/src/shared/util.h b/src/shared/util.h
index 38f4ec8..99fd5d0 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -8,9 +8,17 @@ typedef struct
unsigned long long sec, nsec;
} Util_Modtime;
+typedef enum
+{
+ COMPLETE_FILE,
+ COMPLETE_DIR,
+ COMPLETE_ANY
+} Complete_Type;
+
void util_file_mode_parent_copy(const char *file, Eina_Bool is_dir);
Util_Modtime util_file_modtime_get(const char *file);
int util_modtime_cmp(Util_Modtime t1, Util_Modtime t2);
Eina_Bool util_modtime_valid(Util_Modtime t);
+char *util_complete(const char *str, Complete_Type type);
#endif
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.