diff --git a/src/fe-common/core/chat-completion.c b/src/fe-common/core/chat-completion.c index 7be923fc..54143062 100644 --- a/src/fe-common/core/chat-completion.c +++ b/src/fe-common/core/chat-completion.c @@ -646,6 +646,41 @@ static void sig_complete_msg(GList **list, WINDOW_REC *window, if (*list != NULL) signal_stop(); } +static void sig_erase_complete_msg(WINDOW_REC *window, const char *word, + const char *line) +{ + SERVER_REC *server; + MODULE_SERVER_REC *mserver; + GSList *tmp; + + server = line_get_server(line); + if (server == NULL){ + server = window->active_server; + if (server == NULL) + return; + } + + if (*word == '\0') + return; + + /* check from global list */ + completion_last_message_remove(word); + + /* check from server specific list */ + if (server != NULL) { + mserver = MODULE_DATA(server); + for (tmp = mserver->lastmsgs; tmp != NULL; tmp = tmp->next) { + LAST_MSG_REC *rec = tmp->data; + + if (g_strcasecmp(rec->nick, word) == 0) { + last_msg_destroy(&mserver->lastmsgs, rec); + break; + } + } + + } +} + GList *completion_get_chatnets(const char *word) { GList *list; @@ -874,6 +909,7 @@ void chat_completion_init(void) read_settings(); signal_add("complete word", (SIGNAL_FUNC) sig_complete_word); signal_add("complete command msg", (SIGNAL_FUNC) sig_complete_msg); + signal_add("complete erase command msg", (SIGNAL_FUNC) sig_erase_complete_msg); signal_add("complete command connect", (SIGNAL_FUNC) sig_complete_connect); signal_add("complete command server", (SIGNAL_FUNC) sig_complete_connect); signal_add("complete command topic", (SIGNAL_FUNC) sig_complete_topic); @@ -897,6 +933,7 @@ void chat_completion_deinit(void) signal_remove("complete word", (SIGNAL_FUNC) sig_complete_word); signal_remove("complete command msg", (SIGNAL_FUNC) sig_complete_msg); + signal_remove("complete erase command msg", (SIGNAL_FUNC) sig_erase_complete_msg); signal_remove("complete command connect", (SIGNAL_FUNC) sig_complete_connect); signal_remove("complete command server", (SIGNAL_FUNC) sig_complete_connect); signal_remove("complete command topic", (SIGNAL_FUNC) sig_complete_topic); diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c index b36cb0f7..f10fbb6d 100644 --- a/src/fe-common/core/completion.c +++ b/src/fe-common/core/completion.c @@ -113,27 +113,28 @@ static void free_completions(void) } /* manual word completion - called when TAB is pressed */ -char *word_complete(WINDOW_REC *window, const char *line, int *pos) +char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase) { static int startpos = 0, wordlen = 0; + int old_startpos, old_wordlen; GString *result; char *word, *wordstart, *linestart, *ret; - int want_space; + int continue_complete, want_space; g_return_val_if_fail(line != NULL, NULL); g_return_val_if_fail(pos != NULL, NULL); - if (complist != NULL && *pos == last_line_pos && - strcmp(line, last_line) == 0) { - /* complete from old list */ - complist = complist->next != NULL ? complist->next : - g_list_first(complist); - want_space = last_want_space; - } else { - /* get new completion list */ - free_completions(); + continue_complete = complist != NULL && *pos == last_line_pos && + strcmp(line, last_line) == 0; + old_startpos = startpos; + old_wordlen = wordlen; + + if (!erase && continue_complete) { + word = NULL; + linestart = NULL; + } else { /* get the word we want to complete */ word = get_word_at(line, *pos, &wordstart); startpos = (int) (wordstart-line); @@ -156,7 +157,7 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos) BUT if we start completion with "/msg ", we don't want to complete the /msg word, but instead complete empty word with /msg being in linestart. */ - if (*pos > 0 && line[*pos-1] == ' ' && + if (!erase && *pos > 0 && line[*pos-1] == ' ' && (*linestart == '\0' || wordstart[-1] != ' ')) { char *old; @@ -172,14 +173,38 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos) wordlen = 0; } + } + + if (erase) { + signal_emit("complete erase", 3, window, word, linestart); + + if (!continue_complete) + return NULL; + + /* jump to next completion */ + word = NULL; + linestart = NULL; + startpos = old_startpos; + wordlen = old_wordlen; + } + + if (continue_complete) { + /* complete from old list */ + complist = complist->next != NULL ? complist->next : + g_list_first(complist); + want_space = last_want_space; + } else { + /* get new completion list */ + free_completions(); + want_space = TRUE; signal_emit("complete word", 5, &complist, window, word, linestart, &want_space); last_want_space = want_space; - - g_free(linestart); - g_free(word); } + g_free(linestart); + g_free(word); + if (complist == NULL) return NULL; @@ -532,7 +557,8 @@ static char *expand_aliases(const char *line) } static void sig_complete_word(GList **list, WINDOW_REC *window, - const char *word, const char *linestart, int *want_space) + const char *word, const char *linestart, + int *want_space) { const char *newword, *cmdchars; char *signal, *cmd, *args, *line; @@ -608,6 +634,39 @@ static void sig_complete_word(GList **list, WINDOW_REC *window, g_free(line); } +static void sig_complete_erase(WINDOW_REC *window, const char *word, + const char *linestart) +{ + const char *cmdchars; + char *line, *cmd, *args, *signal; + + if (*linestart == '\0') + return; + + /* we only want to check for commands */ + cmdchars = settings_get_str("cmdchars"); + cmdchars = strchr(cmdchars, *linestart); + if (cmdchars == NULL) + return; + + /* check if there's aliases */ + line = linestart[1] == *cmdchars ? g_strdup(linestart+2) : + expand_aliases(linestart+1); + + cmd = line_get_command(line, &args, FALSE); + if (cmd == NULL) { + g_free(line); + return; + } + + signal = g_strconcat("complete erase command ", cmd, NULL); + signal_emit(signal, 3, window, word, args); + + g_free(signal); + g_free(cmd); + g_free(line); +} + static void sig_complete_set(GList **list, WINDOW_REC *window, const char *word, const char *line, int *want_space) { @@ -682,6 +741,7 @@ void completion_init(void) chat_completion_init(); signal_add_first("complete word", (SIGNAL_FUNC) sig_complete_word); + signal_add_first("complete erase", (SIGNAL_FUNC) sig_complete_erase); signal_add("complete command set", (SIGNAL_FUNC) sig_complete_set); signal_add("complete command toggle", (SIGNAL_FUNC) sig_complete_toggle); signal_add("complete command cat", (SIGNAL_FUNC) sig_complete_filename); @@ -699,6 +759,7 @@ void completion_deinit(void) chat_completion_deinit(); signal_remove("complete word", (SIGNAL_FUNC) sig_complete_word); + signal_remove("complete erase", (SIGNAL_FUNC) sig_complete_erase); signal_remove("complete command set", (SIGNAL_FUNC) sig_complete_set); signal_remove("complete command toggle", (SIGNAL_FUNC) sig_complete_toggle); signal_remove("complete command cat", (SIGNAL_FUNC) sig_complete_filename); diff --git a/src/fe-common/core/completion.h b/src/fe-common/core/completion.h index 35b1ea7c..9a8b32cb 100644 --- a/src/fe-common/core/completion.h +++ b/src/fe-common/core/completion.h @@ -5,8 +5,10 @@ /* automatic word completion - called when space/enter is pressed */ char *auto_word_complete(const char *line, int *pos); -/* manual word completion - called when TAB is pressed */ -char *word_complete(WINDOW_REC *window, const char *line, int *pos); +/* manual word completion - called when TAB is pressed. if erase is TRUE, + the word is removed from completion list entirely (if possible) and + next completion is used */ +char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase); GList *filename_complete(const char *path, const char *default_path); diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 450f13ba..3987d8d9 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -402,14 +402,15 @@ static void key_change_window(const char *data) signal_emit("command window goto", 3, data, active_win->active_server, active_win->active); } -static void key_word_completion(void) +static void key_completion(int erase) { char *line; int pos; pos = gui_entry_get_pos(active_entry); - line = word_complete(active_win, gui_entry_get_text(active_entry), &pos); + line = word_complete(active_win, gui_entry_get_text(active_entry), + &pos, erase); if (line != NULL) { gui_entry_set_text(active_entry, line); gui_entry_set_pos(active_entry, pos); @@ -417,6 +418,16 @@ static void key_word_completion(void) } } +static void key_word_completion(void) +{ + key_completion(FALSE); +} + +static void key_erase_completion(void) +{ + key_completion(TRUE); +} + static void key_check_replaces(void) { char *line; @@ -634,6 +645,7 @@ void gui_readline_init(void) /* line transmitting */ key_bind("send_line", "Execute the input line", "return", NULL, (SIGNAL_FUNC) key_send_line); key_bind("word_completion", "", "^I", NULL, (SIGNAL_FUNC) key_word_completion); + key_bind("erase_completion", "", "meta-k", NULL, (SIGNAL_FUNC) key_erase_completion); key_bind("check_replaces", "Check word replaces", NULL, NULL, (SIGNAL_FUNC) key_check_replaces); /* window managing */