From 09f5cadf1a2052f07f31611dc4ba986b3db0ec27 Mon Sep 17 00:00:00 2001 From: MarcoPolo-PasTonMolo Date: Thu, 7 Oct 2021 15:53:12 +0300 Subject: [PATCH] Add /correct-editor command --- src/command/cmd_ac.c | 18 ++++++- src/command/cmd_defs.c | 19 +++++++ src/command/cmd_funcs.c | 116 ++++++++++++++++++++++++++++++++++++++++ src/command/cmd_funcs.h | 1 + 4 files changed, 153 insertions(+), 1 deletion(-) diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 9db42841..88b2b2f7 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -1795,6 +1795,7 @@ _cmd_ac_complete_params(ProfWin* window, const char* const input, gboolean previ g_hash_table_insert(ac_funcs, "/avatar", _avatar_autocomplete); g_hash_table_insert(ac_funcs, "/correction", _correction_autocomplete); g_hash_table_insert(ac_funcs, "/correct", _correct_autocomplete); + g_hash_table_insert(ac_funcs, "/correct-editor", _correct_autocomplete); g_hash_table_insert(ac_funcs, "/software", _software_autocomplete); g_hash_table_insert(ac_funcs, "/url", _url_autocomplete); g_hash_table_insert(ac_funcs, "/executable", _executable_autocomplete); @@ -4054,7 +4055,22 @@ _correct_autocomplete(ProfWin* window, const char* const input, gboolean previou return NULL; } - GString* result_str = g_string_new("/correct "); + // Get command + int len = strlen(input); + char command[len + 2]; + int i = 0; + while (i < len) { + if (input[i] == ' ') { + break; + } else { + command[i] = input[i]; + } + i++; + } + command[i] = ' '; + command[i + 1] = '\0'; + + GString* result_str = g_string_new(command); g_string_append(result_str, last_message); char* result = result_str->str; g_string_free(result_str, FALSE); diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 1b8c3112..47ab34ad 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2622,6 +2622,25 @@ static struct cmd_t command_defs[] = { CMD_NOEXAMPLES }, + { "/correct-editor", + parse_args_as_one, 1, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_correct_editor) + CMD_TAGS( + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/correct-editor ") + CMD_DESC( + "Spawn external editor to correct and resend the last message (XEP-0308). " + "Use tab completion to get the last sent message. " + "For more information on how to configure corrections, see: /help correction. " + "Use /executable to set your favourite editor.") + CMD_ARGS( + { "message", "The corrected message." }) + CMD_NOEXAMPLES + }, + { "/silence", parse_args, 1, 1, &cons_silence_setting, CMD_NOSUBFUNCS diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 67c59802..7e767659 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -9527,6 +9527,122 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) return TRUE; } +gboolean +cmd_correct_editor(ProfWin* window, const char* const command, gchar** args) +{ + jabber_conn_status_t conn_status = connection_get_status(); + if (conn_status != JABBER_CONNECTED) { + cons_show("You are currently not connected."); + return TRUE; + } else if (!prefs_get_boolean(PREF_CORRECTION_ALLOW)) { + win_println(window, THEME_DEFAULT, "!", "Corrections not enabled. See /help correction."); + return TRUE; + } else if (window->type == WIN_CHAT) { + ProfChatWin* chatwin = (ProfChatWin*)window; + assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); + + if (chatwin->last_msg_id == NULL || chatwin->last_message == NULL) { + win_println(window, THEME_DEFAULT, "!", "No last message to correct."); + return TRUE; + } + } else if (window->type == WIN_MUC) { + ProfMucWin* mucwin = (ProfMucWin*)window; + assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); + + if (mucwin->last_msg_id == NULL || mucwin->last_message == NULL) { + win_println(window, THEME_DEFAULT, "!", "No last message to correct."); + return TRUE; + } + } else { + win_println(window, THEME_DEFAULT, "!", "Command /correct-editor only valid in regular chat windows."); + return TRUE; + } + + // create editor dir if not present + char *jid = connection_get_barejid(); + gchar *path = files_get_account_data_path(DIR_EDITOR, jid); + if (g_mkdir_with_parents(path, S_IRWXU) != 0) { + cons_show_error("Failed to create directory at '%s' with error '%s'", path, strerror(errno)); + free(jid); + g_free(path); + return TRUE; + } + // build temp file name. Example: /home/user/.local/share/profanity/editor/jid/compose.md + char* filename = g_strdup_printf("%s/compose.md", path); + free(jid); + g_free(path); + + 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); + int fd_output_file = open(g_file_get_path(file), O_WRONLY); + + const size_t COUNT = 8192; + gchar* message = g_strjoinv(" ", args); + write(fd_output_file, message, strlen(message)); + + free(message); + free(filename); + + if (creation_error) { + cons_show_error("Editor: could not create temp file"); + return TRUE; + } + g_object_unref(fos); + + char* editor = prefs_get_string(PREF_COMPOSE_EDITOR); + + // Fork / exec + pid_t pid = fork(); + if (pid == 0) { + int x = execlp(editor, editor, g_file_get_path(file), (char*)NULL); + if (x == -1) { + cons_show_error("Editor: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); + 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); + + if (window->type == WIN_CHAT) { + ProfChatWin* chatwin = (ProfChatWin*)window; + assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); + + cl_ev_send_msg_correct(chatwin, text->str, FALSE, TRUE); + } else if (window->type == WIN_MUC) { + ProfMucWin* mucwin = (ProfMucWin*)window; + assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); + + cl_ev_send_muc_msg_corrected(mucwin, text->str, FALSE, TRUE); + } + + g_string_free(text, TRUE); + } + close(fd_input_file); + + 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); + ui_resize(); + rl_point = rl_end; + rl_forced_update_display(); + } + return TRUE; +} + gboolean cmd_silence(ProfWin* window, const char* const command, gchar** args) { diff --git a/src/command/cmd_funcs.h b/src/command/cmd_funcs.h index 54cc6e78..cf6ec5bf 100644 --- a/src/command/cmd_funcs.h +++ b/src/command/cmd_funcs.h @@ -246,6 +246,7 @@ gboolean cmd_executable_urlsave(ProfWin* window, const char* const command, gcha gboolean cmd_executable_editor(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); +gboolean cmd_correct_editor(ProfWin* window, const char* const command, gchar** args); gboolean cmd_silence(ProfWin* window, const char* const command, gchar** args); #endif