about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorMichael Vetter <jubalh@iodoru.org>2021-09-29 19:29:47 +0200
committerGitHub <noreply@github.com>2021-09-29 19:29:47 +0200
commitb72801a0e4afa6ec8b3a500fcfd294f46584695d (patch)
tree30b8614a5e9f225b996c4acd85e8e1da6f39583e
parentfd9ccec8dc604902bbb1d444dba4223ccee0a092 (diff)
parent312063636718b6480c16af3fb0ef57ad3d8ae907 (diff)
downloadprofani-tty-b72801a0e4afa6ec8b3a500fcfd294f46584695d.tar.gz
Merge pull request #1598 from profanity-im/feature/global-plugins
Improve plugins user experience
-rw-r--r--configure.ac30
-rw-r--r--src/command/cmd_ac.c18
-rw-r--r--src/command/cmd_defs.c12
-rw-r--r--src/command/cmd_funcs.c123
-rw-r--r--src/config/preferences.c9
-rw-r--r--src/config/preferences.h1
6 files changed, 84 insertions, 109 deletions
diff --git a/configure.ac b/configure.ac
index 3151cdc8..ce79743d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,8 +7,6 @@ AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_SRCDIR([src/main.c])
 AC_CONFIG_HEADERS([src/config.h])
 AM_INIT_AUTOMAKE([foreign subdir-objects])
-# TODO Introduce with Ruby plugins, see https://github.com/profanity-im/profanity/issues/779
-#AX_PREFIX_CONFIG_H([src/prof_config.h], [PROF], [src/config.h])
 
 ### Checks for programs.
 AC_PROG_CC
@@ -96,6 +94,9 @@ elif test "x$enable_python_plugins" != xno; then
         fi
     fi
     AS_IF([test "x$PLATFORM" = xosx], [rm -f Python.framework])
+    # set path to look for global python plugins
+    GLOBAL_PYTHON_PLUGINS_PATH='${pkgdatadir}/plugins'
+    AC_SUBST(GLOBAL_PYTHON_PLUGINS_PATH)
 else
     AM_CONDITIONAL([BUILD_PYTHON_API], [false])
 fi
@@ -119,6 +120,9 @@ else
                         [AC_MSG_ERROR([dl library needed to run C plugins])],
                     [AM_CONDITIONAL([BUILD_C_API], [false])])
                 ])])
+        # set path to look for global c plugins
+        GLOBAL_C_PLUGINS_PATH='${pkglibdir}/plugins'
+        AC_SUBST(GLOBAL_C_PLUGINS_PATH)
     else
         AM_CONDITIONAL([BUILD_C_API], [false])
     fi
@@ -360,7 +364,7 @@ AS_IF([test "x$PLATFORM" = xosx],
     [AM_CFLAGS="$AM_CFLAGS -Qunused-arguments"])
 AM_LDFLAGS="$AM_LDFLAGS -export-dynamic"
 AM_CPPFLAGS="$AM_CPPFLAGS $glib_CFLAGS $gio_CFLAGS $curl_CFLAGS $libnotify_CFLAGS $PYTHON_CPPFLAGS ${GTK_CFLAGS} ${SQLITE_CFLAGS}"
-AM_CPPFLAGS="$AM_CPPFLAGS -DTHEMES_PATH=\"\\\"$THEMES_PATH\\\"\" -DICONS_PATH=\"\\\"$ICONS_PATH\\\"\""
+AM_CPPFLAGS="$AM_CPPFLAGS -DTHEMES_PATH=\"\\\"$THEMES_PATH\\\"\" -DICONS_PATH=\"\\\"$ICONS_PATH\\\"\" -DGLOBAL_PYTHON_PLUGINS_PATH=\"\\\"$GLOBAL_PYTHON_PLUGINS_PATH\\\"\" -DGLOBAL_C_PLUGINS_PATH=\"\\\"$GLOBAL_C_PLUGINS_PATH\\\"\""
 LIBS="$glib_LIBS $gio_LIBS $curl_LIBS $libnotify_LIBS $PYTHON_LIBS $PYTHON_EXTRA_LIBS $PYTHON_LDFLAGS ${GTK_LIBS} ${SQLITE_LIBS} $LIBS"
 
 AC_SUBST(AM_LDFLAGS)
@@ -374,14 +378,16 @@ AC_CONFIG_FILES([Makefile])
 AC_OUTPUT
 
 echo ""
-echo "PLATFORM       : $host_os"
-echo "PACKAGE_STATUS : $PACKAGE_STATUS"
-echo "AM_CFLAGS      : $AM_CFLAGS"
-echo "AM_CPPFLAGS    : $AM_CPPFLAGS"
-echo "AM_LDFLAGS     : $AM_LDFLAGS"
-echo "LIBS           : $LIBS"
-echo "Install themes : $THEMES_INSTALL"
-echo "Themes path    : $THEMES_PATH"
-echo "Icons path     : $ICONS_PATH"
+echo "PLATFORM                   : $host_os"
+echo "PACKAGE_STATUS             : $PACKAGE_STATUS"
+echo "AM_CFLAGS                  : $AM_CFLAGS"
+echo "AM_CPPFLAGS                : $AM_CPPFLAGS"
+echo "AM_LDFLAGS                 : $AM_LDFLAGS"
+echo "LIBS                       : $LIBS"
+echo "Install themes             : $THEMES_INSTALL"
+echo "Themes path                : $THEMES_PATH"
+echo "Icons path                 : $ICONS_PATH"
+echo "Global Python plugins path : $GLOBAL_PYTHON_PLUGINS_PATH"
+echo "Global C plugins path      : $GLOBAL_C_PLUGINS_PATH"
 echo ""
 echo "Now you can run \`make' to build profanity"
diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c
index e821eb8b..39ab24bc 100644
--- a/src/command/cmd_ac.c
+++ b/src/command/cmd_ac.c
@@ -242,7 +242,6 @@ static Autocomplete console_ac;
 static Autocomplete console_msg_ac;
 static Autocomplete autoping_ac;
 static Autocomplete plugins_ac;
-static Autocomplete plugins_sourcepath_ac;
 static Autocomplete plugins_load_ac;
 static Autocomplete plugins_unload_ac;
 static Autocomplete plugins_reload_ac;
@@ -940,11 +939,6 @@ cmd_ac_init(void)
     autocomplete_add(plugins_ac, "unload");
     autocomplete_add(plugins_ac, "reload");
     autocomplete_add(plugins_ac, "python_version");
-    autocomplete_add(plugins_ac, "sourcepath");
-
-    plugins_sourcepath_ac = autocomplete_new();
-    autocomplete_add(plugins_sourcepath_ac, "set");
-    autocomplete_add(plugins_sourcepath_ac, "clear");
 
     filepath_ac = autocomplete_new();
 
@@ -1355,7 +1349,6 @@ cmd_ac_reset(ProfWin* window)
     autocomplete_reset(console_msg_ac);
     autocomplete_reset(autoping_ac);
     autocomplete_reset(plugins_ac);
-    autocomplete_reset(plugins_sourcepath_ac);
     autocomplete_reset(blocked_ac);
     autocomplete_reset(tray_ac);
     autocomplete_reset(presence_ac);
@@ -2638,21 +2631,10 @@ _plugins_autocomplete(ProfWin* window, const char* const input, gboolean previou
 {
     char* result = NULL;
 
-    if (strncmp(input, "/plugins sourcepath set ", 24) == 0) {
-        return cmd_ac_complete_filepath(input, "/plugins sourcepath set", previous);
-    }
-
     if (strncmp(input, "/plugins install ", 17) == 0) {
         return cmd_ac_complete_filepath(input, "/plugins install", previous);
     }
 
-    if (strncmp(input, "/plugins sourcepath ", 20) == 0) {
-        result = autocomplete_param_with_ac(input, "/plugins sourcepath", plugins_sourcepath_ac, TRUE, previous);
-        if (result) {
-            return result;
-        }
-    }
-
     if (strncmp(input, "/plugins load ", 14) == 0) {
         if (plugins_load_ac == NULL) {
             plugins_load_ac = autocomplete_new();
diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c
index d86e62a3..1b8c3112 100644
--- a/src/command/cmd_defs.c
+++ b/src/command/cmd_defs.c
@@ -2136,7 +2136,6 @@ static struct cmd_t command_defs[] = {
     { "/plugins",
       parse_args, 0, 3, NULL,
       CMD_SUBFUNCS(
-              { "sourcepath", cmd_plugins_sourcepath },
               { "install", cmd_plugins_install },
               { "uninstall", cmd_plugins_uninstall },
               { "update", cmd_plugins_update },
@@ -2148,8 +2147,6 @@ static struct cmd_t command_defs[] = {
       CMD_NOTAGS
       CMD_SYN(
               "/plugins",
-              "/plugins sourcepath set <path>",
-              "/plugins sourcepath clear",
               "/plugins install [<path>]",
               "/plugins uninstall [<plugin>]",
               "/plugins update [<path>]",
@@ -2158,19 +2155,16 @@ static struct cmd_t command_defs[] = {
               "/plugins reload [<plugin>]",
               "/plugins python_version")
       CMD_DESC(
-              "Manage plugins. Passing no arguments lists currently loaded plugins.")
+              "Manage plugins. Passing no arguments lists currently loaded plugins and global plugins which are available for local installation. Global directory for Python plugins is " GLOBAL_PYTHON_PLUGINS_PATH " and for C Plugins is " GLOBAL_C_PLUGINS_PATH ".")
       CMD_ARGS(
-              { "sourcepath set <path>", "Set the default path to install plugins from, will be used if no arg is passed to /plugins install." },
-              { "sourcepath clear", "Clear the default plugins source path." },
-              { "install [<path>]", "Install a plugin, or all plugins found in a directory (recursive). Passing no argument will use the sourcepath if one is set." },
+              { "install [<path>]", "Install a plugin, or all plugins found in a directory (recursive). And loads it/them." },
               { "uninstall [<plugin>]", "Uninstall a plugin." },
               { "update [<path>]", "Updates an installed plugin" },
-              { "load [<plugin>]", "Load a plugin that already exists in the plugin directory, passing no argument loads all found plugins." },
+              { "load [<plugin>]", "Load a plugin that already exists in the plugin directory, passing no argument loads all found plugins. It will be loaded upon next start too unless unloaded." },
               { "unload [<plugin>]", "Unload a loaded plugin, passing no argument will unload all plugins." },
               { "reload [<plugin>]", "Reload a plugin, passing no argument will reload all plugins." },
               { "python_version", "Show the Python interpreter version." })
       CMD_EXAMPLES(
-              "/plugins sourcepath set /home/meee/projects/profanity-plugins",
               "/plugins install",
               "/plugins install /home/steveharris/Downloads/metal.py",
               "/plugins update /home/steveharris/Downloads/metal.py",
diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c
index ad1b3331..2a206d5b 100644
--- a/src/command/cmd_funcs.c
+++ b/src/command/cmd_funcs.c
@@ -6925,67 +6925,35 @@ cmd_receipts(ProfWin* window, const char* const command, gchar** args)
 }
 
 gboolean
-cmd_plugins_sourcepath(ProfWin* window, const char* const command, gchar** args)
+cmd_plugins_install(ProfWin* window, const char* const command, gchar** args)
 {
-    if (args[1] == NULL) {
-        char* sourcepath = prefs_get_string(PREF_PLUGINS_SOURCEPATH);
-        if (sourcepath) {
-            cons_show("Current plugins sourcepath: %s", sourcepath);
-            g_free(sourcepath);
-        } else {
-            cons_show("Plugins sourcepath not currently set.");
-        }
-        return TRUE;
-    }
+    char* path = NULL;
 
-    if (g_strcmp0(args[1], "clear") == 0) {
-        prefs_set_string(PREF_PLUGINS_SOURCEPATH, NULL);
-        cons_show("Plugins sourcepath cleared.");
+    if (args[1] == NULL) {
+        cons_show("Please provide a path to the plugin file or directory, see /help plugins");
         return TRUE;
     }
 
-    if (g_strcmp0(args[1], "set") == 0) {
-        if (args[2] == NULL) {
-            cons_bad_cmd_usage(command);
-            return TRUE;
-        }
-
-        char* path = get_expanded_path(args[2]);
-
-        if (!is_dir(path)) {
-            cons_show("Plugins sourcepath must be a directory.");
-            free(path);
+    // take whole path or build it in case it's just the plugin name
+    if (strchr(args[1], '/')) {
+        path = get_expanded_path(args[1]);
+    } else {
+        if (g_str_has_suffix(args[1], ".py")) {
+            path = g_strdup_printf("%s/%s", GLOBAL_PYTHON_PLUGINS_PATH, args[1]);
+        } else if (g_str_has_suffix(args[1], ".so")) {
+            path = g_strdup_printf("%s/%s", GLOBAL_C_PLUGINS_PATH, args[1]);
+        } else {
+            cons_show("Plugins must have one of the following extensions: '.py' '.so'");
             return TRUE;
         }
+    }
 
-        cons_show("Setting plugins sourcepath: %s", path);
-        prefs_set_string(PREF_PLUGINS_SOURCEPATH, path);
+    if (access(path, R_OK) != 0) {
+        cons_show("Cannot access: %s", path);
         free(path);
         return TRUE;
     }
 
-    cons_bad_cmd_usage(command);
-    return TRUE;
-}
-
-gboolean
-cmd_plugins_install(ProfWin* window, const char* const command, gchar** args)
-{
-    char* path;
-
-    if (args[1] == NULL) {
-        char* sourcepath = prefs_get_string(PREF_PLUGINS_SOURCEPATH);
-        if (sourcepath) {
-            path = strdup(sourcepath);
-            g_free(sourcepath);
-        } else {
-            cons_show("Either a path must be provided or the sourcepath property must be set, see /help plugins");
-            return TRUE;
-        }
-    } else {
-        path = get_expanded_path(args[1]);
-    }
-
     if (is_regular_file(path)) {
         if (!g_str_has_suffix(path, ".py") && !g_str_has_suffix(path, ".so")) {
             cons_show("Plugins must have one of the following extensions: '.py' '.so'");
@@ -6997,7 +6965,7 @@ cmd_plugins_install(ProfWin* window, const char* const command, gchar** args)
         gchar* plugin_name = g_path_get_basename(path);
         gboolean result = plugins_install(plugin_name, path, error_message);
         if (result) {
-            cons_show("Plugin installed: %s", plugin_name);
+            cons_show("Plugin installed and loaded: %s", plugin_name);
         } else {
             cons_show("Failed to install plugin: %s. %s", plugin_name, error_message->str);
         }
@@ -7010,7 +6978,7 @@ cmd_plugins_install(ProfWin* window, const char* const command, gchar** args)
         if (result->installed || result->failed) {
             if (result->installed) {
                 cons_show("");
-                cons_show("Installed plugins:");
+                cons_show("Installed and loaded plugins:");
                 GSList* curr = result->installed;
                 while (curr) {
                     cons_show("  %s", curr->data);
@@ -7046,14 +7014,8 @@ cmd_plugins_update(ProfWin* window, const char* const command, gchar** args)
     char* path;
 
     if (args[1] == NULL) {
-        char* sourcepath = prefs_get_string(PREF_PLUGINS_SOURCEPATH);
-        if (sourcepath) {
-            path = strdup(sourcepath);
-            g_free(sourcepath);
-        } else {
-            cons_show("Either a path must be provided or the sourcepath property must be set, see /help plugins");
-            return TRUE;
-        }
+        cons_show("Please provide a path to the plugin file, see /help plugins");
+        return TRUE;
     } else {
         path = get_expanded_path(args[1]);
     }
@@ -7092,13 +7054,8 @@ cmd_plugins_update(ProfWin* window, const char* const command, gchar** args)
         return TRUE;
     }
 
-    if (is_dir(path)) {
-        free(path);
-        return FALSE;
-    }
-
     free(path);
-    cons_show("Argument must be a file or directory.");
+    cons_show("Argument must be a file.");
     return TRUE;
 }
 
@@ -7210,6 +7167,42 @@ cmd_plugins_python_version(ProfWin* window, const char* const command, gchar** a
 gboolean
 cmd_plugins(ProfWin* window, const char* const command, gchar** args)
 {
+    GDir* global_pyp_dir = NULL;
+    GDir* global_cp_dir = NULL;
+
+    if (access(GLOBAL_PYTHON_PLUGINS_PATH, R_OK) == 0) {
+        GError* error = NULL;
+        global_pyp_dir = g_dir_open(GLOBAL_PYTHON_PLUGINS_PATH, 0, &error);
+        if (error) {
+            log_warning("Error when trying to open global plugins path: %s", GLOBAL_PYTHON_PLUGINS_PATH);
+            g_error_free(error);
+            return TRUE;
+        }
+    }
+    if (access(GLOBAL_C_PLUGINS_PATH, R_OK) == 0) {
+        GError* error = NULL;
+        global_cp_dir = g_dir_open(GLOBAL_C_PLUGINS_PATH, 0, &error);
+        if (error) {
+            log_warning("Error when trying to open global plugins path: %s", GLOBAL_C_PLUGINS_PATH);
+            g_error_free(error);
+            return TRUE;
+        }
+    }
+    if (global_pyp_dir) {
+        const gchar *filename;
+        cons_show("The following Python plugins are available globally and can be installed:");
+        while ((filename = g_dir_read_name(global_pyp_dir))) {
+            cons_show("  %s", filename);
+        }
+    }
+    if (global_cp_dir) {
+        const gchar *filename;
+        cons_show("The following C plugins are available globally and can be installed:");
+        while ((filename = g_dir_read_name(global_cp_dir))) {
+            cons_show("  %s", filename);
+        }
+    }
+
     GList* plugins = plugins_loaded_list();
     if (plugins == NULL) {
         cons_show("No plugins installed.");
diff --git a/src/config/preferences.c b/src/config/preferences.c
index df23efe6..114455fd 100644
--- a/src/config/preferences.c
+++ b/src/config/preferences.c
@@ -214,6 +214,11 @@ _prefs_load(void)
         }
     }
 
+    // 0.12 started to remove `sourcepath`
+    if (g_key_file_has_key(prefs, PREF_GROUP_PLUGINS, "sourcepath", NULL)) {
+        g_key_file_remove_key(prefs, PREF_GROUP_PLUGINS, "sourcepath", NULL);
+    }
+
     _save_prefs();
 
     boolean_choice_ac = autocomplete_new();
@@ -1928,8 +1933,6 @@ _get_group(preference_t pref)
     case PREF_BOOKMARK_INVITE:
     case PREF_ROOM_LIST_CACHE:
         return PREF_GROUP_MUC;
-    case PREF_PLUGINS_SOURCEPATH:
-        return PREF_GROUP_PLUGINS;
     case PREF_OMEMO_LOG:
     case PREF_OMEMO_POLICY:
     case PREF_OMEMO_TRUST_MODE:
@@ -2163,8 +2166,6 @@ _get_key(preference_t pref)
         return "color.occupants.nick";
     case PREF_BOOKMARK_INVITE:
         return "bookmark.invite";
-    case PREF_PLUGINS_SOURCEPATH:
-        return "sourcepath";
     case PREF_ROOM_LIST_CACHE:
         return "rooms.cache";
     case PREF_STATUSBAR_SHOW_NAME:
diff --git a/src/config/preferences.h b/src/config/preferences.h
index f7474c1f..30bd434a 100644
--- a/src/config/preferences.h
+++ b/src/config/preferences.h
@@ -157,7 +157,6 @@ typedef enum {
     PREF_ROSTER_COLOR_NICK,
     PREF_OCCUPANTS_COLOR_NICK,
     PREF_BOOKMARK_INVITE,
-    PREF_PLUGINS_SOURCEPATH,
     PREF_ROOM_LIST_CACHE,
     PREF_STATUSBAR_SHOW_NAME,
     PREF_STATUSBAR_SHOW_NUMBER,