summaryrefslogtreecommitdiff
path: root/src/plugins/script
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/script')
-rw-r--r--src/plugins/script/script-action.c236
-rw-r--r--src/plugins/script/script-buffer.c44
-rw-r--r--src/plugins/script/script-buffer.h5
-rw-r--r--src/plugins/script/script-command.c11
-rw-r--r--src/plugins/script/script-config.c73
-rw-r--r--src/plugins/script/script-config.h3
-rw-r--r--src/plugins/script/script-repo.c56
-rw-r--r--src/plugins/script/script-repo.h1
8 files changed, 378 insertions, 51 deletions
diff --git a/src/plugins/script/script-action.c b/src/plugins/script/script-action.c
index 387dfea45..a55a87fdf 100644
--- a/src/plugins/script/script-action.c
+++ b/src/plugins/script/script-action.c
@@ -26,6 +26,8 @@
#include <string.h>
#include <stdio.h>
#include <libgen.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include "../weechat-plugin.h"
#include "script.h"
@@ -661,19 +663,114 @@ script_action_hold (const char *name, int quiet)
}
/*
- * script_action_show_process_cb: callback called when script is downloaded
- * (for showing source code below script detail)
+ * script_action_show_diff_process_cb: callback called when script is
+ * downloaded (for showing source code
+ * below script detail)
*/
int
-script_action_show_process_cb (void *data, const char *command,
- int return_code, const char *out,
- const char *err)
+script_action_show_diff_process_cb (void *data, const char *command,
+ int return_code, const char *out,
+ const char *err)
{
- char *pos, *filename, line[4096], *ptr_line;
+ char **lines, *filename;
+ const char *color;
+ int num_lines, i, diff_color;
+
+ /* make C compiler happy */
+ (void) command;
+
+ if (script_buffer && script_buffer_detail_script
+ && ((return_code == WEECHAT_HOOK_PROCESS_RUNNING) || (return_code >= 0)))
+ {
+ if (out)
+ {
+ lines = weechat_string_split (out, "\n", 0, 0, &num_lines);
+ if (lines)
+ {
+ diff_color = weechat_config_boolean (script_config_look_diff_color);
+ for (i = 0; i < num_lines; i++)
+ {
+ color = NULL;
+ if (diff_color)
+ {
+ switch (lines[i][0])
+ {
+ case '-':
+ case '<':
+ color = weechat_color ("red");
+ break;
+ case '+':
+ case '>':
+ color = weechat_color ("green");
+ break;
+ case '@':
+ color = weechat_color ("cyan");
+ break;
+ }
+ }
+ weechat_printf_y (script_buffer,
+ script_buffer_detail_script_last_line++,
+ "%s%s",
+ (color) ? color : "",
+ lines[i]);
+ }
+ weechat_string_free_split (lines);
+ }
+ }
+ else if (err)
+ {
+ lines = weechat_string_split (err, "\n", 0, 0, &num_lines);
+ if (lines)
+ {
+ for (i = 0; i < num_lines; i++)
+ {
+ weechat_printf_y (script_buffer,
+ script_buffer_detail_script_last_line++,
+ "%s",
+ lines[i]);
+ }
+ weechat_string_free_split (lines);
+ }
+ }
+ if (return_code >= 0)
+ {
+ weechat_printf_y (script_buffer,
+ script_buffer_detail_script_last_line++,
+ "%s----------------------------------------"
+ "----------------------------------------",
+ weechat_color ("magenta"));
+ }
+ }
+
+ if ((return_code == WEECHAT_HOOK_PROCESS_ERROR) || (return_code >= 0))
+ {
+ /* last call to this callback: delete temporary file */
+ filename = (char *)data;
+ unlink (filename);
+ free (filename);
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * script_action_show_source_process_cb: callback called when script is
+ * downloaded (for showing source code
+ * below script detail)
+ */
+
+int
+script_action_show_source_process_cb (void *data, const char *command,
+ int return_code, const char *out,
+ const char *err)
+{
+ char *pos, *filename, *filename_loaded, line[4096], *ptr_line;
+ char *diff_command;
+ const char *ptr_diff_command;
struct t_repo_script *ptr_script;
FILE *file;
- int line_y;
+ int length, diff_made;
/* make C compiler happy */
(void) data;
@@ -699,7 +796,7 @@ script_action_show_process_cb (void *data, const char *command,
if (ptr_script)
{
filename = script_config_get_script_download_filename (ptr_script,
- ".tmp");
+ ".repository");
if (filename)
{
/*
@@ -710,7 +807,6 @@ script_action_show_process_cb (void *data, const char *command,
if (script_buffer && script_buffer_detail_script
&& (script_buffer_detail_script == ptr_script))
{
- line_y = script_buffer_detail_script_line_source + 2;
file = fopen (filename, "r");
if (file)
{
@@ -719,27 +815,74 @@ script_action_show_process_cb (void *data, const char *command,
ptr_line = fgets (line, sizeof (line) - 1, file);
if (ptr_line)
{
- weechat_printf_y (script_buffer, line_y,
+ weechat_printf_y (script_buffer,
+ script_buffer_detail_script_last_line++,
"%s", ptr_line);
- line_y++;
}
}
fclose (file);
}
else
{
- weechat_printf_y (script_buffer, line_y,
+ weechat_printf_y (script_buffer,
+ script_buffer_detail_script_last_line++,
_("Error: file not found"));
- line_y++;
}
- weechat_printf_y (script_buffer, line_y,
+ weechat_printf_y (script_buffer,
+ script_buffer_detail_script_last_line++,
"%s----------------------------------------"
"----------------------------------------",
- weechat_color ("green"));
- line_y++;
+ weechat_color ("lightcyan"));
+ }
+ diff_made = 0;
+ ptr_diff_command = script_config_get_diff_command ();
+ if (ptr_diff_command && ptr_diff_command[0]
+ && (ptr_script->status & SCRIPT_STATUS_NEW_VERSION))
+ {
+ /*
+ * diff command set => get the diff with a new process,
+ * file will be deleted later (in callback of this new
+ * process)
+ */
+ filename_loaded = script_repo_get_filename_loaded (ptr_script);
+ if (filename_loaded)
+ {
+ length = strlen (ptr_diff_command) + 1
+ + strlen (filename_loaded) + 1
+ + strlen (filename) + 1;
+ diff_command = malloc (length);
+ if (diff_command)
+ {
+ snprintf (diff_command, length,
+ "%s %s %s",
+ ptr_diff_command,
+ filename_loaded,
+ filename);
+ script_buffer_detail_script_last_line++;
+ script_buffer_detail_script_line_diff = script_buffer_detail_script_last_line;
+ weechat_printf_y (script_buffer,
+ script_buffer_detail_script_last_line++,
+ "%s", diff_command);
+ weechat_printf_y (script_buffer,
+ script_buffer_detail_script_last_line++,
+ "%s----------------------------------------"
+ "----------------------------------------",
+ weechat_color ("magenta"));
+ weechat_hook_process (diff_command, 10000,
+ &script_action_show_diff_process_cb,
+ filename);
+ diff_made = 1;
+ free (diff_command);
+ }
+ free (filename_loaded);
+ }
+ }
+ if (!diff_made)
+ {
+ /* no diff made: delete temporary file now */
+ unlink (filename);
+ free (filename);
}
- unlink (filename);
- free (filename);
}
}
}
@@ -769,23 +912,23 @@ script_action_show (const char *name, int quiet)
if (weechat_config_boolean (script_config_look_display_source))
{
weechat_printf_y (script_buffer,
- script_buffer_detail_script_line_source,
+ script_buffer_detail_script_last_line++,
_("Source code:"));
weechat_printf_y (script_buffer,
- script_buffer_detail_script_line_source + 1,
+ script_buffer_detail_script_last_line++,
"%s----------------------------------------"
"----------------------------------------",
- weechat_color ("green"));
+ weechat_color ("lightcyan"));
weechat_printf_y (script_buffer,
- script_buffer_detail_script_line_source + 2,
+ script_buffer_detail_script_last_line,
_("Downloading script..."));
weechat_printf_y (script_buffer,
- script_buffer_detail_script_line_source + 3,
+ script_buffer_detail_script_last_line + 1,
"%s----------------------------------------"
"----------------------------------------",
- weechat_color ("green"));
+ weechat_color ("lightcyan"));
filename = script_config_get_script_download_filename (ptr_script,
- ".tmp");
+ ".repository");
if (filename)
{
options = weechat_hashtable_new (8,
@@ -802,7 +945,7 @@ script_action_show (const char *name, int quiet)
snprintf (url, length, "url:%s", ptr_script->url);
weechat_hashtable_set (options, "file_out", filename);
weechat_hook_process_hashtable (url, options, 30000,
- &script_action_show_process_cb,
+ &script_action_show_source_process_cb,
NULL);
free (url);
}
@@ -827,6 +970,43 @@ script_action_show (const char *name, int quiet)
}
/*
+ * script_action_showdiff: jump to diff on buffer with detail of script
+ */
+
+void
+script_action_showdiff ()
+{
+ char str_command[64];
+ struct t_gui_window *window;
+ int diff, start_line_y, chat_height;
+
+ if (script_buffer && script_buffer_detail_script
+ && (script_buffer_detail_script_line_diff >= 0))
+ {
+ /* check if we are already on diff */
+ diff = 0;
+ window = weechat_window_search_with_buffer (script_buffer);
+ if (window)
+ {
+ script_buffer_get_window_info (window, &start_line_y, &chat_height);
+ diff = (start_line_y == script_buffer_detail_script_line_diff);
+ }
+
+ /* scroll to top of window */
+ weechat_command (script_buffer, "/window scroll_top");
+
+ /* if not currently on diff, jump to it */
+ if (!diff)
+ {
+ snprintf (str_command, sizeof (str_command),
+ "/window scroll %d",
+ script_buffer_detail_script_line_diff);
+ weechat_command (script_buffer, str_command);
+ }
+ }
+}
+
+/*
* script_action_run: run planned actions
* return 1 if an action was executed, otherwise 0
*/
@@ -1017,6 +1197,10 @@ script_action_run ()
quiet);
weechat_buffer_set (script_buffer, "display", "1");
}
+ else if (weechat_strcasecmp (argv[0], "showdiff") == 0)
+ {
+ script_action_showdiff ();
+ }
else if (weechat_strcasecmp (argv[0], "upgrade") == 0)
{
script_found = 0;
diff --git a/src/plugins/script/script-buffer.c b/src/plugins/script/script-buffer.c
index 239c8a01c..1be10b02e 100644
--- a/src/plugins/script/script-buffer.c
+++ b/src/plugins/script/script-buffer.c
@@ -36,7 +36,8 @@
struct t_gui_buffer *script_buffer = NULL;
int script_buffer_selected_line = 0;
struct t_repo_script *script_buffer_detail_script = NULL;
-int script_buffer_detail_script_line_source = 0;
+int script_buffer_detail_script_last_line = 0;
+int script_buffer_detail_script_line_diff = -1;
/*
@@ -475,7 +476,8 @@ script_buffer_display_detail_script (struct t_repo_script *script)
(script->max_weechat) ? script->max_weechat : "-");
line++;
- script_buffer_detail_script_line_source = line + 2;
+ script_buffer_detail_script_last_line = line + 2;
+ script_buffer_detail_script_line_diff = -1;
}
/*
@@ -502,14 +504,14 @@ script_buffer_refresh (int clear)
{
snprintf (str_title, sizeof (str_title),
"%s",
- _("alt+d=back to list"));
+ _("Alt+key/input: v=back to list d=jump to diff"));
}
else
{
snprintf (str_title, sizeof (str_title),
_("%d/%d scripts (filter: %s) | Sort: %s | "
"Alt+key/input: i=install r=remove l=load L=reload "
- "u=unload h=(un)hold d=show detail | Input: q=close "
+ "u=unload h=(un)hold v=view script | Input: q=close "
"$=refresh s:x,y=sort words=filter *=reset filter | "
"Mouse: left=select right=install/remove"),
script_repo_count_displayed,
@@ -704,14 +706,15 @@ int
script_buffer_input_cb (void *data, struct t_gui_buffer *buffer,
const char *input_data)
{
- char *actions[][2] = { { "l", "load" },
- { "u", "unload" },
- { "L", "reload" },
- { "i", "install" },
- { "r", "remove" },
- { "h", "hold" },
- { "d", "show" },
- { NULL, NULL } };
+ char *actions[][2] = { { "l", "load" },
+ { "u", "unload" },
+ { "L", "reload" },
+ { "i", "install" },
+ { "r", "remove" },
+ { "h", "hold" },
+ { "v", "show" },
+ { "d", "showdiff" },
+ { NULL, NULL } };
char str_command[64];
int i;
@@ -811,14 +814,15 @@ script_buffer_set_callbacks ()
void
script_buffer_set_keys ()
{
- char *keys[][2] = { { "meta-l", "load" },
- { "meta-u", "unload" },
- { "meta-L", "reload" },
- { "meta-i", "install" },
- { "meta-r", "remove" },
- { "meta-h", "hold" },
- { "meta-d", "show" },
- { NULL, NULL } };
+ char *keys[][2] = { { "meta-l", "load" },
+ { "meta-u", "unload" },
+ { "meta-L", "reload" },
+ { "meta-i", "install" },
+ { "meta-r", "remove" },
+ { "meta-h", "hold" },
+ { "meta-v", "show" },
+ { "meta-d", "showdiff" },
+ { NULL, NULL } };
char str_key[64], str_command[64];
int i;
diff --git a/src/plugins/script/script-buffer.h b/src/plugins/script/script-buffer.h
index 7fbd1dfc5..407c66460 100644
--- a/src/plugins/script/script-buffer.h
+++ b/src/plugins/script/script-buffer.h
@@ -27,11 +27,14 @@ struct t_repo_script;
extern struct t_gui_buffer *script_buffer;
extern int script_buffer_selected_line;
extern struct t_repo_script *script_buffer_detail_script;
-extern int script_buffer_detail_script_line_source;
+extern int script_buffer_detail_script_last_line;
+extern int script_buffer_detail_script_line_diff;
extern void script_buffer_refresh (int clear);
extern void script_buffer_set_current_line (int line);
extern void script_buffer_show_detail_script (struct t_repo_script *script);
+extern void script_buffer_get_window_info (struct t_gui_window *window,
+ int *start_line_y, int *chat_height);
extern void script_buffer_check_line_outside_window ();
extern int script_buffer_window_scrolled_cb (void *data, const char *signal,
const char *type_data,
diff --git a/src/plugins/script/script-command.c b/src/plugins/script/script-command.c
index b92e3039b..6f3ae7d5d 100644
--- a/src/plugins/script/script-command.c
+++ b/src/plugins/script/script-command.c
@@ -89,8 +89,9 @@ script_command_action (struct t_gui_buffer *buffer, const char *action,
else if (script_buffer && (buffer == script_buffer))
{
/* action on current line of script buffer */
- if ((weechat_strcasecmp (action, "show") == 0)
- && script_buffer_detail_script)
+ if (script_buffer_detail_script
+ && ((weechat_strcasecmp (action, "show") == 0)
+ || (weechat_strcasecmp (action, "showdiff") == 0)))
{
/* if detail on script is displayed, back to list */
snprintf (str_action, sizeof (str_action),
@@ -183,7 +184,8 @@ script_command_script (void *data, struct t_gui_buffer *buffer, int argc,
|| (weechat_strcasecmp (argv[1], "remove") == 0)
|| (weechat_strcasecmp (argv[1], "installremove") == 0)
|| (weechat_strcasecmp (argv[1], "hold") == 0)
- || (weechat_strcasecmp (argv[1], "show") == 0))
+ || (weechat_strcasecmp (argv[1], "show") == 0)
+ || (weechat_strcasecmp (argv[1], "showdiff") == 0))
{
script_command_action (buffer,
argv[1],
@@ -318,7 +320,8 @@ script_command_init ()
" alt+l load script\n"
" alt+L reload script\n"
" alt+u unload script\n"
- " alt+h (un)hold script\n\n"
+ " alt+h (un)hold script\n"
+ " alt+v view script\n\n"
"Input allowed on script buffer:\n"
" i/r/l/L/u/h action on script (same as keys above)\n"
" q close buffer\n"
diff --git a/src/plugins/script/script-config.c b/src/plugins/script/script-config.c
index 92af46600..cedda6f42 100644
--- a/src/plugins/script/script-config.c
+++ b/src/plugins/script/script-config.c
@@ -22,8 +22,11 @@
*/
#include <stdlib.h>
+#include <unistd.h>
#include <stdio.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include "../weechat-plugin.h"
#include "script.h"
@@ -40,6 +43,8 @@ struct t_config_section *script_config_section_scripts = NULL;
/* script config, look section */
struct t_config_option *script_config_look_columns;
+struct t_config_option *script_config_look_diff_color;
+struct t_config_option *script_config_look_diff_command;
struct t_config_option *script_config_look_display_source;
struct t_config_option *script_config_look_quiet_actions;
struct t_config_option *script_config_look_sort;
@@ -84,6 +89,59 @@ struct t_config_option *script_config_scripts_url;
/*
+ * script_config_get_diff_command: get diff command
+ * if option is "auto", try to find git, and
+ * fallbacks on "diff" if not found
+ * return NULL if no diff command is set
+ */
+
+const char *
+script_config_get_diff_command ()
+{
+ const char *diff_command, *dir_separator;
+ static char result[64];
+ struct stat st;
+ char *path, **paths, bin[4096];
+ int num_paths, i, rc;
+
+ diff_command = weechat_config_string (script_config_look_diff_command);
+ if (!diff_command || !diff_command[0])
+ return NULL;
+
+ if (strcmp (diff_command, "auto") == 0)
+ {
+ dir_separator = weechat_info_get ("dir_separator", "");
+ path = getenv ("PATH");
+ result[0] = '\0';
+ if (dir_separator && path)
+ {
+ paths = weechat_string_split (path, ":", 0, 0, &num_paths);
+ if (paths)
+ {
+ for (i = 0; i < num_paths; i++)
+ {
+ snprintf (bin, sizeof (bin), "%s%s%s",
+ paths[i], dir_separator, "git");
+ rc = stat (bin, &st);
+ if ((rc == 0) && (S_ISREG(st.st_mode)))
+ {
+ snprintf (result, sizeof (result),
+ "git diff --no-index");
+ break;
+ }
+ }
+ weechat_string_free_split (paths);
+ }
+ }
+ if (!result[0])
+ snprintf (result, sizeof (result), "diff");
+ return result;
+ }
+
+ return diff_command;
+}
+
+/*
* script_config_get_dir: get local directory for script
* Note: result must be freed after use
*/
@@ -370,6 +428,21 @@ script_config_init ()
"%W=max_weechat)"),
NULL, 0, 0, "%s %n %V %v %u | %d | %t", NULL, 0,
NULL, NULL, &script_config_refresh_cb, NULL, NULL, NULL);
+ script_config_look_diff_color = weechat_config_new_option (
+ script_config_file, ptr_section,
+ "diff_color", "boolean",
+ N_("colorize output of diff"),
+ NULL, 0, 0, "on", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ script_config_look_diff_command = weechat_config_new_option (
+ script_config_file, ptr_section,
+ "diff_command", "string",
+ N_("command used to show differences between script installed and the "
+ "new version in repository (\"auto\" = auto detect diff command (git "
+ "or diff), empty value = disable diff, other string = name of "
+ "command, for example \"diff\")"),
+ NULL, 0, 0, "auto", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL);
script_config_look_display_source = weechat_config_new_option (
script_config_file, ptr_section,
"display_source", "boolean",
diff --git a/src/plugins/script/script-config.h b/src/plugins/script/script-config.h
index dcaded263..af54eed2b 100644
--- a/src/plugins/script/script-config.h
+++ b/src/plugins/script/script-config.h
@@ -25,6 +25,8 @@
struct t_repo_script;
extern struct t_config_option *script_config_look_columns;
+extern struct t_config_option *script_config_look_diff_color;
+extern struct t_config_option *script_config_look_diff_command;
extern struct t_config_option *script_config_look_display_source;
extern struct t_config_option *script_config_look_quiet_actions;
extern struct t_config_option *script_config_look_sort;
@@ -63,6 +65,7 @@ extern struct t_config_option *script_config_scripts_dir;
extern struct t_config_option *script_config_scripts_hold;
extern struct t_config_option *script_config_scripts_url;
+extern const char *script_config_get_diff_command ();
extern char *script_config_get_dir ();
extern char *script_config_get_xml_filename ();
extern char *script_config_get_script_download_filename (struct t_repo_script *script,
diff --git a/src/plugins/script/script-repo.c b/src/plugins/script/script-repo.c
index 4d5be3fe5..5b140eb63 100644
--- a/src/plugins/script/script-repo.c
+++ b/src/plugins/script/script-repo.c
@@ -23,6 +23,7 @@
#define _XOPEN_SOURCE 700
+#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
@@ -147,6 +148,61 @@ script_repo_search_by_name_ext (const char *name_with_extension)
}
/*
+ * script_repo_get_filename_loaded: get filename of a loaded script
+ * (it returns name of file and not the link,
+ * if there is a symbolic to file)
+ * Note: result has to be free() after use
+ */
+
+char *
+script_repo_get_filename_loaded (struct t_repo_script *script)
+{
+ const char *weechat_home;
+ char *filename, resolved_path[PATH_MAX];
+ int length;
+ struct stat st;
+
+ weechat_home = weechat_info_get ("weechat_dir", NULL);
+ length = strlen (weechat_home) + strlen (script->name_with_extension) + 64;
+ filename = malloc (length);
+ if (filename)
+ {
+ snprintf (filename, length, "%s/%s/autoload/%s",
+ weechat_home,
+ script_language[script->language],
+ script->name_with_extension);
+ if (stat (filename, &st) != 0)
+ {
+ snprintf (filename, length, "%s/%s/%s",
+ weechat_home,
+ script_language[script->language],
+ script->name_with_extension);
+ if (stat (filename, &st) != 0)
+ {
+ filename[0] = '\0';
+ }
+ }
+ }
+
+ if (!filename[0])
+ {
+ free (filename);
+ return NULL;
+ }
+
+ if (realpath (filename, resolved_path))
+ {
+ if (strcmp (filename, resolved_path) != 0)
+ {
+ free (filename);
+ return strdup (resolved_path);
+ }
+ }
+
+ return filename;
+}
+
+/*
* script_repo_get_status_for_display: get status for display
* list is the codes of status to display
* (exemple: "*iaHrN" for all status)
diff --git a/src/plugins/script/script-repo.h b/src/plugins/script/script-repo.h
index 5f8b97298..588f5644f 100644
--- a/src/plugins/script/script-repo.h
+++ b/src/plugins/script/script-repo.h
@@ -64,6 +64,7 @@ extern int script_repo_script_valid (struct t_repo_script *script);
extern struct t_repo_script *script_repo_search_displayed_by_number (int number);
extern struct t_repo_script *script_repo_search_by_name (const char *name);
extern struct t_repo_script *script_repo_search_by_name_ext (const char *name_with_extension);
+extern char *script_repo_get_filename_loaded (struct t_repo_script *script);
extern const char *script_repo_get_status_for_display (struct t_repo_script *script,
const char *list,
int collapse);