From 8be8f75b874ddbeddb070e9efda6d12b2230d646 Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 15 Feb 2021 19:47:21 +0100 Subject: [PATCH 1/8] Add new editor command Goal is to launch an external editor (eg vim) to edit the text there. --- src/command/cmd_defs.c | 14 ++++++++++++++ src/command/cmd_funcs.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/command/cmd_funcs.h | 1 + 3 files changed, 55 insertions(+) diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 730169ba..9eaf3f39 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2586,6 +2586,20 @@ static struct cmd_t command_defs[] = { CMD_NOEXAMPLES }, + { "/editor", + parse_args, 0, 0, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_editor) + CMD_TAGS( + CMD_TAG_CHAT) + CMD_SYN( + "/editor") + CMD_DESC( + "Call editor") + CMD_NOARGS + CMD_NOEXAMPLES + }, + // NEXT-COMMAND (search helper) }; diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 90c41dfd..cd6d8308 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -52,6 +52,12 @@ #include #include +// fork / execl +#include +#include +#include +#include + #include "profanity.h" #include "log.h" #include "common.h" @@ -9304,3 +9310,37 @@ cmd_change_password(ProfWin* window, const char* const command, gchar** args) return TRUE; } + +gboolean +cmd_editor(ProfWin* window, const char* const command, gchar** args) +{ + const char* filename = "/tmp/profanity.txt"; + pid_t pid = fork(); + if( pid == 0 ) { + int x = execl("/usr/bin/vim", "/usr/bin/vim", filename, (char *) NULL); + if ( x == -1 ) { + cons_show_error("Failed to exec vim"); + } + } else { + int status = 0; + waitpid(pid, &status, 0); + ui_redraw(); + + int fd_input_file = open(filename, O_RDONLY); + const size_t COUNT = 8192; + char buf[COUNT]; + ssize_t size_read = read(fd_input_file, buf, COUNT); + if(size_read > 0 && size_read <= COUNT ) { + buf[size_read-1] = '\0'; + GString* text = g_string_new(buf); + //ProfWin* window = wins_get_current(); + //cmd_process_input(window, text->str); + rl_insert_text(text->str); + g_string_free(text, TRUE); + } + close(fd_input_file); + ui_redraw(); + } + + return TRUE; +} diff --git a/src/command/cmd_funcs.h b/src/command/cmd_funcs.h index 5a192efb..f4ca72ed 100644 --- a/src/command/cmd_funcs.h +++ b/src/command/cmd_funcs.h @@ -242,5 +242,6 @@ gboolean cmd_executable_avatar(ProfWin* window, const char* const command, gchar gboolean cmd_executable_urlopen(ProfWin* window, const char* const command, gchar** args); gboolean cmd_executable_urlsave(ProfWin* window, const char* const command, gchar** args); gboolean cmd_mam(ProfWin* window, const char* const command, gchar** args); +gboolean cmd_editor(ProfWin* window, const char* const command, gchar** args); #endif From 35b0b0f19479436d980ef20bfe2ff26a0a19f9ea Mon Sep 17 00:00:00 2001 From: Stefan Date: Sun, 11 Apr 2021 09:06:21 +0200 Subject: [PATCH 2/8] Editor command: filename / sensible-editor * Generating a unique file name in tmp_dir folder * Changed exec of vim to exec of sensible-editor * Test file exists and create file with "private" rights * Send a preview of the message in the window * Delete temp file --- src/command/cmd_funcs.c | 59 ++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index cd6d8308..c85b6c78 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -9314,33 +9314,74 @@ cmd_change_password(ProfWin* window, const char* const command, gchar** args) gboolean cmd_editor(ProfWin* window, const char* const command, gchar** args) { - const char* filename = "/tmp/profanity.txt"; + /* Build temp file name */ + GString * tempfile = g_string_new(g_get_tmp_dir()); + g_string_append(tempfile, "/profanity-"); + xmpp_ctx_t* const ctx = connection_get_ctx(); + if(!ctx) { + cons_show("Editor: Not connection"); + return TRUE; + } + char* uuid = xmpp_uuid_gen(ctx); + g_string_append(tempfile, uuid); + if (uuid) { + xmpp_free(ctx, uuid); + } + g_string_append(tempfile, ".txt"); + + // tempfile should be something like + // /tmp/profanity-f2f271dd-98c8-4118-8d47-3bd49c8e2e63.txt + const char* filename = tempfile->str; + + // Check if file exists and create file + if (g_file_test(filename, G_FILE_TEST_EXISTS)) { + cons_show("Editor: The temp file exists"); + g_string_free (tempfile, TRUE); + return TRUE; + } + + GError* creation_error = NULL; + GFile* file = g_file_new_for_path(filename); + GFileOutputStream* fos = g_file_create (file, + G_FILE_CREATE_PRIVATE, NULL, + &creation_error); + if ( creation_error ) { + cons_show("Editor: Error during file creation"); + return TRUE; + } + g_object_unref(fos); + + // Fork / exec pid_t pid = fork(); if( pid == 0 ) { - int x = execl("/usr/bin/vim", "/usr/bin/vim", filename, (char *) NULL); + int x = execl("/usr/bin/sensible-editor", "/usr/bin/sensible-editor", g_file_get_path(file), (char *) NULL); if ( x == -1 ) { - cons_show_error("Failed to exec vim"); + cons_show_error("Failed to exec sensible-editor"); } } else { int status = 0; waitpid(pid, &status, 0); - ui_redraw(); - - int fd_input_file = open(filename, O_RDONLY); + int fd_input_file = open(g_file_get_path(file), O_RDONLY); const size_t COUNT = 8192; char buf[COUNT]; ssize_t size_read = read(fd_input_file, buf, COUNT); if(size_read > 0 && size_read <= COUNT ) { buf[size_read-1] = '\0'; GString* text = g_string_new(buf); - //ProfWin* window = wins_get_current(); - //cmd_process_input(window, text->str); + ProfWin* win = wins_get_current(); + win_println(win, THEME_DEFAULT, "!", "EDITOR PREVIEW: %s", text->str); rl_insert_text(text->str); g_string_free(text, TRUE); } close(fd_input_file); ui_redraw(); + GError* deletion_error = NULL; + g_file_delete (file, NULL, &deletion_error); + if ( deletion_error ) { + cons_show("Editor: Error during file deletion"); + return TRUE; + } + g_object_unref(file); } - return TRUE; } From 9f32b2afb264a7621a8ac660a84e2d72a4a1a44a Mon Sep 17 00:00:00 2001 From: Stefan Date: Sun, 11 Apr 2021 16:21:00 +0200 Subject: [PATCH 3/8] Editor: Using preferences compose.editor compose.editor is the path to the executable ( default /usr/bin/vim ) --- src/command/cmd_funcs.c | 28 +++++++++++++++++++--------- src/config/preferences.c | 5 +++++ src/config/preferences.h | 1 + 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index c85b6c78..7aeb15f0 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -9346,19 +9346,29 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) G_FILE_CREATE_PRIVATE, NULL, &creation_error); if ( creation_error ) { - cons_show("Editor: Error during file creation"); + cons_show_error("Editor: Error during file creation"); return TRUE; } g_object_unref(fos); + char* editor = prefs_get_string(PREF_COMPOSE_EDITOR); + if (!g_file_test(editor, G_FILE_TEST_EXISTS)) { + cons_show_error("Editor: editor %s not exists", editor); + return TRUE; + } + // Fork / exec pid_t pid = fork(); if( pid == 0 ) { - int x = execl("/usr/bin/sensible-editor", "/usr/bin/sensible-editor", g_file_get_path(file), (char *) NULL); + int x = execl(editor, editor, g_file_get_path(file), (char *) NULL); if ( x == -1 ) { - cons_show_error("Failed to exec sensible-editor"); + cons_show_error("Failed to exec %s", editor); } + exit (EXIT_FAILURE); } else { + if ( pid == -1 ) { + return TRUE; + } int status = 0; waitpid(pid, &status, 0); int fd_input_file = open(g_file_get_path(file), O_RDONLY); @@ -9366,12 +9376,12 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) char buf[COUNT]; ssize_t size_read = read(fd_input_file, buf, COUNT); if(size_read > 0 && size_read <= COUNT ) { - buf[size_read-1] = '\0'; - GString* text = g_string_new(buf); - ProfWin* win = wins_get_current(); - win_println(win, THEME_DEFAULT, "!", "EDITOR PREVIEW: %s", text->str); - rl_insert_text(text->str); - g_string_free(text, TRUE); + buf[size_read-1] = '\0'; + GString* text = g_string_new(buf); + ProfWin* win = wins_get_current(); + win_println(win, THEME_DEFAULT, "!", "EDITOR PREVIEW: %s", text->str); + rl_insert_text(text->str); + g_string_free(text, TRUE); } close(fd_input_file); ui_redraw(); diff --git a/src/config/preferences.c b/src/config/preferences.c index f09cb746..a11a5d42 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -1868,6 +1868,7 @@ _get_group(preference_t pref) case PREF_TITLEBAR_MUC_TITLE_JID: case PREF_TITLEBAR_MUC_TITLE_NAME: case PREF_SLASH_GUARD: + case PREF_COMPOSE_EDITOR: return PREF_GROUP_UI; case PREF_STATES: case PREF_OUTTYPE: @@ -2189,6 +2190,8 @@ _get_key(preference_t pref) return "url.open.cmd"; case PREF_URL_SAVE_CMD: return "url.save.cmd"; + case PREF_COMPOSE_EDITOR: + return "compose.editor"; default: return NULL; } @@ -2326,6 +2329,8 @@ _get_default_string(preference_t pref) return "xdg-open"; case PREF_URL_OPEN_CMD: return "xdg-open %u"; + case PREF_COMPOSE_EDITOR: + return "/usr/bin/vim"; case PREF_URL_SAVE_CMD: return NULL; // Default to built-in method. default: diff --git a/src/config/preferences.h b/src/config/preferences.h index 49c2c438..4e254917 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -173,6 +173,7 @@ typedef enum { PREF_MAM, PREF_URL_OPEN_CMD, PREF_URL_SAVE_CMD, + PREF_COMPOSE_EDITOR, } preference_t; typedef struct prof_alias_t From ce508a826a5bb908745272c5ea988142f39fd3a8 Mon Sep 17 00:00:00 2001 From: Stefan Date: Sun, 11 Apr 2021 18:34:00 +0200 Subject: [PATCH 4/8] Editor: Use _exit() instead of exit() --- src/command/cmd_funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 7aeb15f0..1d6d5f8d 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -9364,7 +9364,7 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) if ( x == -1 ) { cons_show_error("Failed to exec %s", editor); } - exit (EXIT_FAILURE); + _exit(EXIT_FAILURE); } else { if ( pid == -1 ) { return TRUE; From f5e1f9fa63b6d0fd7de49f41915acac0d812ff03 Mon Sep 17 00:00:00 2001 From: Stefan Date: Sun, 11 Apr 2021 19:42:22 +0200 Subject: [PATCH 5/8] Editor: Fix redisplay --- src/command/cmd_funcs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 1d6d5f8d..180102d5 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -9384,7 +9384,7 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) g_string_free(text, TRUE); } close(fd_input_file); - ui_redraw(); + GError* deletion_error = NULL; g_file_delete (file, NULL, &deletion_error); if ( deletion_error ) { @@ -9392,6 +9392,9 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) return TRUE; } g_object_unref(file); + ui_resize(); + rl_point = rl_end; + rl_forced_update_display(); } return TRUE; } From 880ce20018d8b4b583da7917a3cc5aa41c656531 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Fri, 16 Apr 2021 17:55:17 +0200 Subject: [PATCH 6/8] Run clang-format on new editor code --- src/command/cmd_defs.c | 2 +- src/command/cmd_funcs.c | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 9eaf3f39..8a8330dc 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2908,7 +2908,7 @@ command_mangen(void) GDateTime* now = g_date_time_new_now_local(); gchar* date = g_date_time_format(now, "%F"); - gchar *header = g_strdup_printf(".TH man 1 \"%s\" \"" PACKAGE_VERSION "\" \"Profanity XMPP client\"\n", date); + gchar* header = g_strdup_printf(".TH man 1 \"%s\" \"" PACKAGE_VERSION "\" \"Profanity XMPP client\"\n", date); if (!header) { log_error("command_mangen(): could not allocate memory"); return; diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 180102d5..a37c9b16 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -6867,7 +6867,7 @@ cmd_plugins_sourcepath(ProfWin* window, const char* const command, gchar** args) return TRUE; } - char *path = get_expanded_path(args[2]); + char* path = get_expanded_path(args[2]); if (!is_dir(path)) { cons_show("Plugins sourcepath must be a directory."); @@ -6888,7 +6888,7 @@ cmd_plugins_sourcepath(ProfWin* window, const char* const command, gchar** args) gboolean cmd_plugins_install(ProfWin* window, const char* const command, gchar** args) { - char *path; + char* path; if (args[1] == NULL) { char* sourcepath = prefs_get_string(PREF_PLUGINS_SOURCEPATH); @@ -9315,10 +9315,10 @@ gboolean cmd_editor(ProfWin* window, const char* const command, gchar** args) { /* Build temp file name */ - GString * tempfile = g_string_new(g_get_tmp_dir()); + GString* tempfile = g_string_new(g_get_tmp_dir()); g_string_append(tempfile, "/profanity-"); xmpp_ctx_t* const ctx = connection_get_ctx(); - if(!ctx) { + if (!ctx) { cons_show("Editor: Not connection"); return TRUE; } @@ -9336,16 +9336,16 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) // Check if file exists and create file if (g_file_test(filename, G_FILE_TEST_EXISTS)) { cons_show("Editor: The temp file exists"); - g_string_free (tempfile, TRUE); + g_string_free(tempfile, TRUE); return TRUE; } GError* creation_error = NULL; GFile* file = g_file_new_for_path(filename); - GFileOutputStream* fos = g_file_create (file, - G_FILE_CREATE_PRIVATE, NULL, - &creation_error); - if ( creation_error ) { + GFileOutputStream* fos = g_file_create(file, + G_FILE_CREATE_PRIVATE, NULL, + &creation_error); + if (creation_error) { cons_show_error("Editor: Error during file creation"); return TRUE; } @@ -9359,14 +9359,14 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) // Fork / exec pid_t pid = fork(); - if( pid == 0 ) { - int x = execl(editor, editor, g_file_get_path(file), (char *) NULL); - if ( x == -1 ) { + if (pid == 0) { + int x = execl(editor, editor, g_file_get_path(file), (char*)NULL); + if (x == -1) { cons_show_error("Failed to exec %s", editor); } _exit(EXIT_FAILURE); } else { - if ( pid == -1 ) { + if (pid == -1) { return TRUE; } int status = 0; @@ -9375,8 +9375,8 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) const size_t COUNT = 8192; char buf[COUNT]; ssize_t size_read = read(fd_input_file, buf, COUNT); - if(size_read > 0 && size_read <= COUNT ) { - buf[size_read-1] = '\0'; + if (size_read > 0 && size_read <= COUNT) { + buf[size_read - 1] = '\0'; GString* text = g_string_new(buf); ProfWin* win = wins_get_current(); win_println(win, THEME_DEFAULT, "!", "EDITOR PREVIEW: %s", text->str); @@ -9386,8 +9386,8 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) close(fd_input_file); GError* deletion_error = NULL; - g_file_delete (file, NULL, &deletion_error); - if ( deletion_error ) { + g_file_delete(file, NULL, &deletion_error); + if (deletion_error) { cons_show("Editor: Error during file deletion"); return TRUE; } From 8be46422d2ca5afff675ef3f7a2117c097a642a7 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Fri, 16 Apr 2021 18:06:30 +0200 Subject: [PATCH 7/8] editor: Use g_strdup_printf() instead of g_string_new() --- src/command/cmd_funcs.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index a37c9b16..9c9674cc 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -9314,29 +9314,22 @@ cmd_change_password(ProfWin* window, const char* const command, gchar** args) gboolean cmd_editor(ProfWin* window, const char* const command, gchar** args) { - /* Build temp file name */ - GString* tempfile = g_string_new(g_get_tmp_dir()); - g_string_append(tempfile, "/profanity-"); xmpp_ctx_t* const ctx = connection_get_ctx(); if (!ctx) { - cons_show("Editor: Not connection"); + log_debug("Editor: No connection"); return TRUE; } + + // build temp file name. Example: /tmp/profanity-f2f271dd-98c8-4118-8d47-3bd49c8e2e63.txt char* uuid = xmpp_uuid_gen(ctx); - g_string_append(tempfile, uuid); + char* filename = g_strdup_printf("%s%s%s.txt", g_get_tmp_dir(), "/profanity-", uuid); if (uuid) { xmpp_free(ctx, uuid); } - g_string_append(tempfile, ".txt"); - - // tempfile should be something like - // /tmp/profanity-f2f271dd-98c8-4118-8d47-3bd49c8e2e63.txt - const char* filename = tempfile->str; // Check if file exists and create file if (g_file_test(filename, G_FILE_TEST_EXISTS)) { cons_show("Editor: The temp file exists"); - g_string_free(tempfile, TRUE); return TRUE; } From e1249d9bbbe6a7a0741c8a83697f7bf962f4f82a Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Fri, 16 Apr 2021 19:14:40 +0200 Subject: [PATCH 8/8] Editor: improve error messages --- src/command/cmd_funcs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 9c9674cc..fc38a2b0 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -9316,7 +9316,7 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) { xmpp_ctx_t* const ctx = connection_get_ctx(); if (!ctx) { - log_debug("Editor: No connection"); + log_debug("Editor: no connection"); return TRUE; } @@ -9329,7 +9329,7 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) // Check if file exists and create file if (g_file_test(filename, G_FILE_TEST_EXISTS)) { - cons_show("Editor: The temp file exists"); + cons_show("Editor: temp file exists already"); return TRUE; } @@ -9339,14 +9339,14 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) G_FILE_CREATE_PRIVATE, NULL, &creation_error); if (creation_error) { - cons_show_error("Editor: Error during file creation"); + cons_show_error("Editor: could not create temp file"); return TRUE; } g_object_unref(fos); char* editor = prefs_get_string(PREF_COMPOSE_EDITOR); if (!g_file_test(editor, G_FILE_TEST_EXISTS)) { - cons_show_error("Editor: editor %s not exists", editor); + cons_show_error("Editor: binary %s not exist", editor); return TRUE; } @@ -9355,7 +9355,7 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) if (pid == 0) { int x = execl(editor, editor, g_file_get_path(file), (char*)NULL); if (x == -1) { - cons_show_error("Failed to exec %s", editor); + cons_show_error("Editor:Failed to exec %s", editor); } _exit(EXIT_FAILURE); } else { @@ -9381,7 +9381,7 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) GError* deletion_error = NULL; g_file_delete(file, NULL, &deletion_error); if (deletion_error) { - cons_show("Editor: Error during file deletion"); + cons_show("Editor: error during file deletion"); return TRUE; } g_object_unref(file);