diff options
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/script/script-action.c | 236 | ||||
-rw-r--r-- | src/plugins/script/script-buffer.c | 44 | ||||
-rw-r--r-- | src/plugins/script/script-buffer.h | 5 | ||||
-rw-r--r-- | src/plugins/script/script-command.c | 11 | ||||
-rw-r--r-- | src/plugins/script/script-config.c | 73 | ||||
-rw-r--r-- | src/plugins/script/script-config.h | 3 | ||||
-rw-r--r-- | src/plugins/script/script-repo.c | 56 | ||||
-rw-r--r-- | src/plugins/script/script-repo.h | 1 |
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); |