Add :source command
authorYutao Yuan <yyt16384@gmail.com>
Sun, 13 Sep 2015 16:41:22 +0000 (00:41 +0800)
committerYutao Yuan <yyt16384@gmail.com>
Sun, 20 Sep 2015 16:47:53 +0000 (00:47 +0800)
src/ex.c
src/ex.h
src/main.c
src/util.c
src/util.h

index 711190a..b315dfa 100644 (file)
--- a/src/ex.c
+++ b/src/ex.c
@@ -78,6 +78,7 @@ typedef enum {
     EX_SCR,
     EX_SET,
     EX_SHELLCMD,
+    EX_SOURCE,
     EX_TABOPEN,
 } ExCode;
 
@@ -148,6 +149,7 @@ static VbCmdResult ex_save(const ExArg *arg);
 static VbCmdResult ex_set(const ExArg *arg);
 static VbCmdResult ex_shellcmd(const ExArg *arg);
 static VbCmdResult ex_shortcut(const ExArg *arg);
+static VbCmdResult ex_source(const ExArg *arg);
 static VbCmdResult ex_handlers(const ExArg *arg);
 
 static gboolean complete(short direction);
@@ -198,6 +200,7 @@ static ExInfo commands[] = {
     {"shortcut-add",     EX_SCA,         ex_shortcut,   EX_FLAG_RHS},
     {"shortcut-default", EX_SCD,         ex_shortcut,   EX_FLAG_RHS},
     {"shortcut-remove",  EX_SCR,         ex_shortcut,   EX_FLAG_RHS},
+    {"source",           EX_SOURCE,      ex_source,     EX_FLAG_RHS|EX_FLAG_EXP},
     {"tabopen",          EX_TABOPEN,     ex_open,       EX_FLAG_CMD},
 };
 
@@ -498,6 +501,34 @@ VbCmdResult ex_run_string(const char *input, gboolean enable_history)
     return res;
 }
 
+/**
+ * Run all ex commands in a file.
+ */
+gboolean ex_run_file(const char *filename)
+{
+    char *line, **lines;
+
+    lines = util_get_lines(filename);
+
+    if (!lines) {
+        return false;
+    }
+
+    int length = g_strv_length(lines) - 1;
+    for (int i = 0; i < length; i++) {
+        line = lines[i];
+        if (*line == '#') {
+            continue;
+        }
+        if (ex_run_string(line, false) & VB_CMD_ERROR) {
+            g_warning("Invalid command in %s: '%s'", filename, line);
+        }
+    }
+    g_strfreev(lines);
+
+    return true;
+}
+
 /**
  * Parses given input string into given ExArg pointer.
  */
@@ -985,6 +1016,11 @@ static VbCmdResult ex_shellcmd(const ExArg *arg)
     return res;
 }
 
+static VbCmdResult ex_source(const ExArg *arg)
+{
+    return ex_run_file(arg->rhs->str) ? VB_CMD_SUCCESS | VB_CMD_KEEPINPUT : VB_CMD_ERROR;
+}
+
 static VbCmdResult ex_handlers(const ExArg *arg)
 {
     char *p;
@@ -1161,6 +1197,11 @@ static gboolean complete(short direction)
                     break;
 #endif
 
+                case EX_SOURCE:
+                    sort  = true;
+                    found = util_filename_fill_completion(store, token);
+                    break;
+
                 default:
                     break;
             }
index 9b706e3..cd3dccb 100644 (file)
--- a/src/ex.h
+++ b/src/ex.h
@@ -29,5 +29,6 @@ VbResult ex_keypress(int key);
 void ex_input_changed(const char *text);
 gboolean ex_fill_completion(GtkListStore *store, const char *input);
 VbCmdResult ex_run_string(const char *input, gboolean enable_history);
+gboolean ex_run_file(const char *filename);
 
 #endif /* end of include guard: _EX_H */
index 8790fa3..aec3276 100644 (file)
@@ -1127,24 +1127,7 @@ static void marks_clear(void)
 
 static void read_config(void)
 {
-    char *line, **lines;
-
-    /* read config from config files */
-    lines = util_get_lines(vb.files[FILES_CONFIG]);
-
-    if (lines) {
-        int length = g_strv_length(lines) - 1;
-        for (int i = 0; i < length; i++) {
-            line = lines[i];
-            if (*line == '#') {
-                continue;
-            }
-            if (ex_run_string(line, false) & VB_CMD_ERROR ) {
-                g_warning("Invalid user config: '%s'", line);
-            }
-        }
-    }
-    g_strfreev(lines);
+    ex_run_file(vb.files[FILES_CONFIG]);
 }
 
 static void setup_signals()
index b1a72c5..dcf2694 100644 (file)
@@ -774,3 +774,48 @@ gboolean util_fill_completion(GtkListStore *store, const char *input, GList *src
 
     return found;
 }
+
+gboolean util_filename_fill_completion(GtkListStore *store, const char *input)
+{
+    gboolean found = false;
+
+    const char *last_slash = strrchr(input, '/');
+    const char *input_basename = last_slash ? last_slash + 1 : input;
+    char *input_dirname = g_strndup(input, input_basename - input);
+    char *real_dirname = util_expand(
+        *input_dirname ? input_dirname : ".",
+        UTIL_EXP_TILDE|UTIL_EXP_DOLLAR|UTIL_EXP_SPECIAL
+    );
+
+    GError *error = NULL;
+    GDir *dir = g_dir_open(real_dirname, 0, &error);
+    if (error) {
+        /* Can't open directory, likely bad user input */
+        g_error_free(error);
+    } else {
+        const char *filename;
+        GtkTreeIter iter;
+        while ((filename = g_dir_read_name(dir))) {
+            if (g_str_has_prefix(filename, input_basename)) {
+                char *fullpath = g_build_filename(real_dirname, filename, NULL);
+                char *result;
+                if (g_file_test(fullpath, G_FILE_TEST_IS_DIR)) {
+                    result = g_strconcat(input_dirname, filename, "/", NULL);
+                } else {
+                    result = g_strconcat(input_dirname, filename, NULL);
+                }
+                g_free(fullpath);
+                gtk_list_store_append(store, &iter);
+                gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, result, -1);
+                g_free(result);
+                found = true;
+            }
+        }
+        g_dir_close(dir);
+    }
+
+    g_free(input_dirname);
+    g_free(real_dirname);
+
+    return found;
+}
index f73a631..104f116 100644 (file)
@@ -51,5 +51,6 @@ gboolean util_parse_expansion(const char **input, GString *str, int flags,
     const char *quoteable);
 gboolean util_wildmatch(const char *pattern, const char *subject);
 gboolean util_fill_completion(GtkListStore *store, const char *input, GList *src);
+gboolean util_filename_fill_completion(GtkListStore *store, const char *input);
 
 #endif /* end of include guard: _UTIL_H */