diff --git a/ChangeLog.adoc b/ChangeLog.adoc index bb2348d12..542b77543 100644 --- a/ChangeLog.adoc +++ b/ChangeLog.adoc @@ -20,6 +20,7 @@ https://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes] New features:: + * core: display similar command names when a command is unknown (issue #1877) * core: force ctrl keys to lower case when they are added (issue #1875) * core, plugins: make many identifiers case sensitive (issue #1872, issue #398, bug #32213) * alias: use lower case for default aliases (issue #1872) diff --git a/po/cs.po b/po/cs.po index eb70e0341..d7b5fb5c5 100644 --- a/po/cs.po +++ b/po/cs.po @@ -21,7 +21,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2023-01-29 16:50+0100\n" +"POT-Creation-Date: 2023-01-30 21:30+0100\n" "PO-Revision-Date: 2022-10-15 22:51+0200\n" "Last-Translator: Ondřej Súkup \n" "Language-Team: weechat-dev \n" @@ -147,6 +147,12 @@ msgstr "" msgid "%sAnother command \"%s\" already exists for plugin \"%s\"" msgstr "%sChyba: příkaz \"%s\" již existuje pro plugin \"%s\"" +#, fuzzy, c-format +msgid "" +"%sUnknown command \"%s\" (type /help for help), commands with similar name: " +"%s" +msgstr "%sChyba: neznámý příkaz \"%s\" (napište /help pro nápovědu)" + #, c-format msgid "%sBad file descriptor (%d) used in hook_fd" msgstr "" @@ -4472,10 +4478,6 @@ msgid "" "buffer: \"%s\")" msgstr "" -#, fuzzy, c-format -msgid "%sUnknown command \"%s\" (type /help for help)" -msgstr "%sChyba: neznámý příkaz \"%s\" (napište /help pro nápovědu)" - #, fuzzy, c-format msgid "" "%sAmbiguous command \"%s\": it exists in many plugins and not in \"%s\" " diff --git a/po/de.po b/po/de.po index d6d21f9ff..196c18459 100644 --- a/po/de.po +++ b/po/de.po @@ -26,7 +26,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2023-01-29 16:50+0100\n" +"POT-Creation-Date: 2023-01-30 21:30+0100\n" "PO-Revision-Date: 2023-01-29 13:05+0100\n" "Last-Translator: Nils Görs \n" "Language-Team: German - Germany \n" @@ -147,6 +147,13 @@ msgid "%sAnother command \"%s\" already exists for plugin \"%s\"" msgstr "" "%sEin anderer Befehl \"%s\" existiert bereits für die Erweiterung \"%s\"" +#, fuzzy, c-format +#| msgid "%sUnknown command \"%s\" (type /help for help)" +msgid "" +"%sUnknown command \"%s\" (type /help for help), commands with similar name: " +"%s" +msgstr "%sDer Befehl \"%s\" ist nicht bekannt (für eine Hilfe nutze /help)" + #, c-format msgid "%sBad file descriptor (%d) used in hook_fd" msgstr "%sBad file descriptor (%d) wurde in Funktion \"hook_fd\" genutzt" @@ -5620,10 +5627,6 @@ msgstr "" "Warnung: momentan ist der Befehl \"%s\" nicht ausführbar (Befehl: \"%s\", " "Buffer: \"%s\")" -#, c-format -msgid "%sUnknown command \"%s\" (type /help for help)" -msgstr "%sDer Befehl \"%s\" ist nicht bekannt (für eine Hilfe nutze /help)" - #, c-format msgid "" "%sAmbiguous command \"%s\": it exists in many plugins and not in \"%s\" " diff --git a/po/es.po b/po/es.po index caca04124..d27dda2d6 100644 --- a/po/es.po +++ b/po/es.po @@ -22,7 +22,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2023-01-29 16:50+0100\n" +"POT-Creation-Date: 2023-01-30 21:30+0100\n" "PO-Revision-Date: 2022-10-15 22:51+0200\n" "Last-Translator: Santiago Forero \n" "Language-Team: weechat-dev \n" @@ -145,6 +145,12 @@ msgstr "" msgid "%sAnother command \"%s\" already exists for plugin \"%s\"" msgstr "%sError: el comando \"%s\" ya existe en el plugin \"%s\"" +#, fuzzy, c-format +msgid "" +"%sUnknown command \"%s\" (type /help for help), commands with similar name: " +"%s" +msgstr "%sError: comando \"%s\" desconocido (use /help para ver la ayuda)" + #, c-format msgid "%sBad file descriptor (%d) used in hook_fd" msgstr "%sError: mal descriptor de archivo (%d) usado en hook_fd" @@ -5030,10 +5036,6 @@ msgid "" "buffer: \"%s\")" msgstr "" -#, fuzzy, c-format -msgid "%sUnknown command \"%s\" (type /help for help)" -msgstr "%sError: comando \"%s\" desconocido (use /help para ver la ayuda)" - #, fuzzy, c-format msgid "" "%sAmbiguous command \"%s\": it exists in many plugins and not in \"%s\" " diff --git a/po/fr.po b/po/fr.po index 348cbc477..50480ce25 100644 --- a/po/fr.po +++ b/po/fr.po @@ -21,8 +21,8 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2023-01-29 16:50+0100\n" -"PO-Revision-Date: 2023-01-29 16:50+0100\n" +"POT-Creation-Date: 2023-01-30 21:30+0100\n" +"PO-Revision-Date: 2023-01-30 21:32+0100\n" "Last-Translator: Sébastien Helleu \n" "Language-Team: weechat-dev \n" "Language: fr\n" @@ -139,6 +139,14 @@ msgstr "Fichier" msgid "%sAnother command \"%s\" already exists for plugin \"%s\"" msgstr "%sUne autre commande \"%s\" existe déjà pour l'extension \"%s\"" +#, c-format +msgid "" +"%sUnknown command \"%s\" (type /help for help), commands with similar name: " +"%s" +msgstr "" +"%sCommande \"%s\" inconnue (tapez /help pour l'aide), commandes avec un nom " +"similaire : %s" + #, c-format msgid "%sBad file descriptor (%d) used in hook_fd" msgstr "%sMauvais descripteur de fichier (%d) utilisé dans hook_fd" @@ -5486,10 +5494,6 @@ msgstr "" "attention : la commande \"%s\" n'est pas autorisée actuellement (commande : " "\"%s\", tampon : \"%s\")" -#, c-format -msgid "%sUnknown command \"%s\" (type /help for help)" -msgstr "%sCommande \"%s\" inconnue (tapez /help pour l'aide)" - #, c-format msgid "" "%sAmbiguous command \"%s\": it exists in many plugins and not in \"%s\" " diff --git a/po/hu.po b/po/hu.po index 9d86d8902..a7cb0f87e 100644 --- a/po/hu.po +++ b/po/hu.po @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2023-01-29 16:50+0100\n" +"POT-Creation-Date: 2023-01-30 21:30+0100\n" "PO-Revision-Date: 2022-10-15 22:51+0200\n" "Last-Translator: Andras Voroskoi \n" "Language-Team: weechat-dev \n" @@ -147,6 +147,12 @@ msgstr "" msgid "%sAnother command \"%s\" already exists for plugin \"%s\"" msgstr "%s az ignore már létezik\n" +#, fuzzy, c-format +msgid "" +"%sUnknown command \"%s\" (type /help for help), commands with similar name: " +"%s" +msgstr "%s a \"%s\" aliasz vagy parancs nem található\n" + #, c-format msgid "%sBad file descriptor (%d) used in hook_fd" msgstr "" @@ -4052,10 +4058,6 @@ msgid "" "buffer: \"%s\")" msgstr "" -#, fuzzy, c-format -msgid "%sUnknown command \"%s\" (type /help for help)" -msgstr "%s a \"%s\" aliasz vagy parancs nem található\n" - #, fuzzy, c-format msgid "" "%sAmbiguous command \"%s\": it exists in many plugins and not in \"%s\" " diff --git a/po/it.po b/po/it.po index 0e66e2e66..3d9979ded 100644 --- a/po/it.po +++ b/po/it.po @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2023-01-29 16:50+0100\n" +"POT-Creation-Date: 2023-01-30 21:30+0100\n" "PO-Revision-Date: 2022-10-15 22:51+0200\n" "Last-Translator: Esteban I. Ruiz Moreno \n" "Language-Team: weechat-dev \n" @@ -144,6 +144,12 @@ msgstr "" msgid "%sAnother command \"%s\" already exists for plugin \"%s\"" msgstr "%sErrore: un altro comando \"%s\" esiste già per il plugin \"%s\"" +#, fuzzy, c-format +msgid "" +"%sUnknown command \"%s\" (type /help for help), commands with similar name: " +"%s" +msgstr "%sErrore: comando \"%s\" sconosciuto (digita /help per l'aiuto)" + #, fuzzy, c-format msgid "%sBad file descriptor (%d) used in hook_fd" msgstr "%sErrore: descrittore file errato (%d) usato in hook_fd" @@ -4729,10 +4735,6 @@ msgid "" "buffer: \"%s\")" msgstr "" -#, fuzzy, c-format -msgid "%sUnknown command \"%s\" (type /help for help)" -msgstr "%sErrore: comando \"%s\" sconosciuto (digita /help per l'aiuto)" - #, fuzzy, c-format msgid "" "%sAmbiguous command \"%s\": it exists in many plugins and not in \"%s\" " diff --git a/po/ja.po b/po/ja.po index d0263810a..f5eed819a 100644 --- a/po/ja.po +++ b/po/ja.po @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2023-01-29 16:50+0100\n" +"POT-Creation-Date: 2023-01-30 21:30+0100\n" "PO-Revision-Date: 2022-10-15 22:51+0200\n" "Last-Translator: AYANOKOUZI, Ryuunosuke \n" "Language-Team: Japanese \n" "Language-Team: Polish \n" @@ -141,6 +141,13 @@ msgstr "" msgid "%sAnother command \"%s\" already exists for plugin \"%s\"" msgstr "%sIstnieje już inna komenda \"%s\" dla wtyczki \"%s\"" +#, fuzzy, c-format +#| msgid "%sUnknown command \"%s\" (type /help for help)" +msgid "" +"%sUnknown command \"%s\" (type /help for help), commands with similar name: " +"%s" +msgstr "%sNieznana komenda \"%s\" (wpisz /help , aby uzyskać pomoc)" + #, c-format msgid "%sBad file descriptor (%d) used in hook_fd" msgstr "%sZły deskryptor pliku (%d) użyty w hook_fd" @@ -5423,10 +5430,6 @@ msgstr "" "uwaga: komenda \"%s\" nie jest obecnie dozwolona (komenda: \"%s\", bufor: " "\"%s\")" -#, c-format -msgid "%sUnknown command \"%s\" (type /help for help)" -msgstr "%sNieznana komenda \"%s\" (wpisz /help , aby uzyskać pomoc)" - #, c-format msgid "" "%sAmbiguous command \"%s\": it exists in many plugins and not in \"%s\" " diff --git a/po/pt.po b/po/pt.po index 4e380c45d..cd3c556bc 100644 --- a/po/pt.po +++ b/po/pt.po @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2023-01-29 16:50+0100\n" +"POT-Creation-Date: 2023-01-30 21:30+0100\n" "PO-Revision-Date: 2022-10-15 22:51+0200\n" "Last-Translator: Vasco Almeida \n" "Language-Team: Portuguese <>\n" @@ -146,6 +146,12 @@ msgstr "" msgid "%sAnother command \"%s\" already exists for plugin \"%s\"" msgstr "%sErro: outro comando \"%s\" já existe para o plugin \"%s\"" +#, fuzzy, c-format +msgid "" +"%sUnknown command \"%s\" (type /help for help), commands with similar name: " +"%s" +msgstr "%sErro: comando desconhecido: \"%s\" (escreva /help para obter ajuda)" + #, fuzzy, c-format msgid "%sBad file descriptor (%d) used in hook_fd" msgstr "%sErro: descritor de ficheiro incorreto (%d) usado em hook_fd" @@ -5289,10 +5295,6 @@ msgid "" "buffer: \"%s\")" msgstr "" -#, fuzzy, c-format -msgid "%sUnknown command \"%s\" (type /help for help)" -msgstr "%sErro: comando desconhecido: \"%s\" (escreva /help para obter ajuda)" - #, fuzzy, c-format msgid "" "%sAmbiguous command \"%s\": it exists in many plugins and not in \"%s\" " diff --git a/po/pt_BR.po b/po/pt_BR.po index 2d4fcf42e..4f3f8da3e 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -21,7 +21,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2023-01-29 16:50+0100\n" +"POT-Creation-Date: 2023-01-30 21:30+0100\n" "PO-Revision-Date: 2022-10-15 22:51+0200\n" "Last-Translator: Érico Nogueira \n" "Language-Team: weechat-dev \n" @@ -143,6 +143,12 @@ msgstr "" msgid "%sAnother command \"%s\" already exists for plugin \"%s\"" msgstr "%sOutro comando \"%s\" já existe para o plugin \"%s\"" +#, fuzzy, c-format +msgid "" +"%sUnknown command \"%s\" (type /help for help), commands with similar name: " +"%s" +msgstr "%sErro com o comando \"%s\" (ajuda no comando: /help %s)" + #, c-format msgid "%sBad file descriptor (%d) used in hook_fd" msgstr "%sDescritor de arquivo ruim (%d) usado em hook_fd" @@ -4721,10 +4727,6 @@ msgid "" "buffer: \"%s\")" msgstr "" -#, fuzzy, c-format -msgid "%sUnknown command \"%s\" (type /help for help)" -msgstr "%sErro com o comando \"%s\" (ajuda no comando: /help %s)" - #, fuzzy, c-format msgid "" "%sAmbiguous command \"%s\": it exists in many plugins and not in \"%s\" " diff --git a/po/ru.po b/po/ru.po index e65ab0060..bad808969 100644 --- a/po/ru.po +++ b/po/ru.po @@ -21,7 +21,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2023-01-29 16:50+0100\n" +"POT-Creation-Date: 2023-01-30 21:30+0100\n" "PO-Revision-Date: 2022-10-15 22:51+0200\n" "Last-Translator: Aleksey V Zapparov AKA ixti \n" "Language-Team: weechat-dev \n" @@ -155,6 +155,12 @@ msgstr "" msgid "%sAnother command \"%s\" already exists for plugin \"%s\"" msgstr "%s игнорирование уже существует\n" +#, fuzzy, c-format +msgid "" +"%sUnknown command \"%s\" (type /help for help), commands with similar name: " +"%s" +msgstr "%s сокращение или команда \"%s\" не найдены\n" + #, c-format msgid "%sBad file descriptor (%d) used in hook_fd" msgstr "" @@ -4080,10 +4086,6 @@ msgid "" "buffer: \"%s\")" msgstr "" -#, fuzzy, c-format -msgid "%sUnknown command \"%s\" (type /help for help)" -msgstr "%s сокращение или команда \"%s\" не найдены\n" - #, fuzzy, c-format msgid "" "%sAmbiguous command \"%s\": it exists in many plugins and not in \"%s\" " diff --git a/po/sr.po b/po/sr.po index dc0518311..e7373fdab 100644 --- a/po/sr.po +++ b/po/sr.po @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2023-01-29 16:50+0100\n" +"POT-Creation-Date: 2023-01-30 21:30+0100\n" "PO-Revision-Date: 2022-12-05 09:44+0400\n" "Last-Translator: Ivan Pešić \n" "Language-Team: weechat-dev \n" @@ -144,6 +144,13 @@ msgstr "" msgid "%sAnother command \"%s\" already exists for plugin \"%s\"" msgstr "%sВећ постоји друга команда \"%s\" за додатак \"%s\"" +#, fuzzy, c-format +#| msgid "%sUnknown command \"%s\" (type /help for help)" +msgid "" +"%sUnknown command \"%s\" (type /help for help), commands with similar name: " +"%s" +msgstr "%sНепозната команда „%s” (за помоћ откуцајте /help)" + #, c-format msgid "%sBad file descriptor (%d) used in hook_fd" msgstr "%sУ hook_fd је употребљен лош дескриптор фајла (%d)" @@ -5603,10 +5610,6 @@ msgid "" msgstr "" "упозорење: тренутно се не дозвољава команда „%s” (команда: „%s”, бафер: „%s”)" -#, c-format -msgid "%sUnknown command \"%s\" (type /help for help)" -msgstr "%sНепозната команда „%s” (за помоћ откуцајте /help)" - #, c-format msgid "" "%sAmbiguous command \"%s\": it exists in many plugins and not in \"%s\" " diff --git a/po/tr.po b/po/tr.po index 2b495e1fd..97456fe95 100644 --- a/po/tr.po +++ b/po/tr.po @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2023-01-29 16:50+0100\n" +"POT-Creation-Date: 2023-01-30 21:30+0100\n" "PO-Revision-Date: 2022-10-15 22:51+0200\n" "Last-Translator: Emir SARI \n" "Language-Team: weechat-dev \n" @@ -143,6 +143,13 @@ msgstr "" msgid "%sAnother command \"%s\" already exists for plugin \"%s\"" msgstr "%sŞu eklenti için başka bir komut (\"%s\") halihazırda var: \"%s\"" +#, fuzzy, c-format +#| msgid "%sUnknown command \"%s\" (type /help for help)" +msgid "" +"%sUnknown command \"%s\" (type /help for help), commands with similar name: " +"%s" +msgstr "%s Bilinmeyen komut \"%s\" (yardım için /help yazın)" + #, c-format msgid "%sBad file descriptor (%d) used in hook_fd" msgstr "%sHatalı dosya açıklayıcısı (%d) hook_fd içinde kullanılmış" @@ -5674,10 +5681,6 @@ msgstr "" "uyarı: şu anda \"%s\" komutuna izin verilmiyor (komut: \"%s\", arabellek: " "\"%s\")" -#, c-format -msgid "%sUnknown command \"%s\" (type /help for help)" -msgstr "%s Bilinmeyen komut \"%s\" (yardım için /help yazın)" - #, c-format msgid "" "%sAmbiguous command \"%s\": it exists in many plugins and not in \"%s\" " diff --git a/po/weechat.pot b/po/weechat.pot index 4bbb97bfd..a90ee12a8 100644 --- a/po/weechat.pot +++ b/po/weechat.pot @@ -21,7 +21,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2023-01-29 16:50+0100\n" +"POT-Creation-Date: 2023-01-30 21:30+0100\n" "PO-Revision-Date: 2014-08-16 10:27+0200\n" "Last-Translator: Sébastien Helleu \n" "Language-Team: weechat-dev \n" @@ -131,6 +131,12 @@ msgstr "" msgid "%sAnother command \"%s\" already exists for plugin \"%s\"" msgstr "" +#, c-format +msgid "" +"%sUnknown command \"%s\" (type /help for help), commands with similar name: " +"%s" +msgstr "" + #, c-format msgid "%sBad file descriptor (%d) used in hook_fd" msgstr "" @@ -3696,10 +3702,6 @@ msgid "" "buffer: \"%s\")" msgstr "" -#, c-format -msgid "%sUnknown command \"%s\" (type /help for help)" -msgstr "" - #, c-format msgid "" "%sAmbiguous command \"%s\": it exists in many plugins and not in \"%s\" " diff --git a/src/core/hook/wee-hook-command.c b/src/core/hook/wee-hook-command.c index 435b0d702..641b345a1 100644 --- a/src/core/hook/wee-hook-command.c +++ b/src/core/hook/wee-hook-command.c @@ -27,6 +27,7 @@ #include #include "../weechat.h" +#include "../wee-arraylist.h" #include "../wee-config.h" #include "../wee-hook.h" #include "../wee-infolist.h" @@ -35,6 +36,7 @@ #include "../wee-string.h" #include "../wee-utf8.h" #include "../../gui/gui-chat.h" +#include "../../gui/gui-filter.h" #include "../../plugins/plugin.h" @@ -522,6 +524,203 @@ hook_command_exec (struct t_gui_buffer *buffer, int any_plugin, return rc; } +/* + * Gets relevance for cmd2 (existing command) compared to cmd1 (non-existing + * command). + * + * Both commands are in lower case. + * + * Returns a number based on the Levenshtein distance between two commands, + * lower is better. + */ + +int +hook_command_similar_get_relevance (const char *cmd1, int length_cmd1, + const char *cmd2, int length_cmd2) +{ + const char *pos; + int relevance, factor; + + /* perfect match if commands are the same (different case) */ + if (strcmp (cmd1, cmd2) == 0) + return -1; + + /* init relevance with Levenshtein distance (lower is better) */ + relevance = string_levenshtein (cmd1, cmd2, 1); + + /* bonus if one command includes the other */ + pos = (length_cmd1 < length_cmd2) ? + strstr (cmd2, cmd1) : strstr (cmd1, cmd2); + if (pos) + { + factor = 4; + /* extra bonus if match is at beginning */ + if ((pos == cmd1) || (pos == cmd2)) + factor = 5; + relevance /= factor; + } + else + { + /* malus if no chars in common between two words */ + if (string_get_common_bytes_count (cmd1, cmd2) == 0) + relevance *= 2; + } + + return relevance; +} + +/* + * Compares similar commands to sort them by relevance (lower number first: + * best relevance). + */ + +int +hook_command_similar_cmp_cb (void *data, struct t_arraylist *arraylist, + void *pointer1, void *pointer2) +{ + struct t_hook_command_similar *ptr_cmd1, *ptr_cmd2; + + /* make C compiler happy */ + (void) data; + (void) arraylist; + + ptr_cmd1 = (struct t_hook_command_similar *)pointer1; + ptr_cmd2 = (struct t_hook_command_similar *)pointer2; + + if (ptr_cmd1->relevance < ptr_cmd2->relevance) + return -1; + + if (ptr_cmd1->relevance > ptr_cmd2->relevance) + return 1; + + return string_strcasecmp (ptr_cmd1->command, ptr_cmd2->command); +} + +/* + * Frees a similar command. + */ + +void +hook_command_similar_free_cb (void *data, struct t_arraylist *arraylist, + void *pointer) +{ + /* make C compiler happy */ + (void) data; + (void) arraylist; + + free (pointer); +} + +/* + * Builds an arraylist with similar commands. + * + * Note: result must be freed after use. + */ + +struct t_arraylist * +hook_command_build_list_similar_commands (const char *command) +{ + struct t_arraylist *list_commands; + struct t_hook *ptr_hook; + struct t_hook_command_similar *cmd_similar; + char *cmd1, *cmd2; + int length_cmd1, length_cmd2, relevance; + + cmd1 = string_tolower (command); + if (!cmd1) + return NULL; + + length_cmd1 = strlen (cmd1); + + list_commands = arraylist_new (64, 1, 0, + &hook_command_similar_cmp_cb, NULL, + &hook_command_similar_free_cb, NULL); + + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook; + ptr_hook = ptr_hook->next_hook) + { + if (ptr_hook->deleted) + continue; + cmd2 = string_tolower (HOOK_COMMAND(ptr_hook, command)); + if (!cmd2) + continue; + length_cmd2 = strlen (cmd2); + relevance = hook_command_similar_get_relevance (cmd1, length_cmd1, + cmd2, length_cmd2); + cmd_similar = (struct t_hook_command_similar *)malloc ( + sizeof (*cmd_similar)); + if (cmd_similar) + { + cmd_similar->command = HOOK_COMMAND(ptr_hook, command); + cmd_similar->relevance = relevance; + } + arraylist_add (list_commands, cmd_similar); + free (cmd2); + } + + free (cmd1); + + return list_commands; +} + +/* + * Displays similar command when an unknown command has been used, to help + * the user. + */ + +void +hook_command_display_error_unknown (const char *command) +{ + struct t_arraylist *list_commands; + struct t_hook_command_similar *cmd_similar; + char **str_commands; + int i, list_size, found; + + if (!command || !command[0]) + return; + + list_commands = hook_command_build_list_similar_commands (command); + if (!list_commands) + return; + + str_commands = string_dyn_alloc (256); + if (!str_commands) + { + arraylist_free (list_commands); + return; + } + + found = 0; + list_size = arraylist_size (list_commands); + for (i = 0; i < list_size; i++) + { + cmd_similar = (struct t_hook_command_similar *)arraylist_get ( + list_commands, i); + if (cmd_similar->relevance >= 3) + break; + if (found > 0) + string_dyn_concat (str_commands, ", ", -1); + string_dyn_concat (str_commands, cmd_similar->command, -1); + found++; + if (found >= 5) + break; + } + if (found == 0) + string_dyn_concat (str_commands, "-", -1); + + gui_chat_printf_date_tags ( + NULL, + 0, GUI_FILTER_TAG_NO_FILTER, + _("%sUnknown command \"%s\" (type /help for help), " + "commands with similar name: %s"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + command, + *str_commands); + + string_dyn_free (str_commands, 1); + arraylist_free (list_commands); +} + /* * Frees data in a command hook. */ diff --git a/src/core/hook/wee-hook-command.h b/src/core/hook/wee-hook-command.h index 41e28363e..cec93e575 100644 --- a/src/core/hook/wee-hook-command.h +++ b/src/core/hook/wee-hook-command.h @@ -65,6 +65,13 @@ struct t_hook_command char **cplt_template_args_concat; /* concatenated arguments */ }; +struct t_hook_command_similar +{ + const char *command; /* pointer to command name */ + int relevance; /* lower is better: mostly based on */ + /* Levenshtein distance between cmds */ +}; + extern char *hook_command_get_description (struct t_hook *hook); extern struct t_hook *hook_command (struct t_weechat_plugin *plugin, const char *command, @@ -78,6 +85,7 @@ extern struct t_hook *hook_command (struct t_weechat_plugin *plugin, extern int hook_command_exec (struct t_gui_buffer *buffer, int any_plugin, struct t_weechat_plugin *plugin, const char *string); +extern void hook_command_display_error_unknown (const char *command); extern void hook_command_free_data (struct t_hook *hook); extern int hook_command_add_to_infolist (struct t_infolist_item *item, struct t_hook *hook); diff --git a/src/core/wee-input.c b/src/core/wee-input.c index d10cdd038..a287d7152 100644 --- a/src/core/wee-input.c +++ b/src/core/wee-input.c @@ -82,6 +82,7 @@ input_exec_command (struct t_gui_buffer *buffer, { char *command, *command_name, *pos; char **old_commands_allowed, **new_commands_allowed; + const char *ptr_command_name; int rc; if ((!string) || (!string[0])) @@ -135,9 +136,11 @@ input_exec_command (struct t_gui_buffer *buffer, goto end; } + ptr_command_name = utf8_next_char (command_name); + /* check if command is allowed */ if (input_commands_allowed - && !string_match_list (command_name + 1, + && !string_match_list (ptr_command_name, (const char **)input_commands_allowed, 1)) { if (weechat_debug_core >= 1) @@ -176,11 +179,7 @@ input_exec_command (struct t_gui_buffer *buffer, } else { - gui_chat_printf_date_tags (NULL, 0, GUI_FILTER_TAG_NO_FILTER, - _("%sUnknown command \"%s\" " - "(type /help for help)"), - gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], - command_name); + hook_command_display_error_unknown (ptr_command_name); rc = WEECHAT_RC_ERROR; } break;