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.

Reply via email to