diff options
author | James Booth <boothj5@gmail.com> | 2016-05-23 22:34:45 +0100 |
---|---|---|
committer | James Booth <boothj5@gmail.com> | 2016-05-23 22:34:45 +0100 |
commit | 0edd4309257a8372761f44cbd576b027d1b9766c (patch) | |
tree | a34f200941578e4a6d351aacec4965f1c5207149 | |
parent | 3aa788772ea74724ca49ab8488168144bb287daa (diff) | |
parent | d0117cdabe5803867596c1256a68a22245abf166 (diff) | |
download | profani-tty-0edd4309257a8372761f44cbd576b027d1b9766c.tar.gz |
Merge branch 'cmd-tidy'
31 files changed, 5646 insertions, 5499 deletions
diff --git a/Makefile.am b/Makefile.am index 52ae369f..a2c023c5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,8 +30,9 @@ core_sources = \ src/ui/privwin.c \ src/ui/mucconfwin.c \ src/ui/xmlwin.c \ - src/command/command.h src/command/command.c \ - src/command/commands.h src/command/commands.c \ + src/command/cmd_defs.h src/command/cmd_defs.c \ + src/command/cmd_funcs.h src/command/cmd_funcs.c \ + src/command/cmd_ac.h src/command/cmd_ac.c \ src/tools/parser.c \ src/tools/parser.h \ src/tools/http_upload.c \ @@ -67,8 +68,9 @@ unittest_sources = \ src/ui/ui.h \ src/otr/otr.h \ src/pgp/gpg.h \ - src/command/command.h src/command/command.c \ - src/command/commands.h src/command/commands.c \ + src/command/cmd_defs.h src/command/cmd_defs.c \ + src/command/cmd_funcs.h src/command/cmd_funcs.c \ + src/command/cmd_ac.h src/command/cmd_ac.c \ src/tools/parser.c \ src/tools/parser.h \ src/tools/p_sha1.h src/tools/p_sha1.c \ diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c new file mode 100644 index 00000000..4ecbdae3 --- /dev/null +++ b/src/command/cmd_ac.c @@ -0,0 +1,2918 @@ +/* + * cmd_ac.c + * + * Copyright (C) 2012 - 2016 James Booth <boothj5@gmail.com> + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see <http://www.gnu.org/licenses/>. + * + * In addition, as a special exception, the copyright holders give permission to + * link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. + * + * You must obey the GNU General Public License in all respects for all of the + * code used other than OpenSSL. If you modify file(s) with this exception, you + * may extend this exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. If you delete this exception statement from all + * source files in the program, then also delete it here. + * + */ + +#define _GNU_SOURCE 1 + +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <libgen.h> +#include <dirent.h> + +#include "common.h" +#include "tools/parser.h" +#include "ui/win_types.h" +#include "command/cmd_funcs.h" +#include "config/preferences.h" +#include "config/scripts.h" +#include "muc.h" +#include "xmpp/xmpp.h" +#include "roster_list.h" +#include "window_list.h" +#include "plugins/plugins.h" +#include "command/cmd_ac.h" + +#ifdef HAVE_LIBGPGME +#include "pgp/gpg.h" +#endif + +static char* _sub_autocomplete(ProfWin *window, const char *const input); +static char* _notify_autocomplete(ProfWin *window, const char *const input); +static char* _theme_autocomplete(ProfWin *window, const char *const input); +static char* _autoaway_autocomplete(ProfWin *window, const char *const input); +static char* _autoconnect_autocomplete(ProfWin *window, const char *const input); +static char* _account_autocomplete(ProfWin *window, const char *const input); +static char* _who_autocomplete(ProfWin *window, const char *const input); +static char* _roster_autocomplete(ProfWin *window, const char *const input); +static char* _group_autocomplete(ProfWin *window, const char *const input); +static char* _bookmark_autocomplete(ProfWin *window, const char *const input); +static char* _otr_autocomplete(ProfWin *window, const char *const input); +static char* _pgp_autocomplete(ProfWin *window, const char *const input); +static char* _connect_autocomplete(ProfWin *window, const char *const input); +static char* _statuses_autocomplete(ProfWin *window, const char *const input); +static char* _alias_autocomplete(ProfWin *window, const char *const input); +static char* _join_autocomplete(ProfWin *window, const char *const input); +static char* _log_autocomplete(ProfWin *window, const char *const input); +static char* _form_autocomplete(ProfWin *window, const char *const input); +static char* _form_field_autocomplete(ProfWin *window, const char *const input); +static char* _occupants_autocomplete(ProfWin *window, const char *const input); +static char* _kick_autocomplete(ProfWin *window, const char *const input); +static char* _ban_autocomplete(ProfWin *window, const char *const input); +static char* _affiliation_autocomplete(ProfWin *window, const char *const input); +static char* _role_autocomplete(ProfWin *window, const char *const input); +static char* _resource_autocomplete(ProfWin *window, const char *const input); +static char* _titlebar_autocomplete(ProfWin *window, const char *const input); +static char* _inpblock_autocomplete(ProfWin *window, const char *const input); +static char* _time_autocomplete(ProfWin *window, const char *const input); +static char* _receipts_autocomplete(ProfWin *window, const char *const input); +static char* _help_autocomplete(ProfWin *window, const char *const input); +static char* _wins_autocomplete(ProfWin *window, const char *const input); +static char* _tls_autocomplete(ProfWin *window, const char *const input); +static char* _script_autocomplete(ProfWin *window, const char *const input); +static char* _subject_autocomplete(ProfWin *window, const char *const input); +static char* _console_autocomplete(ProfWin *window, const char *const input); +static char* _win_autocomplete(ProfWin *window, const char *const input); +static char* _close_autocomplete(ProfWin *window, const char *const input); +static char* _plugins_autocomplete(ProfWin *window, const char *const input); +static char* _sendfile_autocomplete(ProfWin *window, const char *const input); +static char* _blocked_autocomplete(ProfWin *window, const char *const input); +static char *_tray_autocomplete(ProfWin *window, const char *const input); + +static char* _script_autocomplete_func(const char *const prefix); + +static char* _cmd_ac_complete_params(ProfWin *window, const char *const input); + +static Autocomplete commands_ac; +static Autocomplete who_room_ac; +static Autocomplete who_roster_ac; +static Autocomplete help_ac; +static Autocomplete help_commands_ac; +static Autocomplete notify_ac; +static Autocomplete notify_chat_ac; +static Autocomplete notify_room_ac; +static Autocomplete notify_typing_ac; +static Autocomplete notify_mention_ac; +static Autocomplete notify_trigger_ac; +static Autocomplete prefs_ac; +static Autocomplete sub_ac; +static Autocomplete log_ac; +static Autocomplete autoaway_ac; +static Autocomplete autoaway_mode_ac; +static Autocomplete autoaway_presence_ac; +static Autocomplete autoconnect_ac; +static Autocomplete titlebar_ac; +static Autocomplete theme_ac; +static Autocomplete theme_load_ac; +static Autocomplete account_ac; +static Autocomplete account_set_ac; +static Autocomplete account_clear_ac; +static Autocomplete account_default_ac; +static Autocomplete account_status_ac; +static Autocomplete disco_ac; +static Autocomplete wins_ac; +static Autocomplete roster_ac; +static Autocomplete roster_show_ac; +static Autocomplete roster_by_ac; +static Autocomplete roster_count_ac; +static Autocomplete roster_order_ac; +static Autocomplete roster_header_ac; +static Autocomplete roster_contact_ac; +static Autocomplete roster_resource_ac; +static Autocomplete roster_presence_ac; +static Autocomplete roster_char_ac; +static Autocomplete roster_remove_all_ac; +static Autocomplete roster_room_ac; +static Autocomplete roster_room_position_ac; +static Autocomplete roster_room_by_ac; +static Autocomplete roster_room_order_ac; +static Autocomplete roster_unread_ac; +static Autocomplete roster_private_ac; +static Autocomplete group_ac; +static Autocomplete bookmark_ac; +static Autocomplete bookmark_property_ac; +static Autocomplete otr_ac; +static Autocomplete otr_log_ac; +static Autocomplete otr_policy_ac; +static Autocomplete connect_property_ac; +static Autocomplete tls_property_ac; +static Autocomplete statuses_ac; +static Autocomplete statuses_setting_ac; +static Autocomplete alias_ac; +static Autocomplete aliases_ac; +static Autocomplete join_property_ac; +static Autocomplete room_ac; +static Autocomplete affiliation_ac; +static Autocomplete role_ac; +static Autocomplete privilege_cmd_ac; +static Autocomplete subject_ac; +static Autocomplete form_ac; +static Autocomplete form_field_multi_ac; +static Autocomplete occupants_ac; +static Autocomplete occupants_default_ac; +static Autocomplete occupants_show_ac; +static Autocomplete time_ac; +static Autocomplete time_format_ac; +static Autocomplete resource_ac; +static Autocomplete inpblock_ac; +static Autocomplete receipts_ac; +static Autocomplete pgp_ac; +static Autocomplete pgp_log_ac; +static Autocomplete tls_ac; +static Autocomplete tls_certpath_ac; +static Autocomplete script_ac; +static Autocomplete script_show_ac; +static Autocomplete console_ac; +static Autocomplete console_msg_ac; +static Autocomplete autoping_ac; +static Autocomplete plugins_ac; +static Autocomplete plugins_load_ac; +static Autocomplete sendfile_ac; +static Autocomplete blocked_ac; +static Autocomplete tray_ac; + +void +cmd_ac_init(void) +{ + commands_ac = autocomplete_new(); + aliases_ac = autocomplete_new(); + + help_ac = autocomplete_new(); + autocomplete_add(help_ac, "commands"); + autocomplete_add(help_ac, "navigation"); + + help_commands_ac = autocomplete_new(); + autocomplete_add(help_commands_ac, "chat"); + autocomplete_add(help_commands_ac, "groupchat"); + autocomplete_add(help_commands_ac, "roster"); + autocomplete_add(help_commands_ac, "presence"); + autocomplete_add(help_commands_ac, "discovery"); + autocomplete_add(help_commands_ac, "connection"); + autocomplete_add(help_commands_ac, "ui"); + autocomplete_add(help_commands_ac, "plugins"); + + prefs_ac = autocomplete_new(); + autocomplete_add(prefs_ac, "ui"); + autocomplete_add(prefs_ac, "desktop"); + autocomplete_add(prefs_ac, "chat"); + autocomplete_add(prefs_ac, "log"); + autocomplete_add(prefs_ac, "conn"); + autocomplete_add(prefs_ac, "presence"); + autocomplete_add(prefs_ac, "otr"); + autocomplete_add(prefs_ac, "pgp"); + + notify_ac = autocomplete_new(); + autocomplete_add(notify_ac, "chat"); + autocomplete_add(notify_ac, "room"); + autocomplete_add(notify_ac, "typing"); + autocomplete_add(notify_ac, "remind"); + autocomplete_add(notify_ac, "invite"); + autocomplete_add(notify_ac, "sub"); + autocomplete_add(notify_ac, "on"); + autocomplete_add(notify_ac, "off"); + autocomplete_add(notify_ac, "mention"); + autocomplete_add(notify_ac, "trigger"); + autocomplete_add(notify_ac, "reset"); + + notify_chat_ac = autocomplete_new(); + autocomplete_add(notify_chat_ac, "on"); + autocomplete_add(notify_chat_ac, "off"); + autocomplete_add(notify_chat_ac, "current"); + autocomplete_add(notify_chat_ac, "text"); + + notify_room_ac = autocomplete_new(); + autocomplete_add(notify_room_ac, "on"); + autocomplete_add(notify_room_ac, "off"); + autocomplete_add(notify_room_ac, "mention"); + autocomplete_add(notify_room_ac, "current"); + autocomplete_add(notify_room_ac, "text"); + autocomplete_add(notify_room_ac, "trigger"); + + notify_typing_ac = autocomplete_new(); + autocomplete_add(notify_typing_ac, "on"); + autocomplete_add(notify_typing_ac, "off"); + autocomplete_add(notify_typing_ac, "current"); + + notify_mention_ac = autocomplete_new(); + autocomplete_add(notify_mention_ac, "on"); + autocomplete_add(notify_mention_ac, "off"); + autocomplete_add(notify_mention_ac, "case_sensitive"); + autocomplete_add(notify_mention_ac, "case_insensitive"); + autocomplete_add(notify_mention_ac, "word_whole"); + autocomplete_add(notify_mention_ac, "word_part"); + + notify_trigger_ac = autocomplete_new(); + autocomplete_add(notify_trigger_ac, "add"); + autocomplete_add(notify_trigger_ac, "remove"); + autocomplete_add(notify_trigger_ac, "list"); + autocomplete_add(notify_trigger_ac, "on"); + autocomplete_add(notify_trigger_ac, "off"); + + sub_ac = autocomplete_new(); + autocomplete_add(sub_ac, "request"); + autocomplete_add(sub_ac, "allow"); + autocomplete_add(sub_ac, "deny"); + autocomplete_add(sub_ac, "show"); + autocomplete_add(sub_ac, "sent"); + autocomplete_add(sub_ac, "received"); + + titlebar_ac = autocomplete_new(); + autocomplete_add(titlebar_ac, "show"); + autocomplete_add(titlebar_ac, "goodbye"); + + log_ac = autocomplete_new(); + autocomplete_add(log_ac, "maxsize"); + autocomplete_add(log_ac, "rotate"); + autocomplete_add(log_ac, "shared"); + autocomplete_add(log_ac, "where"); + + autoaway_ac = autocomplete_new(); + autocomplete_add(autoaway_ac, "mode"); + autocomplete_add(autoaway_ac, "time"); + autocomplete_add(autoaway_ac, "message"); + autocomplete_add(autoaway_ac, "check"); + + autoaway_mode_ac = autocomplete_new(); + autocomplete_add(autoaway_mode_ac, "away"); + autocomplete_add(autoaway_mode_ac, "idle"); + autocomplete_add(autoaway_mode_ac, "off"); + + autoaway_presence_ac = autocomplete_new(); + autocomplete_add(autoaway_presence_ac, "away"); + autocomplete_add(autoaway_presence_ac, "xa"); + + autoconnect_ac = autocomplete_new(); + autocomplete_add(autoconnect_ac, "set"); + autocomplete_add(autoconnect_ac, "off"); + + theme_ac = autocomplete_new(); + autocomplete_add(theme_ac, "load"); + autocomplete_add(theme_ac, "list"); + autocomplete_add(theme_ac, "colours"); + autocomplete_add(theme_ac, "properties"); + + disco_ac = autocomplete_new(); + autocomplete_add(disco_ac, "info"); + autocomplete_add(disco_ac, "items"); + + account_ac = autocomplete_new(); + autocomplete_add(account_ac, "list"); + autocomplete_add(account_ac, "show"); + autocomplete_add(account_ac, "add"); + autocomplete_add(account_ac, "remove"); + autocomplete_add(account_ac, "enable"); + autocomplete_add(account_ac, "disable"); + autocomplete_add(account_ac, "default"); + autocomplete_add(account_ac, "rename"); + autocomplete_add(account_ac, "set"); + autocomplete_add(account_ac, "clear"); + + account_set_ac = autocomplete_new(); + autocomplete_add(account_set_ac, "jid"); + autocomplete_add(account_set_ac, "server"); + autocomplete_add(account_set_ac, "port"); + autocomplete_add(account_set_ac, "status"); + autocomplete_add(account_set_ac, "online"); + autocomplete_add(account_set_ac, "chat"); + autocomplete_add(account_set_ac, "away"); + autocomplete_add(account_set_ac, "xa"); + autocomplete_add(account_set_ac, "dnd"); + autocomplete_add(account_set_ac, "resource"); + autocomplete_add(account_set_ac, "password"); + autocomplete_add(account_set_ac, "eval_password"); + autocomplete_add(account_set_ac, "muc"); + autocomplete_add(account_set_ac, "nick"); + autocomplete_add(account_set_ac, "otr"); + autocomplete_add(account_set_ac, "pgpkeyid"); + autocomplete_add(account_set_ac, "startscript"); + autocomplete_add(account_set_ac, "tls"); + autocomplete_add(account_set_ac, "theme"); + + account_clear_ac = autocomplete_new(); + autocomplete_add(account_clear_ac, "password"); + autocomplete_add(account_clear_ac, "eval_password"); + autocomplete_add(account_clear_ac, "server"); + autocomplete_add(account_clear_ac, "port"); + autocomplete_add(account_clear_ac, "otr"); + autocomplete_add(account_clear_ac, "pgpkeyid"); + autocomplete_add(account_clear_ac, "startscript"); + autocomplete_add(account_clear_ac, "theme"); + + account_default_ac = autocomplete_new(); + autocomplete_add(account_default_ac, "set"); + autocomplete_add(account_default_ac, "off"); + + account_status_ac = autocomplete_new(); + autocomplete_add(account_status_ac, "online"); + autocomplete_add(account_status_ac, "chat"); + autocomplete_add(account_status_ac, "away"); + autocomplete_add(account_status_ac, "xa"); + autocomplete_add(account_status_ac, "dnd"); + autocomplete_add(account_status_ac, "last"); + + wins_ac = autocomplete_new(); + autocomplete_add(wins_ac, "unread"); + autocomplete_add(wins_ac, "prune"); + autocomplete_add(wins_ac, "tidy"); + autocomplete_add(wins_ac, "autotidy"); + autocomplete_add(wins_ac, "swap"); + + roster_ac = autocomplete_new(); + autocomplete_add(roster_ac, "add"); + autocomplete_add(roster_ac, "online"); + autocomplete_add(roster_ac, "nick"); + autocomplete_add(roster_ac, "clearnick"); + autocomplete_add(roster_ac, "remove"); + autocomplete_add(roster_ac, "remove_all"); + autocomplete_add(roster_ac, "show"); + autocomplete_add(roster_ac, "hide"); + autocomplete_add(roster_ac, "by"); + autocomplete_add(roster_ac, "count"); + autocomplete_add(roster_ac, "order"); + autocomplete_add(roster_ac, "unread"); + autocomplete_add(roster_ac, "room"); + autocomplete_add(roster_ac, "size"); + autocomplete_add(roster_ac, "wrap"); + autocomplete_add(roster_ac, "header"); + autocomplete_add(roster_ac, "contact"); + autocomplete_add(roster_ac, "resource"); + autocomplete_add(roster_ac, "presence"); + autocomplete_add(roster_ac, "private"); + + roster_private_ac = autocomplete_new(); + autocomplete_add(roster_private_ac, "room"); + autocomplete_add(roster_private_ac, "group"); + autocomplete_add(roster_private_ac, "off"); + autocomplete_add(roster_private_ac, "char"); + + roster_header_ac = autocomplete_new(); + autocomplete_add(roster_header_ac, "char"); + + roster_contact_ac = autocomplete_new(); + autocomplete_add(roster_contact_ac, "char"); + autocomplete_add(roster_contact_ac, "indent"); + + roster_resource_ac = autocomplete_new(); + autocomplete_add(roster_resource_ac, "char"); + autocomplete_add(roster_resource_ac, "indent"); + autocomplete_add(roster_resource_ac, "join"); + + roster_presence_ac = autocomplete_new(); + autocomplete_add(roster_presence_ac, "indent"); + + roster_char_ac = autocomplete_new(); + autocomplete_add(roster_char_ac, "none"); + + roster_show_ac = autocomplete_new(); + autocomplete_add(roster_show_ac, "offline"); + autocomplete_add(roster_show_ac, "resource"); + autocomplete_add(roster_show_ac, "presence"); + autocomplete_add(roster_show_ac, "status"); + autocomplete_add(roster_show_ac, "empty"); + autocomplete_add(roster_show_ac, "priority"); + autocomplete_add(roster_show_ac, "contacts"); + autocomplete_add(roster_show_ac, "unsubscribed"); + autocomplete_add(roster_show_ac, "rooms"); + + roster_by_ac = autocomplete_new(); + autocomplete_add(roster_by_ac, "group"); + autocomplete_add(roster_by_ac, "presence"); + autocomplete_add(roster_by_ac, "none"); + + roster_count_ac = autocomplete_new(); + autocomplete_add(roster_count_ac, "unread"); + autocomplete_add(roster_count_ac, "items"); + autocomplete_add(roster_count_ac, "off"); + autocomplete_add(roster_count_ac, "zero"); + + roster_order_ac = autocomplete_new(); + autocomplete_add(roster_order_ac, "name"); + autocomplete_add(roster_order_ac, "presence"); + + roster_unread_ac = autocomplete_new(); + autocomplete_add(roster_unread_ac, "before"); + autocomplete_add(roster_unread_ac, "after"); + autocomplete_add(roster_unread_ac, "off"); + + roster_room_ac = autocomplete_new(); + autocomplete_add(roster_room_ac, "char"); + autocomplete_add(roster_room_ac, "position"); + autocomplete_add(roster_room_ac, "by"); + autocomplete_add(roster_room_ac, "order"); + autocomplete_add(roster_room_ac, "unread"); + autocomplete_add(roster_room_ac, "private"); + + roster_room_by_ac = autocomplete_new(); + autocomplete_add(roster_room_by_ac, "service"); + autocomplete_add(roster_room_by_ac, "none"); + + roster_room_order_ac = autocomplete_new(); + autocomplete_add(roster_room_order_ac, "name"); + autocomplete_add(roster_room_order_ac, "unread"); + + roster_room_position_ac = autocomplete_new(); + autocomplete_add(roster_room_position_ac, "first"); + autocomplete_add(roster_room_position_ac, "last"); + + roster_remove_all_ac = autocomplete_new(); + autocomplete_add(roster_remove_all_ac, "contacts"); + + group_ac = autocomplete_new(); + autocomplete_add(group_ac, "show"); + autocomplete_add(group_ac, "add"); + autocomplete_add(group_ac, "remove"); + + theme_load_ac = NULL; + plugins_load_ac = NULL; + + who_roster_ac = autocomplete_new(); + autocomplete_add(who_roster_ac, "chat"); + autocomplete_add(who_roster_ac, "online"); + autocomplete_add(who_roster_ac, "away"); + autocomplete_add(who_roster_ac, "xa"); + autocomplete_add(who_roster_ac, "dnd"); + autocomplete_add(who_roster_ac, "offline"); + autocomplete_add(who_roster_ac, "available"); + autocomplete_add(who_roster_ac, "unavailable"); + autocomplete_add(who_roster_ac, "any"); + + who_room_ac = autocomplete_new(); + autocomplete_add(who_room_ac, "chat"); + autocomplete_add(who_room_ac, "online"); + autocomplete_add(who_room_ac, "away"); + autocomplete_add(who_room_ac, "xa"); + autocomplete_add(who_room_ac, "dnd"); + autocomplete_add(who_room_ac, "available"); + autocomplete_add(who_room_ac, "unavailable"); + autocomplete_add(who_room_ac, "moderator"); + autocomplete_add(who_room_ac, "participant"); + autocomplete_add(who_room_ac, "visitor"); + autocomplete_add(who_room_ac, "owner"); + autocomplete_add(who_room_ac, "admin"); + autocomplete_add(who_room_ac, "member"); + + bookmark_ac = autocomplete_new(); + autocomplete_add(bookmark_ac, "list"); + autocomplete_add(bookmark_ac, "add"); + autocomplete_add(bookmark_ac, "update"); + autocomplete_add(bookmark_ac, "remove"); + autocomplete_add(bookmark_ac, "join"); + + bookmark_property_ac = autocomplete_new(); + autocomplete_add(bookmark_property_ac, "nick"); + autocomplete_add(bookmark_property_ac, "password"); + autocomplete_add(bookmark_property_ac, "autojoin"); + + otr_ac = autocomplete_new(); + autocomplete_add(otr_ac, "gen"); + autocomplete_add(otr_ac, "start"); + autocomplete_add(otr_ac, "end"); + autocomplete_add(otr_ac, "myfp"); + autocomplete_add(otr_ac, "theirfp"); + autocomplete_add(otr_ac, "trust"); + autocomplete_add(otr_ac, "untrust"); + autocomplete_add(otr_ac, "secret"); + autocomplete_add(otr_ac, "log"); + autocomplete_add(otr_ac, "libver"); + autocomplete_add(otr_ac, "policy"); + autocomplete_add(otr_ac, "question"); + autocomplete_add(otr_ac, "answer"); + autocomplete_add(otr_ac, "char"); + + otr_log_ac = autocomplete_new(); + autocomplete_add(otr_log_ac, "on"); + autocomplete_add(otr_log_ac, "off"); + autocomplete_add(otr_log_ac, "redact"); + + otr_policy_ac = autocomplete_new(); + autocomplete_add(otr_policy_ac, "manual"); + autocomplete_add(otr_policy_ac, "opportunistic"); + autocomplete_add(otr_policy_ac, "always"); + + connect_property_ac = autocomplete_new(); + autocomplete_add(connect_property_ac, "server"); + autocomplete_add(connect_property_ac, "port"); + autocomplete_add(connect_property_ac, "tls"); + + tls_property_ac = autocomplete_new(); + autocomplete_add(tls_property_ac, "force"); + autocomplete_add(tls_property_ac, "allow"); + autocomplete_add(tls_property_ac, "disable"); + + join_property_ac = autocomplete_new(); + autocomplete_add(join_property_ac, "nick"); + autocomplete_add(join_property_ac, "password"); + + statuses_ac = autocomplete_new(); + autocomplete_add(statuses_ac, "console"); + autocomplete_add(statuses_ac, "chat"); + autocomplete_add(statuses_ac, "muc"); + + statuses_setting_ac = autocomplete_new(); + autocomplete_add(statuses_setting_ac, "all"); + autocomplete_add(statuses_setting_ac, "online"); + autocomplete_add(statuses_setting_ac, "none"); + + alias_ac = autocomplete_new(); + autocomplete_add(alias_ac, "add"); + autocomplete_add(alias_ac, "remove"); + autocomplete_add(alias_ac, "list"); + + room_ac = autocomplete_new(); + autocomplete_add(room_ac, "accept"); + autocomplete_add(room_ac, "destroy"); + autocomplete_add(room_ac, "config"); + + affiliation_ac = autocomplete_new(); + autocomplete_add(affiliation_ac, "owner"); + autocomplete_add(affiliation_ac, "admin"); + autocomplete_add(affiliation_ac, "member"); + autocomplete_add(affiliation_ac, "none"); + autocomplete_add(affiliation_ac, "outcast"); + + role_ac = autocomplete_new(); + autocomplete_add(role_ac, "moderator"); + autocomplete_add(role_ac, "participant"); + autocomplete_add(role_ac, "visitor"); + autocomplete_add(role_ac, "none"); + + privilege_cmd_ac = autocomplete_new(); + autocomplete_add(privilege_cmd_ac, "list"); + autocomplete_add(privilege_cmd_ac, "set"); + + subject_ac = autocomplete_new(); + autocomplete_add(subject_ac, "set"); + autocomplete_add(subject_ac, "edit"); + autocomplete_add(subject_ac, "prepend"); + autocomplete_add(subject_ac, "append"); + autocomplete_add(subject_ac, "clear"); + + form_ac = autocomplete_new(); + autocomplete_add(form_ac, "submit"); + autocomplete_add(form_ac, "cancel"); + autocomplete_add(form_ac, "show"); + autocomplete_add(form_ac, "help"); + + form_field_multi_ac = autocomplete_new(); + autocomplete_add(form_field_multi_ac, "add"); + autocomplete_add(form_field_multi_ac, "remove"); + + occupants_ac = autocomplete_new(); + autocomplete_add(occupants_ac, "show"); + autocomplete_add(occupants_ac, "hide"); + autocomplete_add(occupants_ac, "default"); + autocomplete_add(occupants_ac, "size"); + + occupants_default_ac = autocomplete_new(); + autocomplete_add(occupants_default_ac, "show"); + autocomplete_add(occupants_default_ac, "hide"); + + occupants_show_ac = autocomplete_new(); + autocomplete_add(occupants_show_ac, "jid"); + + time_ac = autocomplete_new(); + autocomplete_add(time_ac, "console"); + autocomplete_add(time_ac, "chat"); + autocomplete_add(time_ac, "muc"); + autocomplete_add(time_ac, "mucconfig"); + autocomplete_add(time_ac, "private"); + autocomplete_add(time_ac, "xml"); + autocomplete_add(time_ac, "statusbar"); + autocomplete_add(time_ac, "lastactivity"); + + time_format_ac = autocomplete_new(); + autocomplete_add(time_format_ac, "set"); + autocomplete_add(time_format_ac, "off"); + + resource_ac = autocomplete_new(); + autocomplete_add(resource_ac, "set"); + autocomplete_add(resource_ac, "off"); + autocomplete_add(resource_ac, "title"); + autocomplete_add(resource_ac, "message"); + + inpblock_ac = autocomplete_new(); + autocomplete_add(inpblock_ac, "timeout"); + autocomplete_add(inpblock_ac, "dynamic"); + + receipts_ac = autocomplete_new(); + autocomplete_add(receipts_ac, "send"); + autocomplete_add(receipts_ac, "request"); + + pgp_ac = autocomplete_new(); + autocomplete_add(pgp_ac, "keys"); + autocomplete_add(pgp_ac, "contacts"); + autocomplete_add(pgp_ac, "setkey"); + autocomplete_add(pgp_ac, "libver"); + autocomplete_add(pgp_ac, "start"); + autocomplete_add(pgp_ac, "end"); + autocomplete_add(pgp_ac, "log"); + autocomplete_add(pgp_ac, "char"); + + pgp_log_ac = autocomplete_new(); + autocomplete_add(pgp_log_ac, "on"); + autocomplete_add(pgp_log_ac, "off"); + autocomplete_add(pgp_log_ac, "redact"); + + tls_ac = autocomplete_new(); + autocomplete_add(tls_ac, "allow"); + autocomplete_add(tls_ac, "always"); + autocomplete_add(tls_ac, "deny"); + autocomplete_add(tls_ac, "cert"); + autocomplete_add(tls_ac, "trust"); + autocomplete_add(tls_ac, "trusted"); + autocomplete_add(tls_ac, "revoke"); + autocomplete_add(tls_ac, "certpath"); + autocomplete_add(tls_ac, "show"); + + tls_certpath_ac = autocomplete_new(); + autocomplete_add(tls_certpath_ac, "set"); + autocomplete_add(tls_certpath_ac, "clear"); + + script_ac = autocomplete_new(); + autocomplete_add(script_ac, "run"); + autocomplete_add(script_ac, "list"); + autocomplete_add(script_ac, "show"); + + script_show_ac = NULL; + + console_ac = autocomplete_new(); + autocomplete_add(console_ac, "chat"); + autocomplete_add(console_ac, "muc"); + autocomplete_add(console_ac, "private"); + + console_msg_ac = autocomplete_new(); + autocomplete_add(console_msg_ac, "all"); + autocomplete_add(console_msg_ac, "first"); + autocomplete_add(console_msg_ac, "none"); + + autoping_ac = autocomplete_new(); + autocomplete_add(autoping_ac, "set"); + autocomplete_add(autoping_ac, "timeout"); + + plugins_ac = autocomplete_new(); + autocomplete_add(plugins_ac, "load"); + + sendfile_ac = autocomplete_new(); + + blocked_ac = autocomplete_new(); + autocomplete_add(blocked_ac, "add"); + autocomplete_add(blocked_ac, "remove"); + + tray_ac = autocomplete_new(); + autocomplete_add(tray_ac, "on"); + autocomplete_add(tray_ac, "off"); + autocomplete_add(tray_ac, "read"); + autocomplete_add(tray_ac, "timer"); +} + +void +cmd_ac_add(const char *const value) +{ + if (commands_ac) { + autocomplete_add(commands_ac, value); + } +} + +void +cmd_ac_add_help(const char *const value) +{ + if (help_ac) { + autocomplete_add(help_ac, value); + } +} + +void +cmd_ac_add_cmd(Command *command) +{ + autocomplete_add(commands_ac, command->cmd); + autocomplete_add(help_ac, command->cmd+1); +} + +void +cmd_ac_add_alias(ProfAlias *alias) +{ + GString *ac_alias = g_string_new("/"); + g_string_append(ac_alias, alias->name); + autocomplete_add(commands_ac, ac_alias->str); + autocomplete_add(aliases_ac, alias->name); + g_string_free(ac_alias, TRUE); +} + +void +cmd_ac_add_alias_value(char *value) +{ + if (aliases_ac) { + autocomplete_add(aliases_ac, value); + } +} + +void +cmd_ac_remove_alias_value(char *value) +{ + if (aliases_ac) { + autocomplete_remove(aliases_ac, value); + } +} + +void +cmd_ac_remove(const char *const value) +{ + if (commands_ac) { + autocomplete_remove(commands_ac, value); + } +} + +gboolean +cmd_ac_exists(char *cmd) +{ + if (commands_ac == NULL) { + return FALSE; + } else { + return autocomplete_contains(commands_ac, cmd); + } +} + +void +cmd_ac_add_form_fields(DataForm *form) +{ + if (form == NULL) { + return; + } + + GSList *fields = autocomplete_create_list(form->tag_ac); + GSList *curr_field = fields; + while (curr_field) { + GString *field_str = g_string_new("/"); + g_string_append(field_str, curr_field->data); + cmd_ac_add(field_str->str); + g_string_free(field_str, TRUE); + curr_field = g_slist_next(curr_field); + } + g_slist_free_full(fields, free); +} + +void +cmd_ac_remove_form_fields(DataForm *form) +{ + if (form == NULL) { + return; + } + + GSList *fields = autocomplete_create_list(form->tag_ac); + GSList *curr_field = fields; + while (curr_field) { + GString *field_str = g_string_new("/"); + g_string_append(field_str, curr_field->data); + cmd_ac_remove(field_str->str); + g_string_free(field_str, TRUE); + curr_field = g_slist_next(curr_field); + } + g_slist_free_full(fields, free); +} + +char* +cmd_ac_complete(ProfWin *window, const char *const input) +{ + // autocomplete command + if ((strncmp(input, "/", 1) == 0) && (!str_contains(input, strlen(input), ' '))) { + char *found = NULL; + found = autocomplete_complete(commands_ac, input, TRUE); + if (found) { + return found; + } + + // autocomplete parameters + } else { + char *found = _cmd_ac_complete_params(window, input); + if (found) { + return found; + } + } + + return NULL; +} + +void +cmd_ac_reset(ProfWin *window) +{ + jabber_conn_status_t conn_status = connection_get_status(); + if (conn_status == JABBER_CONNECTED) { + roster_reset_search_attempts(); + + if (window->type == WIN_CHAT) { + ProfChatWin *chatwin = (ProfChatWin*)window; + assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); + PContact contact = roster_get_contact(chatwin->barejid); + if (contact) { + p_contact_resource_ac_reset(contact); + } + } + } + + muc_invites_reset_ac(); + accounts_reset_all_search(); + accounts_reset_enabled_search(); + tlscerts_reset_ac(); + prefs_reset_boolean_choice(); + presence_reset_sub_request_search(); +#ifdef HAVE_LIBGPGME + p_gpg_autocomplete_key_reset(); +#endif + autocomplete_reset(help_ac); + autocomplete_reset(help_commands_ac); + autocomplete_reset(notify_ac); + autocomplete_reset(notify_chat_ac); + autocomplete_reset(notify_room_ac); + autocomplete_reset(notify_typing_ac); + autocomplete_reset(notify_mention_ac); + autocomplete_reset(notify_trigger_ac); + autocomplete_reset(sub_ac); + autocomplete_reset(sendfile_ac); + + autocomplete_reset(who_room_ac); + autocomplete_reset(who_roster_ac); + autocomplete_reset(prefs_ac); + autocomplete_reset(log_ac); + autocomplete_reset(commands_ac); + autocomplete_reset(autoaway_ac); + autocomplete_reset(autoaway_mode_ac); + autocomplete_reset(autoaway_presence_ac); + autocomplete_reset(autoconnect_ac); + autocomplete_reset(theme_ac); + if (theme_load_ac) { + autocomplete_free(theme_load_ac); + theme_load_ac = NULL; + } + if (plugins_load_ac) { + autocomplete_free(plugins_load_ac); + plugins_load_ac = NULL; + } + autocomplete_reset(account_ac); + autocomplete_reset(account_set_ac); + autocomplete_reset(account_clear_ac); + autocomplete_reset(account_default_ac); + autocomplete_reset(account_status_ac); + autocomplete_reset(disco_ac); + autocomplete_reset(wins_ac); + autocomplete_reset(roster_ac); + autocomplete_reset(roster_header_ac); + autocomplete_reset(roster_contact_ac); + autocomplete_reset(roster_resource_ac); + autocomplete_reset(roster_presence_ac); + autocomplete_reset(roster_char_ac); + autocomplete_reset(roster_show_ac); + autocomplete_reset(roster_by_ac); + autocomplete_reset(roster_count_ac); + autocomplete_reset(roster_order_ac); + autocomplete_reset(roster_room_ac); + autocomplete_reset(roster_room_by_ac); + autocomplete_reset(roster_unread_ac); + autocomplete_reset(roster_room_position_ac); + autocomplete_reset(roster_room_order_ac); + autocomplete_reset(roster_remove_all_ac); + autocomplete_reset(roster_private_ac); + autocomplete_reset(group_ac); + autocomplete_reset(titlebar_ac); + autocomplete_reset(bookmark_ac); + autocomplete_reset(bookmark_property_ac); + autocomplete_reset(otr_ac); + autocomplete_reset(otr_log_ac); + autocomplete_reset(otr_policy_ac); + autocomplete_reset(connect_property_ac); + autocomplete_reset(tls_property_ac); + autocomplete_reset(statuses_ac); + autocomplete_reset(statuses_setting_ac); + autocomplete_reset(alias_ac); + autocomplete_reset(aliases_ac); + autocomplete_reset(join_property_ac); + autocomplete_reset(room_ac); + autocomplete_reset(affiliation_ac); + autocomplete_reset(role_ac); + autocomplete_reset(privilege_cmd_ac); + autocomplete_reset(subject_ac); + autocomplete_reset(form_ac); + autocomplete_reset(form_field_multi_ac); + autocomplete_reset(occupants_ac); + autocomplete_reset(occupants_default_ac); + autocomplete_reset(occupants_show_ac); + autocomplete_reset(time_ac); + autocomplete_reset(time_format_ac); + autocomplete_reset(resource_ac); + autocomplete_reset(inpblock_ac); + autocomplete_reset(receipts_ac); + autocomplete_reset(pgp_ac); + autocomplete_reset(pgp_log_ac); + autocomplete_reset(tls_ac); + autocomplete_reset(tls_certpath_ac); + autocomplete_reset(console_ac); + autocomplete_reset(console_msg_ac); + autocomplete_reset(autoping_ac); + autocomplete_reset(plugins_ac); + autocomplete_reset(blocked_ac); + autocomplete_reset(tray_ac); + autocomplete_reset(script_ac); + if (script_show_ac) { + autocomplete_free(script_show_ac); + script_show_ac = NULL; + } + + if (window->type == WIN_MUC) { + ProfMucWin *mucwin = (ProfMucWin*)window; + assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); + muc_autocomplete_reset(mucwin->roomjid); + muc_jid_autocomplete_reset(mucwin->roomjid); + } + + if (window->type == WIN_MUC_CONFIG) { + ProfMucConfWin *confwin = (ProfMucConfWin*)window; + assert(confwin->memcheck == PROFCONFWIN_MEMCHECK); + if (confwin->form) { + form_reset_autocompleters(confwin->form); + } + } + + bookmark_autocomplete_reset(); + blocked_ac_reset(); + prefs_reset_room_trigger_ac(); + win_reset_search_attempts(); + win_close_reset_search_attempts(); + plugins_reset_autocomplete(); +} + +void +cmd_ac_uninit(void) +{ + autocomplete_free(commands_ac); + autocomplete_free(who_room_ac); + autocomplete_free(who_roster_ac); + autocomplete_free(help_ac); + autocomplete_free(help_commands_ac); + autocomplete_free(notify_ac); + autocomplete_free(notify_chat_ac); + autocomplete_free(notify_room_ac); + autocomplete_free(notify_typing_ac); + autocomplete_free(notify_mention_ac); + autocomplete_free(notify_trigger_ac); + autocomplete_free(sub_ac); + autocomplete_free(titlebar_ac); + autocomplete_free(log_ac); + autocomplete_free(prefs_ac); + autocomplete_free(autoaway_ac); + autocomplete_free(autoaway_mode_ac); + autocomplete_free(autoaway_presence_ac); + autocomplete_free(autoconnect_ac); + autocomplete_free(theme_ac); + autocomplete_free(theme_load_ac); + autocomplete_free(account_ac); + autocomplete_free(account_set_ac); + autocomplete_free(account_clear_ac); + autocomplete_free(account_default_ac); + autocomplete_free(account_status_ac); + autocomplete_free(disco_ac); + autocomplete_free(wins_ac); + autocomplete_free(roster_ac); + autocomplete_free(roster_header_ac); + autocomplete_free(roster_contact_ac); + autocomplete_free(roster_resource_ac); + autocomplete_free(roster_presence_ac); + autocomplete_free(roster_char_ac); + autocomplete_free(roster_show_ac); + autocomplete_free(roster_by_ac); + autocomplete_free(roster_count_ac); + autocomplete_free(roster_order_ac); + autocomplete_free(roster_room_ac); + autocomplete_free(roster_room_by_ac); + autocomplete_free(roster_unread_ac); + autocomplete_free(roster_room_position_ac); + autocomplete_free(roster_room_order_ac); + autocomplete_free(roster_remove_all_ac); + autocomplete_free(roster_private_ac); + autocomplete_free(group_ac); + autocomplete_free(bookmark_ac); + autocomplete_free(bookmark_property_ac); + autocomplete_free(otr_ac); + autocomplete_free(otr_log_ac); + autocomplete_free(otr_policy_ac); + autocomplete_free(connect_property_ac); + autocomplete_free(tls_property_ac); + autocomplete_free(statuses_ac); + autocomplete_free(statuses_setting_ac); + autocomplete_free(alias_ac); + autocomplete_free(aliases_ac); + autocomplete_free(join_property_ac); + autocomplete_free(room_ac); + autocomplete_free(affiliation_ac); + autocomplete_free(role_ac); + autocomplete_free(privilege_cmd_ac); + autocomplete_free(subject_ac); + autocomplete_free(form_ac); + autocomplete_free(form_field_multi_ac); + autocomplete_free(occupants_ac); + autocomplete_free(occupants_default_ac); + autocomplete_free(occupants_show_ac); + autocomplete_free(time_ac); + autocomplete_free(time_format_ac); + autocomplete_free(resource_ac); + autocomplete_free(inpblock_ac); + autocomplete_free(receipts_ac); + autocomplete_free(pgp_ac); + autocomplete_free(pgp_log_ac); + autocomplete_free(tls_ac); + autocomplete_free(tls_certpath_ac); + autocomplete_free(script_ac); + autocomplete_free(script_show_ac); + autocomplete_free(console_ac); + autocomplete_free(console_msg_ac); + autocomplete_free(autoping_ac); + autocomplete_free(plugins_ac); + autocomplete_free(plugins_load_ac); + autocomplete_free(sendfile_ac); + autocomplete_free(blocked_ac); + autocomplete_free(tray_ac); +} + +static char* +_cmd_ac_complete_params(ProfWin *window, const char *const input) +{ + int i; + char *result = NULL; + + jabber_conn_status_t conn_status = connection_get_status(); + + // autocomplete boolean settings + gchar *boolean_choices[] = { "/beep", "/intype", "/states", "/outtype", "/flash", "/splash", "/chlog", "/grlog", + "/history", "/vercheck", "/privileges", "/presence", "/wrap", "/winstidy", "/carbons", "/encwarn", + "/lastactivity" }; + + for (i = 0; i < ARRAY_SIZE(boolean_choices); i++) { + result = autocomplete_param_with_func(input, boolean_choices[i], prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + } + + // autocomplete nickname in chat rooms + if (window->type == WIN_MUC) { + ProfMucWin *mucwin = (ProfMucWin*)window; + assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); + Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid); + if (nick_ac) { + gchar *nick_choices[] = { "/msg", "/info", "/caps", "/status", "/software" } ; + + // Remove quote character before and after names when doing autocomplete + char *unquoted = strip_arg_quotes(input); + for (i = 0; i < ARRAY_SIZE(nick_choices); i++) { + result = autocomplete_param_with_ac(unquoted, nick_choices[i], nick_ac, TRUE); + if (result) { + free(unquoted); + return result; + } + } + free(unquoted); + } + + // otherwise autocomplete using roster + } else if (conn_status == JABBER_CONNECTED) { + gchar *contact_choices[] = { "/msg", "/info", "/status" }; + // Remove quote character before and after names when doing autocomplete + char *unquoted = strip_arg_quotes(input); + for (i = 0; i < ARRAY_SIZE(contact_choices); i++) { + result = autocomplete_param_with_func(unquoted, contact_choices[i], roster_contact_autocomplete); + if (result) { + free(unquoted); + return result; + } + } + free(unquoted); + + gchar *resource_choices[] = { "/caps", "/software", "/ping" }; + for (i = 0; i < ARRAY_SIZE(resource_choices); i++) { + result = autocomplete_param_with_func(input, resource_choices[i], roster_fulljid_autocomplete); + if (result) { + return result; + } + } + } + + if (conn_status == JABBER_CONNECTED) { + result = autocomplete_param_with_func(input, "/invite", roster_contact_autocomplete); + if (result) { + return result; + } + } + + gchar *invite_choices[] = { "/decline", "/join" }; + for (i = 0; i < ARRAY_SIZE(invite_choices); i++) { + result = autocomplete_param_with_func(input, invite_choices[i], muc_invites_find); + if (result) { + return result; + } + } + + gchar *cmds[] = { "/prefs", "/disco", "/room", "/autoping" }; + Autocomplete completers[] = { prefs_ac, disco_ac, room_ac, autoping_ac }; + + for (i = 0; i < ARRAY_SIZE(cmds); i++) { + result = autocomplete_param_with_ac(input, cmds[i], completers[i], TRUE); + if (result) { + return result; + } + } + + GHashTable *ac_funcs = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(ac_funcs, "/help", _help_autocomplete); + g_hash_table_insert(ac_funcs, "/who", _who_autocomplete); + g_hash_table_insert(ac_funcs, "/sub", _sub_autocomplete); + g_hash_table_insert(ac_funcs, "/notify", _notify_autocomplete); + g_hash_table_insert(ac_funcs, "/autoaway", _autoaway_autocomplete); + g_hash_table_insert(ac_funcs, "/theme", _theme_autocomplete); + g_hash_table_insert(ac_funcs, "/log", _log_autocomplete); + g_hash_table_insert(ac_funcs, "/account", _account_autocomplete); + g_hash_table_insert(ac_funcs, "/roster", _roster_autocomplete); + g_hash_table_insert(ac_funcs, "/group", _group_autocomplete); + g_hash_table_insert(ac_funcs, "/bookmark", _bookmark_autocomplete); + g_hash_table_insert(ac_funcs, "/autoconnect", _autoconnect_autocomplete); + g_hash_table_insert(ac_funcs, "/otr", _otr_autocomplete); + g_hash_table_insert(ac_funcs, "/pgp", _pgp_autocomplete); + g_hash_table_insert(ac_funcs, "/connect", _connect_autocomplete); + g_hash_table_insert(ac_funcs, "/statuses", _statuses_autocomplete); + g_hash_table_insert(ac_funcs, "/alias", _alias_autocomplete); + g_hash_table_insert(ac_funcs, "/join", _join_autocomplete); + g_hash_table_insert(ac_funcs, "/form", _form_autocomplete); + g_hash_table_insert(ac_funcs, "/occupants", _occupants_autocomplete); + g_hash_table_insert(ac_funcs, "/kick", _kick_autocomplete); + g_hash_table_insert(ac_funcs, "/ban", _ban_autocomplete); + g_hash_table_insert(ac_funcs, "/affiliation", _affiliation_autocomplete); + g_hash_table_insert(ac_funcs, "/role", _role_autocomplete); + g_hash_table_insert(ac_funcs, "/resource", _resource_autocomplete); + g_hash_table_insert(ac_funcs, "/titlebar", _titlebar_autocomplete); + g_hash_table_insert(ac_funcs, "/inpblock", _inpblock_autocomplete); + g_hash_table_insert(ac_funcs, "/time", _time_autocomplete); + g_hash_table_insert(ac_funcs, "/receipts", _receipts_autocomplete); + g_hash_table_insert(ac_funcs, "/wins", _wins_autocomplete); + g_hash_table_insert(ac_funcs, "/tls", _tls_autocomplete); + g_hash_table_insert(ac_funcs, "/script", _script_autocomplete); + g_hash_table_insert(ac_funcs, "/subject", _subject_autocomplete); + g_hash_table_insert(ac_funcs, "/console", _console_autocomplete); + g_hash_table_insert(ac_funcs, "/win", _win_autocomplete); + g_hash_table_insert(ac_funcs, "/close", _close_autocomplete); + g_hash_table_insert(ac_funcs, "/plugins", _plugins_autocomplete); + g_hash_table_insert(ac_funcs, "/sendfile", _sendfile_autocomplete); + g_hash_table_insert(ac_funcs, "/blocked", _blocked_autocomplete); + g_hash_table_insert(ac_funcs, "/tray", _tray_autocomplete); + + int len = strlen(input); + char parsed[len+1]; + i = 0; + while (i < len) { + if (input[i] == ' ') { + break; + } else { + parsed[i] = input[i]; + } + i++; + } + parsed[i] = '\0'; + + char * (*ac_func)(ProfWin*, const char * const) = g_hash_table_lookup(ac_funcs, parsed); + if (ac_func) { + result = ac_func(window, input); + if (result) { + g_hash_table_destroy(ac_funcs); + return result; + } + } + g_hash_table_destroy(ac_funcs); + + result = plugins_autocomplete(input); + if (result) { + return result; + } + + if (g_str_has_prefix(input, "/field")) { + result = _form_field_autocomplete(window, input); + if (result) { + return result; + } + } + + return NULL; +} + +static char* +_sub_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + result = autocomplete_param_with_func(input, "/sub allow", presence_sub_request_find); + if (result) { + return result; + } + result = autocomplete_param_with_func(input, "/sub deny", presence_sub_request_find); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/sub", sub_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_tray_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + result = autocomplete_param_with_func(input, "/tray read", prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/tray", tray_ac, FALSE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_who_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + if (window->type == WIN_MUC) { + result = autocomplete_param_with_ac(input, "/who", who_room_ac, TRUE); + if (result) { + return result; + } + } else { + jabber_conn_status_t conn_status = connection_get_status(); + if (conn_status == JABBER_CONNECTED) { + int i = 0; + gchar *group_commands[] = { "/who any", "/who online", "/who offline", + "/who chat", "/who away", "/who xa", "/who dnd", "/who available", + "/who unavailable" }; + + for (i = 0; i < ARRAY_SIZE(group_commands); i++) { + result = autocomplete_param_with_func(input, group_commands[i], roster_group_autocomplete); + if (result) { + return result; + } + } + } + + result = autocomplete_param_with_ac(input, "/who", who_roster_ac, TRUE); + if (result) { + return result; + } + } + + return result; +} + +static char* +_roster_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + result = autocomplete_param_with_ac(input, "/roster room private char", roster_char_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster room private", roster_header_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster header char", roster_char_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster contact char", roster_char_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster room char", roster_char_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster private char", roster_char_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster resource char", roster_char_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_func(input, "/roster resource join", prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster room position", roster_room_position_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster room by", roster_room_by_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster room order", roster_room_order_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster room unread", roster_unread_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_func(input, "/roster count zero", prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + + jabber_conn_status_t conn_status = connection_get_status(); + if (conn_status == JABBER_CONNECTED) { + result = autocomplete_param_with_func(input, "/roster nick", roster_barejid_autocomplete); + if (result) { + return result; + } + result = autocomplete_param_with_func(input, "/roster clearnick", roster_barejid_autocomplete); + if (result) { + return result; + } + result = autocomplete_param_with_func(input, "/roster remove", roster_barejid_autocomplete); + if (result) { + return result; + } + } + + result = autocomplete_param_with_ac(input, "/roster remove_all", roster_remove_all_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster show", roster_show_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster hide", roster_show_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster by", roster_by_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster count", roster_count_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster order", roster_order_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster unread", roster_unread_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster room", roster_room_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_func(input, "/roster wrap", prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster header", roster_header_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster contact", roster_contact_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster resource", roster_resource_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster presence", roster_presence_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster private", roster_private_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster", roster_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_group_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + jabber_conn_status_t conn_status = connection_get_status(); + + if (conn_status == JABBER_CONNECTED) { + result = autocomplete_param_with_func(input, "/group show", roster_group_autocomplete); + if (result) { + return result; + } + result = autocomplete_param_no_with_func(input, "/group add", 4, roster_contact_autocomplete); + if (result) { + return result; + } + result = autocomplete_param_no_with_func(input, "/group remove", 4, roster_contact_autocomplete); + if (result) { + return result; + } + result = autocomplete_param_with_func(input, "/group add", roster_group_autocomplete); + if (result) { + return result; + } + result = autocomplete_param_with_func(input, "/group remove", roster_group_autocomplete); + if (result) { + return result; + } + } + + result = autocomplete_param_with_ac(input, "/group", group_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_blocked_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + result = autocomplete_param_with_func(input, "/blocked remove", blocked_ac_find); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/blocked", blocked_ac, FALSE); + if (result) { + return result; + } + + return NULL; +} + + +static char* +_bookmark_autocomplete(ProfWin *window, const char *const input) +{ + char *found = NULL; + + gboolean result; + gchar **args = parse_args(input, 3, 8, &result); + gboolean handle_options = result && (g_strv_length(args) > 2); + + if (handle_options && ((strcmp(args[0], "add") == 0) || (strcmp(args[0], "update") == 0)) ) { + GString *beginning = g_string_new("/bookmark"); + gboolean autojoin = FALSE; + int num_args = g_strv_length(args); + + g_string_append(beginning, " "); + g_string_append(beginning, args[0]); + g_string_append(beginning, " "); + g_string_append(beginning, args[1]); + if (num_args == 4 && g_strcmp0(args[2], "autojoin") == 0) { + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + autojoin = TRUE; + } + + if (num_args > 4) { + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + g_string_append(beginning, " "); + g_string_append(beginning, args[3]); + if (num_args == 6 && g_strcmp0(args[4], "autojoin") == 0) { + g_string_append(beginning, " "); + g_string_append(beginning, args[4]); + autojoin = TRUE; + } + } + + if (num_args > 6) { + g_string_append(beginning, " "); + g_string_append(beginning, args[4]); + g_string_append(beginning, " "); + g_string_append(beginning, args[5]); + if (num_args == 8 && g_strcmp0(args[6], "autojoin") == 0) { + g_string_append(beginning, " "); + g_string_append(beginning, args[6]); + autojoin = TRUE; + } + } + + if (autojoin) { + found = autocomplete_param_with_func(input, beginning->str, prefs_autocomplete_boolean_choice); + } else { + found = autocomplete_param_with_ac(input, beginning->str, bookmark_property_ac, TRUE); + } + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } + + g_strfreev(args); + + found = autocomplete_param_with_func(input, "/bookmark remove", bookmark_find); + if (found) { + return found; + } + found = autocomplete_param_with_func(input, "/bookmark join", bookmark_find); + if (found) { + return found; + } + found = autocomplete_param_with_func(input, "/bookmark update", bookmark_find); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/bookmark", bookmark_ac, TRUE); + return found; +} + +static char* +_notify_autocomplete(ProfWin *window, const char *const input) +{ + int i = 0; + char *result = NULL; + + result = autocomplete_param_with_func(input, "/notify room trigger remove", prefs_autocomplete_room_trigger); + if (result) { + return result; + } + + gchar *boolean_choices1[] = { "/notify room current", "/notify chat current", "/notify typing current", + "/notify room text", "/notify chat text" }; + for (i = 0; i < ARRAY_SIZE(boolean_choices1); i++) { + result = autocomplete_param_with_func(input, boolean_choices1[i], prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + } + + result = autocomplete_param_with_ac(input, "/notify room mention", notify_mention_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/notify room trigger", notify_trigger_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/notify room", notify_room_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/notify chat", notify_chat_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/notify typing", notify_typing_ac, TRUE); + if (result) { + return result; + } + + gchar *boolean_choices2[] = { "/notify invite", "/notify sub", "/notify mention", "/notify trigger"}; + for (i = 0; i < ARRAY_SIZE(boolean_choices2); i++) { + result = autocomplete_param_with_func(input, boolean_choices2[i], prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + } + + result = autocomplete_param_with_ac(input, "/notify", notify_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_autoaway_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + result = autocomplete_param_with_ac(input, "/autoaway mode", autoaway_mode_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/autoaway time", autoaway_presence_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/autoaway message", autoaway_presence_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_func(input, "/autoaway check", prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/autoaway", autoaway_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_log_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + result = autocomplete_param_with_func(input, "/log rotate", + prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + result = autocomplete_param_with_func(input, "/log shared", + prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/log", log_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_autoconnect_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + result = autocomplete_param_with_func(input, "/autoconnect set", accounts_find_enabled); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/autoconnect", autoconnect_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_otr_autocomplete(ProfWin *window, const char *const input) +{ + char *found = NULL; + + jabber_conn_status_t conn_status = connection_get_status(); + + if (conn_status == JABBER_CONNECTED) { + found = autocomplete_param_with_func(input, "/otr start", roster_contact_autocomplete); + if (found) { + return found; + } + } + + found = autocomplete_param_with_ac(input, "/otr log", otr_log_ac, TRUE); + if (found) { + return found; + } + + // /otr policy always user@server.com + if (conn_status == JABBER_CONNECTED) { + gboolean result; + gchar **args = parse_args(input, 3, 3, &result); + if (result && (strcmp(args[0], "policy") == 0)) { + GString *beginning = g_string_new("/otr "); + g_string_append(beginning, args[0]); + g_string_append(beginning, " "); + g_string_append(beginning, args[1]); + + found = autocomplete_param_with_func(input, beginning->str, roster_contact_autocomplete); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } + g_strfreev(args); + } + + found = autocomplete_param_with_ac(input, "/otr policy", otr_policy_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/otr", otr_ac, TRUE); + if (found) { + return found; + } + + return NULL; +} + +static char* +_pgp_autocomplete(ProfWin *window, const char *const input) +{ + char *found = NULL; + + jabber_conn_status_t conn_status = connection_get_status(); + + if (conn_status == JABBER_CONNECTED) { + found = autocomplete_param_with_func(input, "/pgp start", roster_contact_autocomplete); + if (found) { + return found; + } + } + + found = autocomplete_param_with_ac(input, "/pgp log", pgp_log_ac, TRUE); + if (found) { + return found; + } + +#ifdef HAVE_LIBGPGME + gboolean result; + gchar **args = parse_args(input, 2, 3, &result); + if ((strncmp(input, "/pgp", 4) == 0) && (result == TRUE)) { + GString *beginning = g_string_new("/pgp "); + g_string_append(beginning, args[0]); + if (args[1]) { + g_string_append(beginning, " "); + g_string_append(beginning, args[1]); + } + found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } + g_strfreev(args); +#endif + + if (conn_status == JABBER_CONNECTED) { + found = autocomplete_param_with_func(input, "/pgp setkey", roster_barejid_autocomplete); + if (found) { + return found; + } + } + + found = autocomplete_param_with_ac(input, "/pgp", pgp_ac, TRUE); + if (found) { + return found; + } + + return NULL; +} + +static char* +_plugins_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + if ((strncmp(input, "/plugins load ", 14) == 0) && (strlen(input) > 14)) { + if (plugins_load_ac == NULL) { + plugins_load_ac = autocomplete_new(); + GSList *plugins = plugins_unloaded_list(); + GSList *curr = plugins; + while (curr) { + autocomplete_add(plugins_load_ac, curr->data); + curr = g_slist_next(curr); + } + g_slist_free_full(plugins, g_free); + } + result = autocomplete_param_with_ac(input, "/plugins load", plugins_load_ac, TRUE); + if (result) { + return result; + } + } + result = autocomplete_param_with_ac(input, "/plugins", plugins_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_theme_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + if ((strncmp(input, "/theme load ", 12) == 0) && (strlen(input) > 12)) { + if (theme_load_ac == NULL) { + theme_load_ac = autocomplete_new(); + GSList *themes = theme_list(); + GSList *curr = themes; + while (curr) { + autocomplete_add(theme_load_ac, curr->data); + curr = g_slist_next(curr); + } + g_slist_free_full(themes, g_free); + autocomplete_add(theme_load_ac, "default"); + } + result = autocomplete_param_with_ac(input, "/theme load", theme_load_ac, TRUE); + if (result) { + return result; + } + } + result = autocomplete_param_with_ac(input, "/theme", theme_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_script_autocomplete_func(const char *const prefix) +{ + if (script_show_ac == NULL) { + script_show_ac = autocomplete_new(); + GSList *scripts = scripts_list(); + GSList *curr = scripts; + while (curr) { + autocomplete_add(script_show_ac, curr->data); + curr = g_slist_next(curr); + } + g_slist_free_full(scripts, g_free); + } + + return autocomplete_complete(script_show_ac, prefix, FALSE); +} + + +static char* +_script_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + if ((strncmp(input, "/script show ", 13) == 0) && (strlen(input) > 13)) { + result = autocomplete_param_with_func(input, "/script show", _script_autocomplete_func); + if (result) { + return result; + } + } + + if ((strncmp(input, "/script run ", 12) == 0) && (strlen(input) > 12)) { + result = autocomplete_param_with_func(input, "/script run", _script_autocomplete_func); + if (result) { + return result; + } + } + + result = autocomplete_param_with_ac(input, "/script", script_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_resource_autocomplete(ProfWin *window, const char *const input) +{ + char *found = NULL; + + jabber_conn_status_t conn_status = connection_get_status(); + if (conn_status == JABBER_CONNECTED && window->type == WIN_CHAT) { + ProfChatWin *chatwin = (ProfChatWin*)window; + assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); + PContact contact = roster_get_contact(chatwin->barejid); + if (contact) { + Autocomplete ac = p_contact_resource_ac(contact); + found = autocomplete_param_with_ac(input, "/resource set", ac, FALSE); + if (found) { + return found; + } + } + } + + found = autocomplete_param_with_func(input, "/resource title", prefs_autocomplete_boolean_choice); + if (found) { + return found; + } + + found = autocomplete_param_with_func(input, "/resource message", prefs_autocomplete_boolean_choice); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/resource", resource_ac, FALSE); + if (found) { + return found; + } + + return NULL; +} + +static char* +_titlebar_autocomplete(ProfWin *window, const char *const input) +{ + char *found = NULL; + + found = autocomplete_param_with_func(input, "/titlebar show", prefs_autocomplete_boolean_choice); + if (found) { + return found; + } + + found = autocomplete_param_with_func(input, "/titlebar goodbye", prefs_autocomplete_boolean_choice); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/titlebar", titlebar_ac, FALSE); + if (found) { + return found; + } + + return NULL; +} + +static char* +_inpblock_autocomplete(ProfWin *window, const char *const input) +{ + char *found = NULL; + + found = autocomplete_param_with_func(input, "/inpblock dynamic", prefs_autocomplete_boolean_choice); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/inpblock", inpblock_ac, FALSE); + if (found) { + return found; + } + + return NULL; +} + +static char* +_form_autocomplete(ProfWin *window, const char *const input) +{ + if (window->type != WIN_MUC_CONFIG) { + return NULL; + } + + char *found = NULL; + + ProfMucConfWin *confwin = (ProfMucConfWin*)window; + DataForm *form = confwin->form; + if (form) { + found = autocomplete_param_with_ac(input, "/form help", form->tag_ac, TRUE); + if (found) { + return found; + } + } + + found = autocomplete_param_with_ac(input, "/form", form_ac, TRUE); + if (found) { + return found; + } + + return NULL; +} + +static char* +_form_field_autocomplete(ProfWin *window, const char *const input) +{ + if (window->type != WIN_MUC_CONFIG) { + return NULL; + } + + char *found = NULL; + + ProfMucConfWin *confwin = (ProfMucConfWin*)window; + DataForm *form = confwin->form; + if (form == NULL) { + return NULL; + } + + gchar **split = g_strsplit(input, " ", 0); + + if (g_strv_length(split) == 3) { + char *field_tag = split[0]+1; + if (form_tag_exists(form, field_tag)) { + form_field_type_t field_type = form_get_field_type(form, field_tag); + Autocomplete value_ac = form_get_value_ac(form, field_tag);; + GString *beginning = g_string_new(split[0]); + g_string_append(beginning, " "); + g_string_append(beginning, split[1]); + + if (((g_strcmp0(split[1], "add") == 0) || (g_strcmp0(split[1], "remove") == 0)) + && field_type == FIELD_LIST_MULTI) { + found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE); + + } else if ((g_strcmp0(split[1], "remove") == 0) && field_type == FIELD_TEXT_MULTI) { + found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE); + + } else if ((g_strcmp0(split[1], "remove") == 0) && field_type == FIELD_JID_MULTI) { + found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE); + } + + g_string_free(beginning, TRUE); + } + + } else if (g_strv_length(split) == 2) { + char *field_tag = split[0]+1; + if (form_tag_exists(form, field_tag)) { + form_field_type_t field_type = form_get_field_type(form, field_tag); + Autocomplete value_ac = form_get_value_ac(form, field_tag);; + + switch (field_type) + { + case FIELD_BOOLEAN: + found = autocomplete_param_with_func(input, split[0], prefs_autocomplete_boolean_choice); + break; + case FIELD_LIST_SINGLE: + found = autocomplete_param_with_ac(input, split[0], value_ac, TRUE); + break; + case FIELD_LIST_MULTI: + case FIELD_JID_MULTI: + case FIELD_TEXT_MULTI: + found = autocomplete_param_with_ac(input, split[0], form_field_multi_ac, TRUE); + break; + default: + break; + } + } + } + + g_strfreev(split); + + return found; +} + +static char* +_occupants_autocomplete(ProfWin *window, const char *const input) +{ + char *found = NULL; + + found = autocomplete_param_with_ac(input, "/occupants default show", occupants_show_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/occupants default hide", occupants_show_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/occupants default", occupants_default_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/occupants show", occupants_show_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/occupants hide", occupants_show_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/occupants", occupants_ac, TRUE); + if (found) { + return found; + } + + return NULL; +} + +static char* +_time_autocomplete(ProfWin *window, const char *const input) +{ + char *found = NULL; + + found = autocomplete_param_with_ac(input, "/time statusbar", time_format_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/time lastactivity", time_format_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/time console", time_format_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/time chat", time_format_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/time muc", time_format_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/time mucconfig", time_format_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/time private", time_format_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/time xml", time_format_ac, TRUE); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/time", time_ac, TRUE); + if (found) { + return found; + } + + return NULL; +} + +static char* +_kick_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + if (window->type == WIN_MUC) { + ProfMucWin *mucwin = (ProfMucWin*)window; + assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); + Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid); + + if (nick_ac) { + result = autocomplete_param_with_ac(input, "/kick", nick_ac, TRUE); + if (result) { + return result; + } + } + } + + return result; +} + +static char* +_ban_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + if (window->type == WIN_MUC) { + ProfMucWin *mucwin = (ProfMucWin*)window; + assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); + Autocomplete jid_ac = muc_roster_jid_ac(mucwin->roomjid); + + if (jid_ac) { + result = autocomplete_param_with_ac(input, "/ban", jid_ac, TRUE); + if (result) { + return result; + } + } + } + + return result; +} + +static char* +_affiliation_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + if (window->type == WIN_MUC) { + ProfMucWin *mucwin = (ProfMucWin*)window; + assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); + gboolean parse_result; + Autocomplete jid_ac = muc_roster_jid_ac(mucwin->roomjid); + + gchar **args = parse_args(input, 3, 3, &parse_result); + + if ((strncmp(input, "/affiliation", 12) == 0) && (parse_result == TRUE)) { + GString *beginning = g_string_new("/affiliation "); + g_string_append(beginning, args[0]); + g_string_append(beginning, " "); + g_string_append(beginning, args[1]); + + result = autocomplete_param_with_ac(input, beginning->str, jid_ac, TRUE); + g_string_free(beginning, TRUE); + if (result) { + g_strfreev(args); + return result; + } + } + + g_strfreev(args); + } + + result = autocomplete_param_with_ac(input, "/affiliation set", affiliation_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/affiliation list", affiliation_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/affiliation", privilege_cmd_ac, TRUE); + if (result) { + return result; + } + + return result; +} + +static char* +_role_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + if (window->type == WIN_MUC) { + ProfMucWin *mucwin = (ProfMucWin*)window; + assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); + gboolean parse_result; + Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid); + + gchar **args = parse_args(input, 3, 3, &parse_result); + + if ((strncmp(input, "/role", 5) == 0) && (parse_result == TRUE)) { + GString *beginning = g_string_new("/role "); + g_string_append(beginning, args[0]); + g_string_append(beginning, " "); + g_string_append(beginning, args[1]); + + result = autocomplete_param_with_ac(input, beginning->str, nick_ac, TRUE); + g_string_free(beginning, TRUE); + if (result) { + g_strfreev(args); + return result; + } + } + + g_strfreev(args); + } + + result = autocomplete_param_with_ac(input, "/role set", role_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/role list", role_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/role", privilege_cmd_ac, TRUE); + if (result) { + return result; + } + + return result; +} + +static char* +_statuses_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + result = autocomplete_param_with_ac(input, "/statuses console", statuses_setting_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/statuses chat", statuses_setting_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/statuses muc", statuses_setting_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/statuses", statuses_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_wins_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + result = autocomplete_param_with_func(input, "/wins autotidy", prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/wins", wins_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_tls_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + result = autocomplete_param_with_func(input, "/tls revoke", tlscerts_complete); + if (result) { + return result; + } + + result = autocomplete_param_with_func(input, "/tls cert", tlscerts_complete); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/tls certpath", tls_certpath_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_func(input, "/tls show", prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/tls", tls_ac, TRUE); + if (result) { + return result; + } + + return result; +} + +static char* +_receipts_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + result = autocomplete_param_with_func(input, "/receipts send", prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + + result = autocomplete_param_with_func(input, "/receipts request", prefs_autocomplete_boolean_choice); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/receipts", receipts_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_alias_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + result = autocomplete_param_with_ac(input, "/alias remove", aliases_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/alias", alias_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_connect_autocomplete(ProfWin *window, const char *const input) +{ + char *found = NULL; + gboolean result = FALSE; + + gchar **args = parse_args(input, 2, 6, &result); + + if ((strncmp(input, "/connect", 8) == 0) && (result == TRUE)) { + GString *beginning = g_string_new("/connect "); + g_string_append(beginning, args[0]); + if (args[1] && args[2]) { + g_string_append(beginning, " "); + g_string_append(beginning, args[1]); + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + if (args[3] && args[4]) { + g_string_append(beginning, " "); + g_string_append(beginning, args[3]); + g_string_append(beginning, " "); + g_string_append(beginning, args[4]); + } + } + found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } + + g_strfreev(args); + + result = FALSE; + args = parse_args(input, 2, 7, &result); + + if ((strncmp(input, "/connect", 8) == 0) && (result == TRUE)) { + GString *beginning = g_string_new("/connect "); + g_string_append(beginning, args[0]); + int curr = 0; + if (args[1]) { + g_string_append(beginning, " "); + g_string_append(beginning, args[1]); + curr = 1; + if (args[2] && args[3]) { + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + g_string_append(beginning, " "); + g_string_append(beginning, args[3]); + curr = 3; + if (args[4] && args[5]) { + g_string_append(beginning, " "); + g_string_append(beginning, args[4]); + g_string_append(beginning, " "); + g_string_append(beginning, args[5]); + curr = 5; + } + } + } + if (curr != 0 && (g_strcmp0(args[curr], "tls") == 0)) { + found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } else { + g_string_free(beginning, TRUE); + } + } + + g_strfreev(args); + + found = autocomplete_param_with_func(input, "/connect", accounts_find_enabled); + if (found) { + return found; + } + + return NULL; +} + +static char* +_help_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + result = autocomplete_param_with_ac(input, "/help commands", help_commands_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/help", help_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_join_autocomplete(ProfWin *window, const char *const input) +{ + char *found = NULL; + gboolean result = FALSE; + + found = autocomplete_param_with_func(input, "/join", bookmark_find); + if (found) { + return found; + } + + gchar **args = parse_args(input, 2, 4, &result); + + if ((strncmp(input, "/join", 5) == 0) && (result == TRUE)) { + GString *beginning = g_string_new("/join "); + g_string_append(beginning, args[0]); + if (args[1] && args[2]) { + g_string_append(beginning, " "); + g_string_append(beginning, args[1]); + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + } + found = autocomplete_param_with_ac(input, beginning->str, join_property_ac, TRUE); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } + + g_strfreev(args); + + return NULL; +} + +static char* +_console_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + result = autocomplete_param_with_ac(input, "/console chat", console_msg_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/console muc", console_msg_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/console private", console_msg_ac, TRUE); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/console", console_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_win_autocomplete(ProfWin *window, const char *const input) +{ + char *found = NULL; + + found = autocomplete_param_with_func(input, "/win", win_autocomplete); + if (found) { + return found; + } + + return NULL; +} + +static char* +_close_autocomplete(ProfWin *window, const char *const input) +{ + char *found = NULL; + + found = autocomplete_param_with_func(input, "/close", win_close_autocomplete); + if (found) { + return found; + } + + return NULL; +} + +static char* +_sendfile_autocomplete(ProfWin *window, const char *const input) +{ + static char* last_directory = NULL; + + unsigned int output_off = 0; + + char *result = NULL; + char *tmp; + + // strip command + char *inpcp = (char*)input + 9; + while (*inpcp == ' ') { + inpcp++; + } + + inpcp = strdup(inpcp); + + // strip quotes + if (*inpcp == '"') { + tmp = strchr(inpcp+1, '"'); + if (tmp) { + *tmp = '\0'; + } + tmp = strdup(inpcp+1); + free(inpcp); + inpcp = tmp; + } + + // expand ~ to $HOME + if (inpcp[0] == '~' && inpcp[1] == '/') { + if (asprintf(&tmp, "%s/%sfoo", getenv("HOME"), inpcp+2) == -1) { + return NULL; + } + output_off = strlen(getenv("HOME"))+1; + } else { + if (asprintf(&tmp, "%sfoo", inpcp) == -1) { + return NULL; + } + } + free(inpcp); + inpcp = tmp; + + char* inpcp2 = strdup(inpcp); + char* foofile = strdup(basename(inpcp2)); + char* directory = strdup(dirname(inpcp)); + free(inpcp); + free(inpcp2); + + if (!last_directory || strcmp(last_directory, directory) != 0) { + free(last_directory); + last_directory = directory; + autocomplete_reset(sendfile_ac); + + struct dirent *dir; + + DIR *d = opendir(directory); + if (d) { + while ((dir = readdir(d)) != NULL) { + if (strcmp(dir->d_name, ".") == 0) { + continue; + } else if (strcmp(dir->d_name, "..") == 0) { + continue; + } else if (*(dir->d_name) == '.' && *foofile != '.') { + // only show hidden files on explicit request + continue; + } + char * acstring; + if (output_off) { + if (asprintf(&tmp, "%s/%s", directory, dir->d_name) == -1) { + return NULL; + } + if (asprintf(&acstring, "~/%s", tmp+output_off) == -1) { + return NULL; + } + free(tmp); + } else if (strcmp(directory, "/") == 0) { + if (asprintf(&acstring, "/%s", dir->d_name) == -1) { + return NULL; + } + } else { + if (asprintf(&acstring, "%s/%s", directory, dir->d_name) == -1) { + return NULL; + } + } + autocomplete_add(sendfile_ac, acstring); + free(acstring); + } + closedir(d); + } + } else { + free(foofile); + free(directory); + } + + result = autocomplete_param_with_ac(input, "/sendfile", sendfile_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + + +static char* +_subject_autocomplete(ProfWin *window, const char *const input) +{ + char *result = NULL; + + if (window->type == WIN_MUC) { + if ((g_strcmp0(input, "/subject e") == 0) + || (g_strcmp0(input, "/subject ed") == 0) + || (g_strcmp0(input, "/subject edi") == 0) + || (g_strcmp0(input, "/subject edit") == 0) + || (g_strcmp0(input, "/subject edit ") == 0) + || (g_strcmp0(input, "/subject edit \"") == 0)) { + ProfMucWin *mucwin = (ProfMucWin*)window; + assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); + + char *subject = muc_subject(mucwin->roomjid); + if (subject) { + GString *result_str = g_string_new("/subject edit \""); + g_string_append(result_str, subject); + g_string_append(result_str, "\""); + + result = result_str->str; + g_string_free(result_str, FALSE); + } + } + } + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/subject", subject_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + +static char* +_account_autocomplete(ProfWin *window, const char *const input) +{ + char *found = NULL; + gboolean result = FALSE; + + gchar **args = parse_args(input, 3, 4, &result); + + if ((strncmp(input, "/account set", 12) == 0) && (result == TRUE)) { + GString *beginning = g_string_new("/account set "); + g_string_append(beginning, args[1]); + if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "otr")) == 0) { + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + found = autocomplete_param_with_ac(input, beginning->str, otr_policy_ac, TRUE); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } else if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "status")) == 0) { + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + found = autocomplete_param_with_ac(input, beginning->str, account_status_ac, TRUE); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } else if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "tls")) == 0) { + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } else if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "startscript")) == 0) { + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + found = autocomplete_param_with_func(input, beginning->str, _script_autocomplete_func); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } else if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "theme")) == 0) { + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + if (theme_load_ac == NULL) { + theme_load_ac = autocomplete_new(); + GSList *themes = theme_list(); + GSList *curr = themes; + while (curr) { + autocomplete_add(theme_load_ac, curr->data); + curr = g_slist_next(curr); + } + g_slist_free_full(themes, g_free); + autocomplete_add(theme_load_ac, "default"); + } + found = autocomplete_param_with_ac(input, beginning->str, theme_load_ac, TRUE); + g_string_free(beginning, TRUE); + if (found) { + return found; + } +#ifdef HAVE_LIBGPGME + } else if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "pgpkeyid")) == 0) { + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } +#endif + } else { + found = autocomplete_param_with_ac(input, beginning->str, account_set_ac, TRUE); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } + } + + if ((strncmp(input, "/account clear", 14) == 0) && (result == TRUE)) { + GString *beginning = g_string_new("/account clear "); + g_string_append(beginning, args[1]); + found = autocomplete_param_with_ac(input, beginning->str, account_clear_ac, TRUE); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } + + g_strfreev(args); + + found = autocomplete_param_with_ac(input, "/account default", account_default_ac, TRUE); + if(found){ + return found; + } + + int i = 0; + gchar *account_choice[] = { "/account set", "/account show", "/account enable", + "/account disable", "/account rename", "/account clear", "/account remove", + "/account default set" }; + + for (i = 0; i < ARRAY_SIZE(account_choice); i++) { + found = autocomplete_param_with_func(input, account_choice[i], accounts_find_all); + if (found) { + return found; + } + } + + found = autocomplete_param_with_ac(input, "/account", account_ac, TRUE); + return found; +} diff --git a/src/command/cmd_ac.h b/src/command/cmd_ac.h new file mode 100644 index 00000000..b294fcd5 --- /dev/null +++ b/src/command/cmd_ac.h @@ -0,0 +1,62 @@ +/* + * cmd_ac.h + * + * Copyright (C) 2012 - 2016 James Booth <boothj5@gmail.com> + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see <http://www.gnu.org/licenses/>. + * + * In addition, as a special exception, the copyright holders give permission to + * link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. + * + * You must obey the GNU General Public License in all respects for all of the + * code used other than OpenSSL. If you modify file(s) with this exception, you + * may extend this exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. If you delete this exception statement from all + * source files in the program, then also delete it here. + * + */ + +#ifndef CMD_AC_H +#define CMD_AC_H + +#include "config/preferences.h" +#include "command/cmd_funcs.h" + +void cmd_ac_init(void); +void cmd_ac_uninit(void); + +void cmd_ac_add(const char *const value); +void cmd_ac_add_help(const char *const value); +void cmd_ac_add_cmd(Command *command); +void cmd_ac_add_alias(ProfAlias *alias); +void cmd_ac_add_alias_value(char *value); + +void cmd_ac_remove(const char *const value); +void cmd_ac_remove_alias_value(char *value); + +gboolean cmd_ac_exists(char *cmd); + +void cmd_ac_add_form_fields(DataForm *form); +void cmd_ac_remove_form_fields(DataForm *form); + +char* cmd_ac_complete(ProfWin *window, const char *const input); + +void cmd_ac_reset(ProfWin *window); + +#endif diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c new file mode 100644 index 00000000..9669f4b6 --- /dev/null +++ b/src/command/cmd_defs.c @@ -0,0 +1,2367 @@ +/* + * cmd_defs.c + * + * Copyright (C) 2012 - 2016 James Booth <boothj5@gmail.com> + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see <http://www.gnu.org/licenses/>. + * + * In addition, as a special exception, the copyright holders give permission to + * link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. + * + * You must obey the GNU General Public License in all respects for all of the + * code used other than OpenSSL. If you modify file(s) with this exception, you + * may extend this exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. If you delete this exception statement from all + * source files in the program, then also delete it here. + * + */ + +#define _GNU_SOURCE 1 + +#include "config.h" + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <libgen.h> +#include <dirent.h> +#include <sys/types.h> + +#include <glib.h> + +#include "chat_session.h" +#include "command/cmd_defs.h" +#include "command/cmd_funcs.h" +#include "command/cmd_ac.h" +#include "common.h" +#include "config/accounts.h" +#include "config/preferences.h" +#include "config/theme.h" +#include "config/tlscerts.h" +#include "config/scripts.h" +#include "contact.h" +#include "roster_list.h" +#include "jid.h" +#include "log.h" +#include "muc.h" +#include "plugins/plugins.h" +#include "profanity.h" +#include "tools/autocomplete.h" +#include "tools/parser.h" +#include "tools/tinyurl.h" +#include "xmpp/xmpp.h" +#include "ui/ui.h" +#include "window_list.h" + +#ifdef HAVE_LIBOTR +#include "otr/otr.h" +#endif + +#ifdef HAVE_LIBGPGME +#include "pgp/gpg.h" +#endif + +#define CMD_TAG_CHAT "chat" +#define CMD_TAG_GROUPCHAT "groupchat" +#define CMD_TAG_ROSTER "roster" +#define CMD_TAG_PRESENCE "presence" +#define CMD_TAG_CONNECTION "connection" +#define CMD_TAG_DISCOVERY "discovery" +#define CMD_TAG_UI "ui" +#define CMD_TAG_PLUGINS "plugins" + +#define CMD_MAINFUNC(func) func, +#define CMD_NOMAINFUNC NULL, +#define CMD_SUBFUNCS(...) { __VA_ARGS__, { NULL, NULL } }, +#define CMD_NOSUBFUNCS { { NULL, NULL } }, + +#define CMD_NOTAGS { { NULL }, +#define CMD_TAGS(...) { { __VA_ARGS__, NULL }, +#define CMD_SYN(...) { __VA_ARGS__, NULL }, +#define CMD_DESC(desc) desc, +#define CMD_NOARGS { { NULL, NULL } }, +#define CMD_ARGS(...) { __VA_ARGS__, { NULL, NULL } }, +#define CMD_NOEXAMPLES { NULL } } +#define CMD_EXAMPLES(...) { __VA_ARGS__, NULL } } + +GHashTable *commands = NULL; + +static gboolean _cmd_has_tag(Command *pcmd, const char *const tag); + +/* + * Command list + */ +static struct cmd_t command_defs[] = +{ + { "/help", + parse_args, 0, 2, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_help) + CMD_NOTAGS + CMD_SYN( + "/help [<area>|<command>]") + CMD_DESC( + "Help on using Profanity. Passing no arguments list help areas. " + "For command help, optional arguments are shown using square brackets e.g. [argument], " + "arguments representing variables rather than a literal name are surrounded by angle brackets " + "e.g. <argument>. " + "Arguments that may be one of a number of values are separated by a pipe " + "e.g. val1|val2|val3.") + CMD_ARGS( + { "<area>", "Summary help for commands in a certain area of functionality." }, + { "<command>", "Full help for a specific command, for example '/help connect'." }) + CMD_EXAMPLES( + "/help commands", + "/help presence", + "/help who") + }, + + { "/about", + parse_args, 0, 0, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_about) + CMD_NOTAGS + CMD_SYN( + "/about") + CMD_DESC( + "Show version and license information.") + CMD_NOARGS + CMD_NOEXAMPLES + }, + + { "/connect", + parse_args, 0, 7, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_connect) + CMD_TAGS( + CMD_TAG_CONNECTION) + CMD_SYN( + "/connect [<account>]", + "/connect <account> [server <server>] [port <port>] [tls force|allow|disable]") + CMD_DESC( + "Login to a chat service. " + "If no account is specified, the default is used if one is configured. " + "A local account is created with the JID as it's name if it doesn't already exist.") + CMD_ARGS( + { "<account>", "The local account you wish to connect with, or a JID if connecting for the first time." }, + { "server <server>", "Supply a server if it is different to the domain part of your JID." }, + { "port <port>", "The port to use if different to the default (5222, or 5223 for SSL)." }, + { "tls force", "Force TLS connection, and fail if one cannot be established, this is default behaviour." }, + { "tls allow", "Use TLS for the connection if it is available." }, + { "tls disable", "Disable TLS for the connection." }) + CMD_EXAMPLES( + "/connect", + "/connect myuser@gmail.com", + "/connect myuser@mycompany.com server talk.google.com", + "/connect bob@someplace port 5678", + "/connect me@localhost.test.org server 127.0.0.1 tls disable", + "/connect me@chatty server chatty.com port 5443") + }, + + { "/tls", + parse_args, 1, 3, NULL, + CMD_SUBFUNCS( + { "certpath", cmd_tls_certpath }, + { "trust", cmd_tls_trust }, + { "trusted", cmd_tls_trusted }, + { "revoke", cmd_tls_revoke }, + { "show", cmd_tls_show }, + { "cert", cmd_tls_cert }) + CMD_NOMAINFUNC + CMD_TAGS( + CMD_TAG_CONNECTION, + CMD_TAG_UI) + CMD_SYN( + "/tls allow", + "/tls always", + "/tls deny", + "/tls cert [<fingerprint>]", + "/tls trust", + "/tls trusted", + "/tls revoke <fingerprint>", + "/tls certpath", + "/tls certpath set <path>", + "/tls certpath clear", + "/tls show on|off") + CMD_DESC( + "Handle TLS certificates. ") + CMD_ARGS( + { "allow", "Allow connection to continue with TLS certificate." }, + { "always", "Always allow connections with TLS certificate." }, + { "deny", "Abort connection." }, + { "cert", "Show the current TLS certificate." }, + { "cert <fingerprint>", "Show details of trusted certificate." }, + { "trust", "Add the current TLS certificate to manually trusted certificates." }, + { "trusted", "List summary of manually trusted certificates (with '/tls always' or '/tls trust')." }, + { "revoke <fingerprint>", "Remove a manually trusted certificate." }, + { "certpath", "Show the trusted certificate path." }, + { "certpath set <path>", "Specify filesystem path containing trusted certificates." }, + { "certpath clear", "Clear the trusted certificate path." }, + { "show on|off", "Show or hide the TLS indicator in the titlebar." }) + CMD_NOEXAMPLES + }, + + { "/disconnect", + parse_args, 0, 0, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_disconnect) + CMD_TAGS( + CMD_TAG_CONNECTION) + CMD_SYN( + "/disconnect") + CMD_DESC( + "Disconnect from the current chat service.") + CMD_NOARGS + CMD_NOEXAMPLES + }, + + { "/msg", + parse_args_with_freetext, 1, 2, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_msg) + CMD_TAGS( + CMD_TAG_CHAT) + CMD_SYN( + "/msg <contact> [<message>]", + "/msg <nick> [<message>]") + CMD_DESC( + "Send a one to one chat message, or a private message to a chat room occupant. " + "If the message is omitted, a new chat window will be opened without sending a message. " + "Use quotes if the nickname includes spaces.") + CMD_ARGS( + { "<contact>", "Open chat window with contact, by JID or nickname." }, + { "<contact> [<message>]", "Send message to contact, by JID or nickname." }, + { "<nick>", "Open private chat window with chat room occupant." }, + { "<nick> [<message>]", "Send a private message to a chat room occupant." }) + CMD_EXAMPLES( + "/msg myfriend@server.com Hey, here's a message!", + "/msg otherfriend@server.com", + "/msg Bob Here is a private message", + "/msg \"My Friend\" Hi, how are you?") + }, + + { "/roster", + parse_args_with_freetext, 0, 4, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_roster) + CMD_TAGS( + CMD_TAG_ROSTER, + CMD_TAG_UI) + CMD_SYN( + "/roster", + "/roster online", + "/roster show [offline|resource|presence|status|empty|priority|contacts|rooms]", + "/roster hide [offline|resource|presence|status|empty|priority|contacts|rooms]", + "/roster by group|presence|none", + "/roster count unread|items|off", + "/roster count zero on|off", + "/roster order name|presence", + "/roster unread before|after|off", + "/roster room char <char>|none", + "/roster room private char <char>|none", + "/roster room position first|last", + "/roster room by service|none", + "/roster room order name|unread", + "/roster room unread before|after|off", + "/roster private room|group|off", + "/roster private char <char>|none", + "/roster header char <char>|none", + "/roster presence indent <indent>", + "/roster contact char <char>|none", + "/roster contact indent <indent>", + "/roster resource char <char>|none", + "/roster resource indent <indent>", + "/roster resource join on|off", + "/roster size <percent>", + "/roster wrap on|off", + "/roster add <jid> [<nick>]", + "/roster remove <jid>", + "/roster remove_all contacts", + "/roster nick <jid> <nick>", + "/roster clearnick <jid>") + CMD_DESC( + "Manage your roster, and roster display settings. " + "Passing no arguments lists all contacts in your roster.") + CMD_ARGS( + { "online", "Show all online contacts in console." }, + { "show", "Show the roster panel." }, + { "show offline", "Show offline contacts in roster panel." }, + { "show resource", "Show contact's connected resources in roster panel." }, + { "show presence", "Show contact's presence in roster panel." }, + { "show status", "Show contact's status message in roster panel." }, + { "show empty", "Show empty groups in roster panel." }, + { "show priority", "Show resource priority in roster panel." }, + { "show contacts", "Show contacts in roster panel." }, + { "show rooms", "Show chat rooms in roster panel." }, + { "hide", "Hide the roster panel." }, + { "hide offline", "Hide offline contacts in roster panel." }, + { "hide resource", "Hide contact's connected resources in roster panel." }, + { "hide presence", "Hide contact's presence in roster panel." }, + { "hide status", "Hide contact's status message in roster panel." }, + { "hide empty", "Hide empty groups in roster panel." }, + { "hide priority", "Hide resource priority in roster panel." }, + { "hide contacts", "Hide contacts in roster panel." }, + { "hide rooms", "Hide chat rooms in roster panel." }, + { "by group", "Group contacts in roster panel by roster group." }, + { "by presence", "Group contacts in roster panel by presence." }, + { "by none", "No grouping in roster panel." }, + { "count unread", "Show unread message count with roster headers." }, + { "count items", "Show item count with roster headers." }, + { "count off", "Do not show any count with roster headers." }, + { "count zero on", "Show roster header count when 0." }, + { "count zero off", "Hide roster header count when 0." }, + { "order name", "Order roster contacts by name only." }, + { "order presence", "Order roster contacts by presence, and then by name." }, + { "unread before", "Show unread message count before contact." }, + { "unread after", "Show unread message count after contact." }, + { "unread off", "Do not show unread message count for contacts." }, + { "room char <char>", "Prefix rooms with specified character." }, + { "room char none", "Remove room character prefix." }, + { "room private char <char>", "Prefix private room chat with specified character when displayed with room." }, + { "room private char none", "Remove private room chat character prefix when displayed with room." }, + { "room position first", "Show rooms first in roster." }, + { "room position last", "Show rooms last in roster." }, + { "room by service", "Group rooms by chat service." }, + { "room by none", "Do not group rooms." }, + { "room order name", "Order rooms by name." }, + { "room order unread", "Order rooms by unread messages, and then by name." }, + { "room unread before", "Show unread message count before room." }, + { "room unread after", "Show unread message count after room." }, + { "room unread off", "Do not show unread message count for rooms." }, + { "private room", "Show room private chats with the room." }, + { "private group", "Show room private chats as a separate roster group." }, + { "private off", "Do not show room private chats." }, + { "private char <char>", "Prefix private room chats with specified character when displayed in separate group." }, + { "private char none", "Remove private room chat character prefix." }, + { "header char <char>", "Prefix roster headers with specified character." }, + { "header char none", "Remove roster header character prefix." }, + { "contact char <char>", "Prefix roster contacts with specified character." }, + { "contact char none", "Remove roster contact character prefix." }, + { "contact indent <indent>", "Indent contact line by <indent> spaces (0 to 10)." }, + { "resource char <char>", "Prefix roster resources with specified character." }, + { "resource char none", "Remove roster resource character prefix." }, + { "resource indent <indent>", "Indent resource line by <indent> spaces (0 to 10)." }, + { "resource join on|off", "Join resource with previous line when only one available resource." }, + { "presence indent <indent>", "Indent presence line by <indent> spaces (-1 to 10), a value of -1 will show presence on the previous line." }, + { "size <precent>", "Percentage of the screen taken up by the roster (1-99)." }, + { "wrap on|off", "Enable or disable line wrapping in roster panel." }, + { "add <jid> [<nick>]", "Add a new item to the roster." }, + { "remove <jid>", "Removes an item from the roster." }, + { "remove_all contacts", "Remove all items from roster." }, + { "nick <jid> <nick>", "Change a contacts nickname." }, + { "clearnick <jid>", "Removes the current nickname." }) + CMD_EXAMPLES( + "/roster", + "/roster add someone@contacts.org", + "/roster add someone@contacts.org Buddy", + "/roster remove someone@contacts.org", + "/roster nick myfriend@chat.org My Friend", + "/roster clearnick kai@server.com", + "/roster size 15") + }, + + { "/blocked", + parse_args, 0, 2, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_blocked) + CMD_TAGS( + CMD_TAG_ROSTER, + CMD_TAG_CHAT) + CMD_SYN( + "/blocked", + "/blocked add [<jid>]", + "/blocked remove <jid>") + CMD_DESC( + "Manage blocked users, calling with no arguments shows the current list of blocked users.") + CMD_ARGS( + { "add [<jid>]", "Block the specified Jabber ID, if in a chat window, and not jid specified, the current recipient will be blocked." }, + { "remove <jid>", "Remove the specified Jabber ID from the blocked list." }) + CMD_EXAMPLES( + "/blocked add spammer@spam.org") + }, + + { "/group", + parse_args_with_freetext, 0, 3, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_group) + CMD_TAGS( + CMD_TAG_ROSTER, + CMD_TAG_UI) + CMD_SYN( + "/group", + "/group show <group>", + "/group add <group> <contat>", + "/group remove <group> <contact>") + CMD_DESC( + "View, add to, and remove from roster groups. " + "Passing no argument will list all roster groups.") + CMD_ARGS( + { "show <group>", "List all roster items a group." }, + { "add <group> <contact>", "Add a contact to a group." }, + { "remove <group> <contact>", "Remove a contact from a group." }) + CMD_EXAMPLES( + "/group", + "/group show friends", + "/group add friends newfriend@server.org", + "/group add family Brother", + "/group remove colleagues boss@work.com") + }, + + { "/info", + parse_args, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_info) + CMD_TAGS( + CMD_TAG_ROSTER, + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/info", + "/info <contact>|<nick>") + CMD_DESC( + "Show information about a contact, room, or room member. " + "Passing no argument in a chat window will use the current recipient. " + "Passing no argument in a chat room will display information about the room.") + CMD_ARGS( + { "<contact>", "The contact you wish to view information about." }, + { "<nick>", "When in a chat room, the occupant you wish to view information about." }) + CMD_EXAMPLES( + "/info mybuddy@chat.server.org", + "/info kai") + }, + + { "/caps", + parse_args, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_caps) + CMD_TAGS( + CMD_TAG_DISCOVERY, + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/caps", + "/caps <fulljid>|<nick>") + CMD_DESC( + "Find out a contacts, or room members client software capabilities. " + "If in private chat initiated from a chat room, no parameter is required.") + CMD_ARGS( + { "<fulljid>", "If in the console or a chat window, the full JID for which you wish to see capabilities." }, + { "<nick>", "If in a chat room, nickname for which you wish to see capabilities." }) + CMD_EXAMPLES( + "/caps mybuddy@chat.server.org/laptop", + "/caps mybuddy@chat.server.org/phone", + "/caps bruce") + }, + + { "/software", + parse_args, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_software) + CMD_TAGS( + CMD_TAG_DISCOVERY, + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/software", + "/software <fulljid>|<nick>") + CMD_DESC( + "Find out a contact, or room members software version information. " + "If in private chat initiated from a chat room, no parameter is required. " + "If the contact's software does not support software version requests, nothing will be displayed.") + CMD_ARGS( + { "<fulljid>", "If in the console or a chat window, the full JID for which you wish to see software information." }, + { "<nick>", "If in a chat room, nickname for which you wish to see software information." }) + CMD_EXAMPLES( + "/software mybuddy@chat.server.org/laptop", + "/software mybuddy@chat.server.org/phone", + "/software bruce") + }, + + { "/status", + parse_args, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_status) + CMD_TAGS( + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/status", + "/status <contact>|<nick>") + CMD_DESC( + "Find out a contact, or room members presence information. " + "If in a chat window the parameter is not required, the current recipient will be used.") + CMD_ARGS( + { "<contact>", "The contact who's presence you which to see." }, + { "<nick>", "If in a chat room, the occupant who's presence you wish to see." }) + CMD_EXAMPLES( + "/status buddy@server.com", + "/status jon") + }, + + { "/resource", + parse_args, 1, 2, &cons_resource_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_resource) + CMD_TAGS( + CMD_TAG_CHAT, + CMD_TAG_UI) + CMD_SYN( + "/resource set <resource>", + "/resource off", + "/resource title on|off", + "/resource message on|off") + CMD_DESC( + "Override chat session resource, and manage resource display settings.") + CMD_ARGS( + { "set <resource>", "Set the resource to which messages will be sent." }, + { "off", "Let the server choose which resource to route messages to." }, + { "title on|off", "Show or hide the current resource in the titlebar." }, + { "message on|off", "Show or hide the resource when showing an incoming message." }) + CMD_NOEXAMPLES + }, + + { "/join", + parse_args, 0, 5, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_join) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/join", + "/join <room> [nick <nick>] [password <password>]") + CMD_DESC( + "Join a chat room at the conference server. " + "If no room is supplied, a generated name will be used with the format private-chat-[UUID]. " + "If the domain part is not included in the room name, the account preference 'muc.service' will be used. " + "If no nickname is specified the account preference 'muc.nick' will be used which by default is the localpart of your JID. " + "If the room doesn't exist, and the server allows it, a new one will be created.") + CMD_ARGS( + { "<room>", "The chat room to join." }, + { "nick <nick>", "Nickname to use in the room." }, + { "password <password>", "Password if the room requires one." }) + CMD_EXAMPLES( + "/join", + "/join jdev@conference.jabber.org", + "/join jdev@conference.jabber.org nick mynick", + "/join private@conference.jabber.org nick mynick password mypassword", + "/join jdev") + }, + + { "/leave", + parse_args, 0, 0, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_leave) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/leave") + CMD_DESC( + "Leave the current chat room.") + CMD_NOARGS + CMD_NOEXAMPLES + }, + + { "/invite", + parse_args_with_freetext, 1, 2, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_invite) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/invite <contact> [<message>]") + CMD_DESC( + "Send an invite to a contact for the current chat room.") + CMD_ARGS( + { "<contact>", "The contact you wish to invite." }, + { "<message>", "An optional message to send with the invite." }) + CMD_NOEXAMPLES + }, + + { "/invites", + parse_args_with_freetext, 0, 0, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_invites) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/invites") + CMD_DESC( + "Show all rooms that you have been invited to, and not accepted or declined.") + CMD_NOARGS + CMD_NOEXAMPLES + }, + + { "/decline", + parse_args_with_freetext, 1, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_decline) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/decline <room>") + CMD_DESC( + "Decline a chat room invitation.") + CMD_ARGS( + { "<room>", "The room for the invite you wish to decline." }) + CMD_NOEXAMPLES + }, + + { "/room", + parse_args, 1, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_room) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/room accept|destroy|config") + CMD_DESC( + "Chat room configuration.") + CMD_ARGS( + { "accept", "Accept default room configuration." }, + { "destroy", "Reject default room configuration, and destroy the room." }, + { "config", "Edit room configuration." }) + CMD_NOEXAMPLES + }, + + { "/kick", + parse_args_with_freetext, 1, 2, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_kick) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/kick <nick> [<reason>]") + CMD_DESC( + "Kick occupant from chat room.") + CMD_ARGS( + { "<nick>", "Nickname of the occupant to kick from the room." }, + { "<reason>", "Optional reason for kicking the occupant." }) + CMD_NOEXAMPLES + }, + + { "/ban", + parse_args_with_freetext, 1, 2, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_ban) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/ban <jid> [<reason>]") + CMD_DESC( + "Ban user from chat room.") + CMD_ARGS( + { "<jid>", "Bare JID of the user to ban from the room." }, + { "<reason>", "Optional reason for banning the user." }) + CMD_NOEXAMPLES + }, + + { "/subject", + parse_args_with_freetext, 0, 2, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_subject) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/subject set <subject>", + "/subject edit <subject>", + "/subject prepend <text>", + "/subject append <text>", + "/subject clear") + CMD_DESC( + "Set, modify, or clear room subject.") + CMD_ARGS( + { "set <subject>", "Set the room subject." }, + { "edit <subject>", "Edit the current room subject, tab autocompletion will display the subject to edit." }, + { "prepend <text>", "Prepend text to the current room subject, use double quotes if a trailing space is needed." }, + { "append <text>", "Append text to the current room subject, use double quotes if a preceding space is needed." }, + { "clear", "Clear the room subject." }) + CMD_NOEXAMPLES + }, + + { "/affiliation", + parse_args_with_freetext, 1, 4, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_affiliation) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/affiliation set <affiliation> <jid> [<reason>]", + "/affiliation list [<affiliation>]") + CMD_DESC( + "Manage room affiliations. " + "Affiliation may be one of owner, admin, member, outcast or none.") + CMD_ARGS( + { "set <affiliation> <jid> [<reason>]", "Set the affiliation of user with jid, with an optional reason." }, + { "list [<affiliation>]", "List all users with the specified affiliation, or all if none specified." }) + CMD_NOEXAMPLES + }, + + { "/role", + parse_args_with_freetext, 1, 4, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_role) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/role set <role> <nick> [<reason>]", + "/role list [<role>]") + CMD_DESC( + "Manage room roles. " + "Role may be one of moderator, participant, visitor or none.") + CMD_ARGS( + { "set <role> <nick> [<reason>]", "Set the role of occupant with nick, with an optional reason." }, + { "list [<role>]", "List all occupants with the specified role, or all if none specified." }) + CMD_NOEXAMPLES + }, + + { "/occupants", + parse_args, 1, 3, cons_occupants_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_occupants) + CMD_TAGS( + CMD_TAG_GROUPCHAT, + CMD_TAG_UI) + CMD_SYN( + "/occupants show|hide [jid]", + "/occupants default show|hide [jid]", + "/occupants size [<percent>]") + CMD_DESC( + "Show or hide room occupants, and occupants panel display settings.") + CMD_ARGS( + { "show", "Show the occupants panel in current room." }, + { "hide", "Hide the occupants panel in current room." }, + { "show jid", "Show jid in the occupants panel in current room." }, + { "hide jid", "Hide jid in the occupants panel in current room." }, + { "default show|hide", "Whether occupants are shown by default in new rooms." }, + { "default show|hide jid", "Whether occupants jids are shown by default in new rooms." }, + { "size <percent>", "Percentage of the screen taken by the occupants list in rooms (1-99)." }) + CMD_NOEXAMPLES + }, + + { "/form", + parse_args, 1, 2, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_form) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/form show", + "/form submit", + "/form cancel", + "/form help [<tag>]") + CMD_DESC( + "Form configuration.") + CMD_ARGS( + { "show", "Show the current form." }, + { "submit", "Submit the current form." }, + { "cancel", "Cancel changes to the current form." }, + { "help [<tag>]", "Display help for form, or a specific field." }) + CMD_NOEXAMPLES + }, + + { "/rooms", + parse_args, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_rooms) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/rooms [<service>]") + CMD_DESC( + "List the chat rooms available at the specified conference service. " + "If no argument is supplied, the account preference 'muc.service' is used, 'conference.<domain-part>' by default.") + CMD_ARGS( + { "<service>", "The conference service to query." }) + CMD_EXAMPLES( + "/rooms conference.jabber.org") + }, + + { "/bookmark", + parse_args, 0, 8, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_bookmark) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/bookmark", + "/bookmark list", + "/bookmark add <room> [nick <nick>] [password <password>] [autojoin on|off]", + "/bookmark update <room> [nick <nick>] [password <password>] [autojoin on|off]", + "/bookmark remove <room>", + "/bookmark join <room>") + CMD_DESC( + "Manage bookmarks and join bookmarked rooms. " + "In a chat room, no arguments will bookmark the current room, setting autojoin to \"on\".") + CMD_ARGS( + { "list", "List all bookmarks." }, + { "add <room>", "Add a bookmark." }, + { "remove <room>", "Remove a bookmark." }, + { "update <room>", "Update the properties associated with a bookmark." }, + { "nick <nick>", "Nickname used in the chat room." }, + { "password <password>", "Password if required, may be stored in plaintext on your server." }, + { "autojoin on|off", "Whether to join the room automatically on login." }, + { "join <room>", "Join room using the properties associated with the bookmark." }) + CMD_NOEXAMPLES + }, + + { "/disco", + parse_args, 1, 2, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_disco) + CMD_TAGS( + CMD_TAG_DISCOVERY) + CMD_SYN( + "/disco info [<jid>]", + "/disco items [<jid>]") + CMD_DESC( + "Find out information about an entities supported services. " + "Calling with no arguments will query the server you are currently connected to.") + CMD_ARGS( + { "info [<jid>]", "List protocols and features supported by an entity." }, + { "items [<jid>]", "List items associated with an entity." }) + CMD_EXAMPLES( + "/disco info", + "/disco items myserver.org", + "/disco items conference.jabber.org", + "/disco info myfriend@server.com/laptop") + }, + + { "/sendfile", + parse_args_with_freetext, 1, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_sendfile) + CMD_TAGS( + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/sendfile <file>") + CMD_DESC( + "Send a file using XEP-0363 HTTP file transfer.") + CMD_ARGS( + { "<file>", "Path to the file." }) + CMD_EXAMPLES( + "/sendfile /etc/hosts", + "/sendfile ~/images/sweet_cat.jpg") + }, + + { "/lastactivity", + parse_args, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_lastactivity) + CMD_TAGS( + CMD_TAG_PRESENCE) + CMD_SYN( + "/lastactivity on|off", + "/lastactivity [<jid>]") + CMD_DESC( + "Enable/disable sending last activity, and send last activity requests.") + CMD_ARGS( + { "on|off", "Enable or disable sending of last activity." }, + { "<jid>", "The JID of the entity to query, omitting the JID will query your server." }) + CMD_EXAMPLES( + "/lastactivity", + "/lastactivity off", + "/lastactivity alice@securechat.org", + "/lastactivity alice@securechat.org/laptop", + "/lastactivity someserver.com") + }, + + { "/nick", + parse_args_with_freetext, 1, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_nick) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/nick <nickname>") + CMD_DESC( + "Change your nickname in the current chat room.") + CMD_ARGS( + { "<nickname>", "Your new nickname." }) + CMD_NOEXAMPLES + }, + + { "/win", + parse_args, 1, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_win) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/win console", + "/win <num>", + "/win <barejid>", + "/win <nick>", + "/win <roomjid>", + "/win <roomoccupantjid>", + "/win xmlconsole") + CMD_DESC( + "Move to the specified window.") + CMD_ARGS( + { "console", "Go to the Console window." }, + { "<num>", "Go to specified window number." }, + { "<barejid>", "Go to chat window with contact by JID if open." }, + { "<nick>", "Go to chat window with contact by nickname if open." }, + { "<roomjid>", "Go to chat room window with roomjid if open." }, + { "<roomoccupantjid>", "Go to private chat roomoccupantjid if open." }, + { "xmlconsole", "Go to the XML Console window if open." }) + CMD_EXAMPLES( + "/win console", + "/win 4", + "/win friend@chat.org", + "/win Eddie", + "/win bigroom@conference.chat.org", + "/win bigroom@conference.chat.org/bruce") + }, + + { "/wins", + parse_args, 0, 3, NULL, + CMD_SUBFUNCS( + { "unread", cmd_wins_unread }, + { "tidy", cmd_wins_tidy }, + { "prune", cmd_wins_prune }, + { "swap", cmd_wins_swap }, + { "autotidy", cmd_wins_autotidy }) + CMD_MAINFUNC(cmd_wins) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/wins", + "/wins unread", + "/wins tidy", + "/wins autotidy on|off", + "/wins prune", + "/wins swap <source> <target>") + CMD_DESC( + "Manage windows. " + "Passing no argument will list all currently active windows and information about their usage.") + CMD_ARGS( + { "unread", "List windows with unread messages." }, + { "tidy", "Move windows so there are no gaps." }, + { "autotidy on|off", "Automatically remove gaps when closing windows." }, + { "prune", "Close all windows with no unread messages, and then tidy so there are no gaps." }, + { "swap <source> <target>", "Swap windows, target may be an empty position." }) + CMD_NOEXAMPLES + }, + + { "/sub", + parse_args, 1, 2, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_sub) + CMD_TAGS( + CMD_TAG_ROSTER) + CMD_SYN( + "/sub request [<jid>]", + "/sub allow [<jid>]", + "/sub deny [<jid>]", + "/sub show [<jid>]", + "/sub sent", + "/sub received") + CMD_DESC( + "Manage subscriptions to contact presence. " + "If jid is omitted, the contact of the current window is used.") + CMD_ARGS( + { "request [<jid>]", "Send a subscription request to the user." }, + { "allow [<jid>]", "Approve a contact's subscription request." }, + { "deny [<jid>]", "Remove subscription for a contact, or deny a request." }, + { "show [<jid>]", "Show subscription status for a contact." }, + { "sent", "Show all sent subscription requests pending a response." }, + { "received", "Show all received subscription requests awaiting your response." }) + CMD_EXAMPLES( + "/sub request myfriend@jabber.org", + "/sub allow myfriend@jabber.org", + "/sub request", + "/sub sent") + }, + + { "/tiny", + parse_args, 1, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_tiny) + CMD_TAGS( + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/tiny <url>") + CMD_DESC( + "Send url as tinyurl in current chat.") + CMD_ARGS( + { "<url>", "The url to make tiny." }) + CMD_EXAMPLES( + "Example: /tiny http://www.profanity.im") + }, + + { "/who", + parse_args, 0, 2, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_who) + CMD_TAGS( + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT, + CMD_TAG_ROSTER) + CMD_SYN( + "/who", + "/who online|offline|away|dnd|xa|chat|available|unavailable|any [<group>]", + "/who moderator|participant|visitor", + "/who owner|admin|member") + CMD_DESC( + "Show contacts or room occupants with chosen status, role or affiliation") + CMD_ARGS( + { "offline|away|dnd|xa|chat", "Show contacts or room occupants with specified presence." }, + { "online", "Contacts that are online, chat, away, xa, dnd." }, + { "available", "Contacts that are available for chat - online, chat." }, + { "unavailable", "Contacts that are not available for chat - offline, away, xa, dnd." }, + { "any", "Contacts with any status (same as calling with no argument)." }, + { "<group>", "Filter the results by the specified roster group, not applicable in chat rooms." }, + { "moderator|participant|visitor", "Room occupants with the specified role." }, + { "owner|admin|member", "Room occupants with the specified affiliation." }) + CMD_EXAMPLES( + "/who", + "/who xa", + "/who online friends", + "/who any family", + "/who participant", + "/who admin") + }, + + { "/close", + parse_args, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_close) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/close", + "/close <num>", + "/close <barejid>", + "/close <nick>", + "/close <roomjid>", + "/close <roomoccupantjid>", + "/close xmlconsole", + "/close all|read") + CMD_DESC( + "Close windows. " + "Passing no argument closes the current window.") + CMD_ARGS( + { "<num>", "Close specified window number." }, + { "<barejid>", "Close chat window with contact by JID if open." }, + { "<nick>", "Close chat window with contact by nickname if open." }, + { "<roomjid>", "Close chat room window with roomjid if open." }, + { "<roomoccupantjid>", "Close private chat roomoccupantjid if open." }, + { "xmlconsole", "Close the XML Console window if open." }, + { "all", "Close all windows." }, + { "read", "Close all windows that have no unread messages." }) + CMD_NOEXAMPLES + }, + + { "/clear", + parse_args, 0, 0, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_clear) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/clear") + CMD_DESC( + "Clear the current window.") + CMD_NOARGS + CMD_NOEXAMPLES + }, + + { "/quit", + parse_args, 0, 0, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_quit) + CMD_NOTAGS + CMD_SYN( + "/quit") + CMD_DESC( + "Logout of any current session, and quit Profanity.") + CMD_NOARGS + CMD_NOEXAMPLES + }, + + { "/privileges", + parse_args, 1, 1, &cons_privileges_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_privileges) + CMD_TAGS( + CMD_TAG_GROUPCHAT, + CMD_TAG_UI) + CMD_SYN( + "/privileges on|off") + CMD_DESC( + "Group occupants panel by role, and show role information in chat rooms.") + CMD_ARGS( + { "on|off", "Enable or disable privilege information." }) + CMD_NOEXAMPLES + }, + + { "/charset", + parse_args, 0, 0, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_charset) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/charset") + CMD_DESC( + "Display information about the current character set supported by the terminal. ") + CMD_NOARGS + CMD_NOEXAMPLES + }, + + { "/beep", + parse_args, 1, 1, &cons_beep_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_beep) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/beep on|off") + CMD_DESC( + "Switch the terminal bell on or off. " + "The bell will sound when incoming messages are received. " + "If the terminal does not support sounds, it may attempt to flash the screen instead.") + CMD_ARGS( + { "on|off", "Enable or disable terminal bell." }) + CMD_NOEXAMPLES + }, + + { "/console", + parse_args, 2, 2, &cons_console_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_console) + CMD_TAGS( + CMD_TAG_UI, + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/console chat all|first|none", + "/console muc all|first|none", + "/console private all|first|none") + CMD_DESC( + "Configure what is displayed in the console window when messages are received. " + "The default is set to 'all' for all types of messages.") + CMD_ARGS( + { "chat all", "Indicate all new chat messages in the console." }, + { "chat first", "Indicate only the first new message per chat in the console." }, + { "chat none", "Do not show any new chat messages in the console window." }, + { "muc all", "Indicate all new chat room messages in the console." }, + { "muc first", "Indicate only the first new message in each room in the console." }, + { "muc none", "Do not show any new chat room messages in the console window." }, + { "private all", "Indicate all new private room messages in the console." }, + { "private first", "Indicate only the first private room message in the console." }, + { "private none", "Do not show any new private room messages in the console window." }) + CMD_NOEXAMPLES + }, + + { "/encwarn", + parse_args, 1, 1, &cons_encwarn_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_encwarn) + CMD_TAGS( + CMD_TAG_CHAT, + CMD_TAG_UI) + CMD_SYN( + "/encwarn on|off") + CMD_DESC( + "Titlebar encryption warning.") + CMD_ARGS( + { "on|off", "Enable or disable the unencrypted warning message in the titlebar." }) + CMD_NOEXAMPLES + }, + + { "/presence", + parse_args, 1, 1, &cons_presence_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_presence) + CMD_TAGS( + CMD_TAG_UI, + CMD_TAG_CHAT) + CMD_SYN( + "/presence on|off") + CMD_DESC( + "Show the contacts presence in the titlebar.") + CMD_ARGS( + { "on|off", "Switch display of the contacts presence in the titlebar on or off." }) + CMD_NOEXAMPLES + }, + + { "/wrap", + parse_args, 1, 1, &cons_wrap_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_wrap) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/wrap on|off") + CMD_DESC( + "Word wrapping.") + CMD_ARGS( + { "on|off", "Enable or disable word wrapping in the main window." }) + CMD_NOEXAMPLES + }, + + { "/time", + parse_args, 1, 3, &cons_time_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_time) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/time console|chat|muc|mucconfig|private|xml set <format>", + "/time console|chat|muc|mucconfig|private|xml off", + "/time statusbar set <format>", + "/time statusbar off", + "/time lastactivity set <format>") + CMD_DESC( + "Configure time display preferences. " + "Time formats are strings supported by g_date_time_format. " + "See https://developer.gnome.org/glib/stable/glib-GDateTime.html#g-date-time-format for more details. " + "Setting the format to an unsupported string, will display the string. " + "If the format contains spaces, it must be surrounded with double quotes.") + CMD_ARGS( + { "console set <format>", "Set time format for console window." }, + { "console off", "Do not show time in console window." }, + { "chat set <format>", "Set time format for chat windows." }, + { "chat off", "Do not show time in chat windows." }, + { "muc set <format>", "Set time format for chat room windows." }, + { "muc off", "Do not show time in chat room windows." }, + { "mucconfig set <format>", "Set time format for chat room config windows." }, + { "mucconfig off", "Do not show time in chat room config windows." }, + { "private set <format>", "Set time format for private chat windows." }, + { "private off", "Do not show time in private chat windows." }, + { "xml set <format>", "Set time format for XML console window." }, + { "xml off", "Do not show time in XML console window." }, + { "statusbar set <format>", "Change time format in statusbar." }, + { "statusbar off", "Do not show time in status bar." }, + { "lastactivity set <format>", "Change time format for last activity." }) + CMD_EXAMPLES( + "/time console set %H:%M:%S", + "/time chat set \"%d-%m-%y %H:%M:%S\"", + "/time xml off", + "/time statusbar set %H:%M", + "/time lastactivity set \"%d-%m-%y %H:%M:%S\"") + }, + + { "/inpblock", + parse_args, 2, 2, &cons_inpblock_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_inpblock) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/inpblock timeout <millis>", + "/inpblock dynamic on|off") + CMD_DESC( + "How long to wait for keyboard input before checking for new messages or checking for state changes such as 'idle'.") + CMD_ARGS( + { "timeout <millis>", "Time to wait (1-1000) in milliseconds before reading input from the terminal buffer, default: 1000." }, + { "dynamic on|off", "Start with 0 millis and dynamically increase up to timeout when no activity, default: on." }) + CMD_NOEXAMPLES + }, + + { "/notify", + parse_args_with_freetext, 0, 4, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_notify) + CMD_TAGS( + CMD_TAG_UI, + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/notify chat on|off", + "/notify chat current on|off", + "/notify chat text on|off", + "/notify room on|off", + "/notify room mention on|off", + "/notify room mention case_sensitive|case_insensitive", + "/notify room mention word_whole|word_part", + "/notify room current on|off", + "/notify room text on|off", + "/notify room trigger add <text>", + "/notify room trigger remove <text>", + "/notify room trigger list", + "/notify room trigger on|off", + "/notify on|off", + "/notify mention on|off", + "/notify trigger on|off", + "/notify reset", + "/notify remind <seconds>", + "/notify typing on|off", + "/notify typing current on|off", + "/notify invite on|off", + "/notify sub on|off") + CMD_DESC( + "Settings for various kinds of desktop notifications.") + CMD_ARGS( + { "chat on|off", "Notifications for regular chat messages." }, + { "chat current on|off", "Whether to show regular chat message notifications when the window is focussed." }, + { "chat text on|off", "Show message text in regular message notifications." }, + { "room on|off", "Notifications for all chat room messages, 'mention' only notifies when your nick is mentioned." }, + { "room mention on|off", "Notifications for all chat room messages when your nick is mentioned." }, + { "room mention case_sensitive", "Set room mention notifications as case sensitive." }, + { "room mention case_insensitive", "Set room mention notifications as case insensitive." }, + { "room mention word_whole", "Set room mention notifications only on whole word match, i.e. when nickname is not part of a larger word." }, + { "room mention word_part", "Set room mention notifications on partial word match, i.e. nickname may be part of a larger word." }, + { "room current on|off", "Whether to show all chat room messages notifications when the window is focussed." }, + { "room text on|off", "Show message text in chat room message notifications." }, + { "room trigger add <text>", "Notify when specified text included in all chat room messages." }, + { "room trigger remove <text>", "Remove chat room notification trigger." }, + { "room trigger list", "List all chat room triggers." }, + { "room trigger on|off", "Enable or disable all chat room notification triggers." }, + { "on|off", "Override the global message setting for the current chat room." }, + { "mention on|off", "Override the global 'mention' setting for the current chat room." }, + { "trigger on|off", "Override the global 'trigger' setting for the current chat room." }, + { "reset", "Reset to global notification settings for the current chat room." }, + { "remind <seconds>", "Notification reminder period for unread messages, use 0 to disable." }, + { "typing on|off", "Notifications when contacts are typing." }, + { "typing current on|off", "Whether typing notifications are triggered for the current window." }, + { "invite on|off", "Notifications for chat room invites." }, + { "sub on|off", "Notifications for subscription requests." }) + CMD_EXAMPLES( + "/notify chat on", + "/notify chat text on", + "/notify room mention on", + "/notify room trigger add beer", + "/notify room trigger on", + "/notify room current off", + "/notify room text off", + "/notify remind 60", + "/notify typing on", + "/notify invite on") + }, + + { "/flash", + parse_args, 1, 1, &cons_flash_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_flash) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/flash on|off") + CMD_DESC( + "Make the terminal flash when incoming messages are received in another window. " + "If the terminal doesn't support flashing, it may attempt to beep.") + CMD_ARGS( + { "on|off", "Enable or disable terminal flash." }) + CMD_NOEXAMPLES + }, + + { "/tray", + parse_args, 1, 2, &cons_tray_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_tray) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/tray on|off", + "/tray read on|off", + "/tray timer <seconds>") + CMD_DESC( + "Display an icon in the tray that will indicate new messages.") + CMD_ARGS( + { "on|off", "Show tray icon." }, + { "read on|off", "Show tray icon when no unread messages." }, + { "timer <seconds>", "Set tray icon timer, seconds must be between 1-10" }) + CMD_NOEXAMPLES + }, + + { "/intype", + parse_args, 1, 1, &cons_intype_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_intype) + CMD_TAGS( + CMD_TAG_UI, + CMD_TAG_CHAT) + CMD_SYN( + "/intype on|off") + CMD_DESC( + "Show when a contact is typing in the console, and in active message window.") + CMD_ARGS( + { "on|off", "Enable or disable contact typing messages." }) + CMD_NOEXAMPLES + }, + + { "/splash", + parse_args, 1, 1, &cons_splash_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_splash) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/splash on|off") + CMD_DESC( + "Switch on or off the ascii logo on start up and when the /about command is called.") + CMD_ARGS( + { "on|off", "Enable or disable splash logo." }) + CMD_NOEXAMPLES + }, + + { "/autoconnect", + parse_args, 1, 2, &cons_autoconnect_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_autoconnect) + CMD_TAGS( + CMD_TAG_CONNECTION) + CMD_SYN( + "/autoconnect set <account>", + "/autoconnect off") + CMD_DESC( + "Enable or disable autoconnect on start up. " + "The setting can be overridden by the -a (--account) command line option.") + CMD_ARGS( + { "set <account>", "Connect with account on start up." }, + { "off", "Disable autoconnect." }) + CMD_EXAMPLES( + "/autoconnect set jc@stuntteam.org", + "/autoconnect off") + }, + + { "/vercheck", + parse_args, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_vercheck) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/vercheck on|off") + CMD_DESC( + "Check for new versions when Profanity starts, and when the /about command is run.") + CMD_ARGS( + { "on|off", "Enable or disable the version check." }) + CMD_NOEXAMPLES + }, + + { "/titlebar", + parse_args, 2, 2, &cons_titlebar_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_titlebar) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/titlebar show on|off", + "/titlebar goodbye on|off") + CMD_DESC( + "Allow Profanity to modify the window title bar.") + CMD_ARGS( + { "show on|off", "Show current logged in user, and unread messages as the window title." }, + { "goodbye on|off", "Show a message in the title when exiting profanity." }) + CMD_NOEXAMPLES + }, + + { "/alias", + parse_args_with_freetext, 1, 3, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_alias) + CMD_NOTAGS + CMD_SYN( + "/alias list", + "/alias add <name> <value>", + "/alias remove <name>") + CMD_DESC( + "Add, remove or list command aliases.") + CMD_ARGS( + { "list", "List all aliases." }, + { "add <name> <value>", "Add a new command alias." }, + { "remove <name>", "Remove a command alias." }) + CMD_EXAMPLES( + "/alias add friends /who online friends", + "/alias add /q /quit", + "/alias a /away \"I'm in a meeting.\"", + "/alias remove q", + "/alias list") + }, + + { "/chlog", + parse_args, 1, 1, &cons_chlog_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_chlog) + CMD_TAGS( + CMD_TAG_CHAT) + CMD_SYN( + "/chlog on|off") + CMD_DESC( + "Switch chat logging on or off. " + "This setting will be enabled if /history is set to on. " + "When disabling this option, /history will also be disabled. " + "See the /grlog setting for enabling logging of chat room (groupchat) messages.") + CMD_ARGS( + { "on|off", "Enable or disable chat logging." }) + CMD_NOEXAMPLES + }, + + { "/grlog", + parse_args, 1, 1, &cons_grlog_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_grlog) + CMD_TAGS( + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/grlog on|off") + CMD_DESC( + "Switch chat room logging on or off. " + "See the /chlog setting for enabling logging of one to one chat.") + CMD_ARGS( + { "on|off", "Enable or disable chat room logging." }) + CMD_NOEXAMPLES + }, + + { "/states", + parse_args, 1, 1, &cons_states_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_states) + CMD_TAGS( + CMD_TAG_CHAT) + CMD_SYN( + "/states on|off") + CMD_DESC( + "Send chat state notifications to recipient during chat sessions, such as typing, paused, active, gone.") + CMD_ARGS( + { "on|off", "Enable or disable sending of chat state notifications." }) + CMD_NOEXAMPLES + }, + + { "/pgp", + parse_args, 1, 3, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_pgp) + CMD_TAGS( + CMD_TAG_CHAT, + CMD_TAG_UI) + CMD_SYN( + "/pgp libver", + "/pgp keys", + "/pgp contacts", + "/pgp setkey <contact> <keyid>", + "/pgp start [<contact>]", + "/pgp end", + "/pgp log on|off|redact", + "/pgp char <char>") + CMD_DESC( + "Open PGP commands to manage keys, and perform PGP encryption during chat sessions. " + "See the /account command to set your own PGP key.") + CMD_ARGS( + { "libver", "Show which version of the libgpgme library is being used." }, + { "keys", "List all keys known to the system." }, + { "contacts", "Show contacts with assigned public keys." }, + { "setkey <contact> <keyid>", "Manually associate a contact with a public key." }, + { "start [<contact>]", "Start PGP encrypted chat, current contact will be used if not specified." }, + { "end", "End PGP encrypted chat with the current recipient." }, + { "log on|off", "Enable or disable plaintext logging of PGP encrypted messages." }, + { "log redact", "Log PGP encrypted messages, but replace the contents with [redacted]. This is the default." }, + { "char <char>", "Set the character to be displayed next to PGP encrypted messages." }) + CMD_EXAMPLES( + "/pgp log off", + "/pgp setkey buddy@buddychat.org BA19CACE5A9592C5", + "/pgp start buddy@buddychat.org", + "/pgp end", + "/pgp char P") + }, + + { "/otr", + parse_args, 1, 3, NULL, + CMD_SUBFUNCS( + { "char", cmd_otr_char }, + { "log", cmd_otr_log }, + { "libver", cmd_otr_libver }, + { "policy", cmd_otr_policy }, + { "gen", cmd_otr_gen }, + { "myfp", cmd_otr_myfp }, + { "theirfp", cmd_otr_theirfp }, + { "start", cmd_otr_start }, + { "end", cmd_otr_end }, + { "trust", cmd_otr_trust }, + { "untrust", cmd_otr_untrust }, + { "secret", cmd_otr_secret }, + { "question", cmd_otr_question }, + { "answer", cmd_otr_answer }) + CMD_NOMAINFUNC + CMD_TAGS( + CMD_TAG_CHAT, + CMD_TAG_UI) + CMD_SYN( + "/otr libver", + "/otr gen", + "/otr myfp|theirfp", + "/otr start [<contact>]", + "/otr end", + "/otr trust|untrust", + "/otr secret <secret>", + "/otr question <question> <answer>", + "/otr answer <answer>", + "/otr policy manual|opportunistic|always [<contact>]", + "/otr log on|off|redact", + "/otr char <char>") + CMD_DESC( + "Off The Record (OTR) commands to manage keys, and perform OTR encryption during chat sessions.") + CMD_ARGS( + { "libver", "Show which version of the libotr library is being used." }, + { "gen", "Generate your private key." }, + { "myfp", "Show your fingerprint." }, + { "theirfp", "Show contacts fingerprint." }, + { "start [<contact>]", "Start an OTR session with contact, or current recipient if omitted." }, + { "end", "End the current OTR session," }, + { "trust|untrust", "Indicate whether or not you trust the contact's fingerprint." }, + { "secret <secret>", "Verify a contact's identity using a shared secret." }, + { "question <question> <answer>", "Verify a contact's identity using a question and expected answer." }, + { "answer <answer>", "Respond to a question answer verification request with your answer." }, + { "policy manual", "Set the global OTR policy to manual, OTR sessions must be started manually." }, + { "policy manual <contact>", "Set the OTR policy to manual for a specific contact." }, + { "policy opportunistic", "Set the global OTR policy to opportunistic, an OTR session will be attempted upon starting a conversation." }, + { "policy opportunistic <contact>", "Set the OTR policy to opportunistic for a specific contact." }, + { "policy always", "Set the global OTR policy to always, an error will be displayed if an OTR session cannot be initiated upon starting a conversation." }, + { "policy always <contact>", "Set the OTR policy to always for a specific contact." }, + { "log on|off", "Enable or disable plaintext logging of OTR encrypted messages." }, + { "log redact", "Log OTR encrypted messages, but replace the contents with [redacted]. This is the default." }, + { "char <char>", "Set the character to be displayed next to OTR encrypted messages." }) + CMD_EXAMPLES( + "/otr log off", + "/otr policy manual", + "/otr policy opportunistic mrfriend@workchat.org", + "/otr gen", + "/otr start buddy@buddychat.org", + "/otr myfp", + "/otr theirfp", + "/otr question \"What is the name of my rabbit?\" fiffi", + "/otr end", + "/otr char *") + }, + + { "/outtype", + parse_args, 1, 1, &cons_outtype_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_outtype) + CMD_TAGS( + CMD_TAG_CHAT) + CMD_SYN( + "/outtype on|off") + CMD_DESC( + "Send typing notifications, chat states (/states) will be enabled if this setting is enabled.") + CMD_ARGS( + { "on|off", "Enable or disable sending typing notifications." }) + CMD_NOEXAMPLES + }, + + { "/gone", + parse_args, 1, 1, &cons_gone_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_gone) + CMD_TAGS( + CMD_TAG_CHAT) + CMD_SYN( + "/gone <minutes>") + CMD_DESC( + "Send a 'gone' state to the recipient after the specified number of minutes. " + "Chat states (/states) will be enabled if this setting is set.") + CMD_ARGS( + { "<minutes>", "Number of minutes of inactivity before sending the 'gone' state, a value of 0 will disable sending this state." }) + CMD_NOEXAMPLES + }, + + { "/history", + parse_args, 1, 1, &cons_history_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_history) + CMD_TAGS( + CMD_TAG_UI, + CMD_TAG_CHAT) + CMD_SYN( + "/history on|off") + CMD_DESC( + "Switch chat history on or off, /chlog will automatically be enabled when this setting is on. " + "When history is enabled, previous messages are shown in chat windows.") + CMD_ARGS( + { "on|off", "Enable or disable showing chat history." }) + CMD_NOEXAMPLES + }, + + { "/log", + parse_args, 1, 2, &cons_log_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_log) + CMD_NOTAGS + CMD_SYN( + "/log where", + "/log rotate on|off", + "/log maxsize <bytes>", + "/log shared on|off") + CMD_DESC( + "Manage profanity log settings.") + CMD_ARGS( + { "where", "Show the current log file location." }, + { "rotate on|off", "Rotate log, default on." }, + { "maxsize <bytes>", "With rotate enabled, specifies the max log size, defaults to 1048580 (1MB)." }, + { "shared on|off", "Share logs between all instances, default: on. When off, the process id will be included in the log." }) + CMD_NOEXAMPLES + }, + + { "/carbons", + parse_args, 1, 1, &cons_carbons_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_carbons) + CMD_TAGS( + CMD_TAG_CHAT) + CMD_SYN( + "/carbons on|off") + CMD_DESC( + "Enable or disable message carbons. " + "Message carbons ensure that both sides of all conversations are shared with all the user's clients that implement this protocol.") + CMD_ARGS( + { "on|off", "Enable or disable message carbons." }) + CMD_NOEXAMPLES + }, + + { "/receipts", + parse_args, 2, 2, &cons_receipts_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_receipts) + CMD_TAGS( + CMD_TAG_CHAT) + CMD_SYN( + "/receipts request on|off", + "/receipts send on|off") + CMD_DESC( + "Enable or disable message delivery receipts. The interface will indicate when a message has been received.") + CMD_ARGS( + { "request on|off", "Whether or not to request a receipt upon sending a message." }, + { "send on|off", "Whether or not to send a receipt if one has been requested with a received message." }) + CMD_NOEXAMPLES + }, + + { "/reconnect", + parse_args, 1, 1, &cons_reconnect_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_reconnect) + CMD_TAGS( + CMD_TAG_CONNECTION) + CMD_SYN( + "/reconnect <seconds>") + CMD_DESC( + "Set the reconnect attempt interval for when the connection is lost.") + CMD_ARGS( + { "<seconds>", "Number of seconds before attempting to reconnect, a value of 0 disables reconnect." }) + CMD_NOEXAMPLES + }, + + { "/autoping", + parse_args, 2, 2, &cons_autoping_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_autoping) + CMD_TAGS( + CMD_TAG_CONNECTION) + CMD_SYN( + "/autoping set <seconds>", + "/autoping timeout <seconds>") + CMD_DESC( + "Set the interval between sending ping requests to the server to ensure the connection is kept alive.") + CMD_ARGS( + { "set <seconds>", "Number of seconds between sending pings, a value of 0 disables autoping." }, + { "timeout <seconds>", "Seconds to wait for autoping responses, after which the connection is considered broken." }) + CMD_NOEXAMPLES + }, + + { "/ping", + parse_args, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_ping) + CMD_TAGS( + CMD_TAG_CONNECTION) + CMD_SYN( + "/ping [<jid>]") + CMD_DESC( + "Sends an IQ ping stanza to the specified JID. " + "If no JID is supplied, your chat server will be pinged.") + CMD_ARGS( + { "<jid>", "The Jabber ID to send the ping request to." }) + CMD_NOEXAMPLES + }, + + { "/autoaway", + parse_args_with_freetext, 2, 3, &cons_autoaway_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_autoaway) + CMD_TAGS( + CMD_TAG_PRESENCE) + CMD_SYN( + "/autoaway mode idle|away|off", + "/autoaway time away|xa <minutes>", + "/autoaway message away|xa <message>|off", + "/autoaway check on|off") + CMD_DESC( + "Manage autoway settings for idle time.") + CMD_ARGS( + { "mode idle", "Sends idle time, status remains online." }, + { "mode away", "Sends away and xa presence as well as idle time." }, + { "mode off", "Disabled (default)." }, + { "time away <minutes>", "Number of minutes before the away presence is sent, default: 15." }, + { "time xa <minutes>", "Number of minutes before the xa presence is sent, default: 0 (disabled)." }, + { "message away <message>", "Optional message to send with the away presence, default: off (disabled)." }, + { "message xa <message>", "Optional message to send with the xa presence, default: off (disabled)." }, + { "message away off", "Send no message with away presence." }, + { "message xa off", "Send no message with xa presence." }, + { "check on|off", "When enabled, checks for activity and sends online presence, default: on." }) + CMD_EXAMPLES( + "/autoaway mode away", + "/autoaway time away 30", + "/autoaway message away Away from computer for a while", + "/autoaway time xa 120", + "/autoaway message xa Away from computer for a very long time", + "/autoaway check off") + }, + + { "/priority", + parse_args, 1, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_priority) + CMD_TAGS( + CMD_TAG_PRESENCE) + CMD_SYN( + "/priority <priority>") + CMD_DESC( + "Set priority for the current account. " + "See the /account command for specific priority settings per presence status.") + CMD_ARGS( + { "<priority>", "Number between -128 and 127, default: 0." }) + CMD_NOEXAMPLES + }, + + { "/account", + parse_args, 0, 4, NULL, + CMD_SUBFUNCS( + { "list", cmd_account_list }, + { "show", cmd_account_show }, + { "add", cmd_account_add }, + { "remove", cmd_account_remove }, + { "enable", cmd_account_enable }, + { "disable", cmd_account_disable }, + { "rename", cmd_account_rename }, + { "default", cmd_account_default }, + { "set", cmd_account_set }, + { "clear", cmd_account_clear }) + CMD_MAINFUNC(cmd_account) + CMD_TAGS( + CMD_TAG_CONNECTION + CMD_TAG_PRESENCE, + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/account", + "/account list", + "/account show <account>", + "/account enable|disable <account>", + "/account default set <account>", + "/account default off", + "/account add <account>", + "/account remove <account>", + "/account rename <account> <newaccount>", + "/account set <account> jid <jid>", + "/account set <account> server <server>", + "/account set <account> port <port>", + "/account set <account> status <presence>", + "/account set <account> status last", + "/account set <account> <presence> <priority>", + "/account set <account> resource <resource>", + "/account set <account> password <password>", + "/account set <account> eval_password <command>", + "/account set <account> muc <service>", + "/account set <account> nick <nick>", + "/account set <account> otr <policy>", + "/account set <account> pgpkeyid <pgpkeyid>", + "/account set <account> startscript <script>", + "/account set <account> tls force|allow|disable", + "/account set <account> theme <theme>", + "/account clear <account> password", + "/account clear <account> eval_password", + "/account clear <account> server", + "/account clear <account> port", + "/account clear <account> otr", + "/account clear <account> pgpkeyid", + "/account clear <account> startscript") + CMD_DESC( + "Commands for creating and managing accounts. " + "Calling with no arguments will display information for the current account.") + CMD_ARGS( + { "list", "List all accounts." }, + { "enable <account>", "Enable the account, it will be used for autocompletion." }, + { "show <account>", "Show details for the specified account." }, + { "disable <account>", "Disable the account." }, + { "default set <account>", "Set the default account, used when no argument passed to the /connect command." }, + { "default off", "Clear the default account setting." }, + { "add <account>", "Create a new account." }, + { "remove <account>", "Remove an account." }, + { "rename <account> <newaccount>", "Rename 'account' to 'newaccount'." }, + { "set <account> jid <jid>", "Set the Jabber ID for the account, account name will be used if not set." }, + { "set <account> server <server>", "The chat server, if different to the domainpart of the JID." }, + { "set <account> port <port>", "The port used for connecting if not the default (5222, or 5223 for SSL)." }, + { "set <account> status <presence>", "The presence status to use on login." }, + { "set <account> status last", "Use your last status before logging out, when logging in." }, + { "set <account> <presence> <priority>", "Set the priority (-128..127) to use for the specified presence." }, + { "set <account> resource <resource>", "The resource to be used for this account." }, + { "set <account> password <password>", "Password for the account, note this is currently stored in plaintext if set." }, + { "set <account> eval_password <command>", "Shell command evaluated to retrieve password for the account. Can be used to retrieve password from keyring." }, + { "set <account> muc <service>", "The default MUC chat service to use, defaults to 'conference.<domainpart>' where the domain part is from the account JID." }, + { "set <account> nick <nick>", "The default nickname to use when joining chat rooms." }, + { "set <account> otr <policy>", "Override global OTR policy for this account, see /otr." }, + { "set <account> pgpkeyid <pgpkeyid>", "Set the ID of the PGP key for this account, see /pgp." }, + { "set <account> startscript <script>", "Set the script to execute after connecting." }, + { "set <account> tls force", "Force TLS connection, and fail if one cannot be established, this is default behaviour." }, + { "set <account> tls allow", "Use TLS for the connection if it is available." }, + { "set <account> tls disable", "Disable TLS for the connection." }, + { "set <account> <theme>", "Set the UI theme for the account." }, + { "clear <account> server", "Remove the server setting for this account." }, + { "clear <account> port", "Remove the port setting for this account." }, + { "clear <account> password", "Remove the password setting for this account." }, + { "clear <account> eval_password", "Remove the eval_password setting for this account." }, + { "clear <account> otr", "Remove the OTR policy setting for this account." }, + { "clear <account> pgpkeyid", "Remove pgpkeyid associated with this account." }, + { "clear <account> startscript", "Remove startscript associated with this account." }, + { "clear <account> theme", "Clear the theme setting for the account, the global theme will be used." }) + CMD_EXAMPLES( + "/account add me", + "/account set me jid me@chatty", + "/account set me server talk.chat.com", + "/account set me port 5111", + "/account set me muc chatservice.mycompany.com", + "/account set me nick dennis", + "/account set me status dnd", + "/account set me dnd -1", + "/account rename me gtalk") + }, + + { "/plugins", + parse_args, 0, 2, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_plugins) + CMD_NOTAGS + CMD_SYN( + "/plugins", + "/plugins load <plugin>") + CMD_DESC( + "Manage plugins. Passing no arguments lists currently loaded plugins.") + CMD_ARGS( + { "load <plugin>", "Load a plugin." }) + CMD_EXAMPLES( + "/plugin load browser.py") + }, + + { "/prefs", + parse_args, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_prefs) + CMD_NOTAGS + CMD_SYN( + "/prefs [ui|desktop|chat|log|conn|presence|otr|pgp]") + CMD_DESC( + "Show preferences for different areas of functionality. " + "Passing no arguments shows all preferences.") + CMD_ARGS( + { "ui", "User interface preferences." }, + { "desktop", "Desktop notification preferences." }, + { "chat", "Chat state preferences." }, + { "log", "Logging preferences." }, + { "conn", "Connection handling preferences." }, + { "presence", "Chat presence preferences." }, + { "otr", "Off The Record preferences." }, + { "pgp", "OpenPGP preferences." }) + CMD_NOEXAMPLES + }, + + { "/theme", + parse_args, 1, 2, &cons_theme_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_theme) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/theme list", + "/theme load <theme>", + "/theme colours", + "/theme properties") + CMD_DESC( + "Load a theme, includes colours and UI options.") + CMD_ARGS( + { "list", "List all available themes." }, + { "load <theme>", "Load the specified theme. 'default' will reset to the default theme." }, + { "colours", "Show colour values as rendered by the terminal." }, + { "properties", "Show colour settings for current theme." }) + CMD_EXAMPLES( + "/theme list", + "/theme load forest") + }, + + { "/statuses", + parse_args, 2, 2, &cons_statuses_setting, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_statuses) + CMD_TAGS( + CMD_TAG_UI, + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/statuses console|chat|muc all|online|none") + CMD_DESC( + "Configure which presence changes are displayed in various windows. " + "The default is 'all' for all windows.") + CMD_ARGS( + { "console", "Configure what is displayed in the console window." }, + { "chat", "Configure what is displayed in chat windows." }, + { "muc", "Configure what is displayed in chat room windows." }, + { "all", "Show all presence changes." }, + { "online", "Show only online/offline changes." }, + { "none", "Don't show any presence changes." }) + CMD_EXAMPLES( + "/statuses console none", + "/statuses chat online", + "/statuses muc all") + }, + + { "/xmlconsole", + parse_args, 0, 0, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_xmlconsole) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/xmlconsole") + CMD_DESC( + "Open the XML console to view incoming and outgoing XMPP traffic.") + CMD_NOARGS + CMD_NOEXAMPLES + }, + + { "/away", + parse_args_with_freetext, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_away) + CMD_TAGS( + CMD_TAG_PRESENCE) + CMD_SYN( + "/away [<message>]") + CMD_DESC( + "Set your status to 'away'.") + CMD_ARGS( + { "<message>", "Optional message to use with the status." }) + CMD_EXAMPLES( + "/away", + "/away Gone for lunch") + }, + + { "/chat", + parse_args_with_freetext, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_chat) + CMD_TAGS( + CMD_TAG_PRESENCE) + CMD_SYN( + "/chat [<message>]") + CMD_DESC( + "Set your status to 'chat' (available for chat).") + CMD_ARGS( + { "<message>", "Optional message to use with the status." }) + CMD_EXAMPLES( + "/chat", + "/chat Please talk to me!") + }, + + { "/dnd", + parse_args_with_freetext, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_dnd) + CMD_TAGS( + CMD_TAG_PRESENCE) + CMD_SYN( + "/dnd [<message>]") + CMD_DESC( + "Set your status to 'dnd' (do not disturb).") + CMD_ARGS( + { "<message>", "Optional message to use with the status." }) + CMD_EXAMPLES( + "/dnd", + "/dnd I'm in the zone") + }, + + { "/online", + parse_args_with_freetext, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_online) + CMD_TAGS( + CMD_TAG_PRESENCE) + CMD_SYN( + "/online [<message>]") + CMD_DESC( + "Set your status to 'online'.") + CMD_ARGS( + { "<message>", "Optional message to use with the status." }) + CMD_EXAMPLES( + "/online", + "/online Up the Irons!") + }, + + { "/xa", + parse_args_with_freetext, 0, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_xa) + CMD_TAGS( + CMD_TAG_PRESENCE) + CMD_SYN( + "/xa [<message>]") + CMD_DESC( + "Set your status to 'xa' (extended away).") + CMD_ARGS( + { "<message>", "Optional message to use with the status." }) + CMD_EXAMPLES( + "/xa", + "/xa This meeting is going to be a long one") + }, + + { "/script", + parse_args, 1, 2, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_script) + CMD_NOTAGS + CMD_SYN( + "/script run <script>", + "/script list", + "/script show <script>") + CMD_DESC( + "Run command scripts. " + "Scripts are stored in $XDG_DATA_HOME/profanity/scripts/ which is usually $HOME/.local/share/profanity/scripts/.") + CMD_ARGS( + { "script run <script>", "Execute a script." }, + { "script list", "List all scripts TODO." }, + { "script show <script>", "Show the commands in script TODO." }) + CMD_EXAMPLES( + "/script list", + "/script run myscript", + "/script show somescript") + }, + + { "/export", + parse_args, 1, 1, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_export) + CMD_NOTAGS + CMD_SYN( + "/export <filepath>") + CMD_DESC( + "Exports contacts to a csv file.") + CMD_ARGS( + { "<filepath>", "Path to the output file." }) + CMD_EXAMPLES( + "/export /path/to/output.csv", + "/export ~/contacts.csv") + }, +}; + + +/* + * Initialise command autocompleter and history + */ +void +cmd_init(void) +{ + log_info("Initialising commands"); + + cmd_ac_init(); + + // load command defs into hash table + commands = g_hash_table_new(g_str_hash, g_str_equal); + unsigned int i; + for (i = 0; i < ARRAY_SIZE(command_defs); i++) { + Command *pcmd = command_defs+i; + + // add to hash + g_hash_table_insert(commands, pcmd->cmd, pcmd); + + // add to commands and help autocompleters + cmd_ac_add_cmd(pcmd); + } + + // load aliases + GList *aliases = prefs_get_aliases(); + GList *curr = aliases; + while (curr) { + ProfAlias *alias = curr->data; + cmd_ac_add_alias(alias); + curr = g_list_next(curr); + } + prefs_free_aliases(aliases); +} + +void +cmd_uninit(void) +{ + cmd_ac_uninit(); +} + +gboolean +cmd_valid_tag(const char *const str) +{ + return ((g_strcmp0(str, CMD_TAG_CHAT) == 0) || + (g_strcmp0(str, CMD_TAG_GROUPCHAT) == 0) || + (g_strcmp0(str, CMD_TAG_PRESENCE) == 0) || + (g_strcmp0(str, CMD_TAG_ROSTER) == 0) || + (g_strcmp0(str, CMD_TAG_DISCOVERY) == 0) || + (g_strcmp0(str, CMD_TAG_CONNECTION) == 0) || + (g_strcmp0(str, CMD_TAG_UI) == 0) || + (g_strcmp0(str, CMD_TAG_PLUGINS) == 0)); +} + +Command* +cmd_get(const char *const command) +{ + if (commands) { + return g_hash_table_lookup(commands, command); + } else { + return NULL; + } +} + +GList* +cmd_get_ordered(const char *const tag) +{ + GList *ordered_commands = NULL; + + GHashTableIter iter; + gpointer key; + gpointer value; + + g_hash_table_iter_init(&iter, commands); + while (g_hash_table_iter_next(&iter, &key, &value)) { + Command *pcmd = (Command *)value; + if (tag) { + if (_cmd_has_tag(pcmd, tag)) { + ordered_commands = g_list_insert_sorted(ordered_commands, pcmd->cmd, (GCompareFunc)g_strcmp0); + } + } else { + ordered_commands = g_list_insert_sorted(ordered_commands, pcmd->cmd, (GCompareFunc)g_strcmp0); + } + } + + return ordered_commands; +} + +static gboolean +_cmd_has_tag(Command *pcmd, const char *const tag) +{ + int i = 0; + for (i = 0; pcmd->help.tags[i] != NULL; i++) { + if (g_strcmp0(tag, pcmd->help.tags[i]) == 0) { + return TRUE; + } + } + + return FALSE; +} + +static int +_cmp_command(Command *cmd1, Command *cmd2) +{ + return g_strcmp0(cmd1->cmd, cmd2->cmd); +} + +void +command_docgen(void) +{ + GList *cmds = NULL; + unsigned int i; + for (i = 0; i < ARRAY_SIZE(command_defs); i++) { + Command *pcmd = command_defs+i; + cmds = g_list_insert_sorted(cmds, pcmd, (GCompareFunc)_cmp_command); + } + + FILE *toc_fragment = fopen("toc_fragment.html", "w"); + FILE *main_fragment = fopen("main_fragment.html", "w"); + + fputs("<ul><li><ul><li>\n", toc_fragment); + fputs("<hr>\n", main_fragment); + + GList *curr = cmds; + while (curr) { + Command *pcmd = curr->data; + + fprintf(toc_fragment, "<a href=\"#%s\">%s</a>,\n", &pcmd->cmd[1], pcmd->cmd); + fprintf(main_fragment, "<a name=\"%s\"></a>\n", &pcmd->cmd[1]); + fprintf(main_fragment, "<h4>%s</h4>\n", pcmd->cmd); + + fputs("<p><b>Synopsis</b></p>\n", main_fragment); + fputs("<p><pre><code>", main_fragment); + int i = 0; + while (pcmd->help.synopsis[i]) { + char *str1 = str_replace(pcmd->help.synopsis[i], "<", "<"); + char *str2 = str_replace(str1, ">", ">"); + fprintf(main_fragment, "%s\n", str2); + i++; + } + fputs("</code></pre></p>\n", main_fragment); + + fputs("<p><b>Description</b></p>\n", main_fragment); + fputs("<p>", main_fragment); + fprintf(main_fragment, "%s\n", pcmd->help.desc); + fputs("</p>\n", main_fragment); + + if (pcmd->help.args[0][0] != NULL) { + fputs("<p><b>Arguments</b></p>\n", main_fragment); + fputs("<table>", main_fragment); + for (i = 0; pcmd->help.args[i][0] != NULL; i++) { + fputs("<tr>", main_fragment); + fputs("<td>", main_fragment); + fputs("<code>", main_fragment); + char *str1 = str_replace(pcmd->help.args[i][0], "<", "<"); + char *str2 = str_replace(str1, ">", ">"); + fprintf(main_fragment, "%s", str2); + fputs("</code>", main_fragment); + fputs("</td>", main_fragment); + fputs("<td>", main_fragment); + fprintf(main_fragment, "%s", pcmd->help.args[i][1]); + fputs("</td>", main_fragment); + fputs("</tr>", main_fragment); + } + fputs("</table>\n", main_fragment); + } + + if (pcmd->help.examples[0] != NULL) { + fputs("<p><b>Examples</b></p>\n", main_fragment); + fputs("<p><pre><code>", main_fragment); + int i = 0; + while (pcmd->help.examples[i]) { + fprintf(main_fragment, "%s\n", pcmd->help.examples[i]); + i++; + } + fputs("</code></pre></p>\n", main_fragment); + } + + fputs("<a href=\"#top\"><h5>back to top</h5></a><br><hr>\n", main_fragment); + fputs("\n", main_fragment); + + curr = g_list_next(curr); + } + + fputs("</ul></ul>\n", toc_fragment); + + fclose(toc_fragment); + fclose(main_fragment); + printf("\nProcessed %d commands.\n\n", g_list_length(cmds)); + g_list_free(cmds); +} diff --git a/src/command/command.h b/src/command/cmd_defs.h index 34beee86..85dee14f 100644 --- a/src/command/command.h +++ b/src/command/cmd_defs.h @@ -1,5 +1,5 @@ /* - * command.h + * cmd_defs.h * * Copyright (C) 2012 - 2016 James Booth <boothj5@gmail.com> * @@ -32,43 +32,20 @@ * */ -#ifndef COMMAND_H -#define COMMAND_H +#ifndef CMD_DEFS_H +#define CMD_DEFS_H #include <glib.h> #include "ui/ui.h" -GHashTable *commands; - void cmd_init(void); void cmd_uninit(void); -char* cmd_autocomplete(ProfWin *window, const char *const input); -void cmd_reset_autocomplete(ProfWin *window); -void cmd_help_autocomplete_add(const char *const value); -void cmd_autocomplete_add(const char *const value); -void cmd_autocomplete_remove(const char *const value); -void cmd_autocomplete_add_form_fields(DataForm *form); -void cmd_autocomplete_remove_form_fields(DataForm *form); -void cmd_alias_add(char *value); -void cmd_alias_remove(char *value); +Command* cmd_get(const char *const command); +GList* cmd_get_ordered(const char *const tag); gboolean cmd_valid_tag(const char *const str); -gboolean cmd_has_tag(Command *pcmd, const char *const tag); - -gboolean cmd_process_input(ProfWin *window, char *inp); -void cmd_execute_connect(ProfWin *window, const char *const account); - -gboolean cmd_exists(char *cmd); - -GSList* cmd_get_basic_help(void); -GSList* cmd_get_settings_help(void); -GSList* cmd_get_presence_help(void); - -void cmd_history_append(char *inp); -char* cmd_history_previous(char *inp); -char* cmd_history_next(char *inp); void command_docgen(void); diff --git a/src/command/commands.c b/src/command/cmd_funcs.c index 177c56bb..03a7e8e5 100644 --- a/src/command/commands.c +++ b/src/command/cmd_funcs.c @@ -1,5 +1,5 @@ /* - * commands.c + * cmd_funcs.c * * Copyright (C) 2012 - 2016 James Booth <boothj5@gmail.com> * @@ -50,8 +50,9 @@ #include <ctype.h> #include "chat_session.h" -#include "command/commands.h" -#include "command/command.h" +#include "command/cmd_funcs.h" +#include "command/cmd_defs.h" +#include "command/cmd_ac.h" #include "common.h" #include "config/accounts.h" #include "config/account.h" @@ -90,96 +91,59 @@ static void _cmd_set_boolean_preference(gchar *arg, const char *const command, const char *const display, preference_t pref); static void _who_room(ProfWin *window, const char *const command, gchar **args); static void _who_roster(ProfWin *window, const char *const command, gchar **args); +static gboolean _cmd_execute(ProfWin *window, const char *const command, const char *const inp); +static gboolean _cmd_execute_default(ProfWin *window, const char *inp); +static gboolean _cmd_execute_alias(ProfWin *window, const char *const inp, gboolean *ran); -extern GHashTable *commands; - +/* + * Take a line of input and process it, return TRUE if profanity is to + * continue, FALSE otherwise + */ gboolean -cmd_execute_default(ProfWin *window, const char *inp) +cmd_process_input(ProfWin *window, char *inp) { - // handle escaped commands - treat as normal message - if (g_str_has_prefix(inp, "//")) { - inp++; - - // handle unknown commands - } else if ((inp[0] == '/') && (!g_str_has_prefix(inp, "/me "))) { - cons_show("Unknown command: %s", inp); - cons_alert(); - return TRUE; - } + log_debug("Input received: %s", inp); + gboolean result = FALSE; + g_strchomp(inp); - // handle non commands in non chat or plugin windows - if (window->type != WIN_CHAT && window->type != WIN_MUC && window->type != WIN_PRIVATE && window->type != WIN_PLUGIN && window->type != WIN_XML) { - cons_show("Unknown command: %s", inp); - return TRUE; - } - - // handle plugin window - if (window->type == WIN_PLUGIN) { - ProfPluginWin *pluginwin = (ProfPluginWin*)window; - plugins_win_process_line(pluginwin->tag, inp); - return TRUE; - } + // just carry on if no input + if (strlen(inp) == 0) { + result = TRUE; - jabber_conn_status_t status = connection_get_status(); - if (status != JABBER_CONNECTED) { - ui_current_print_line("You are not currently connected."); - return TRUE; - } + // handle command if input starts with a '/' + } else if (inp[0] == '/') { + char *inp_cpy = strdup(inp); + char *command = strtok(inp_cpy, " "); + char *question_mark = strchr(command, '?'); + if (question_mark) { + *question_mark = '\0'; + char *fakeinp; + if (asprintf(&fakeinp, "/help %s", command+1)) { + result = _cmd_execute(window, "/help", fakeinp); + free(fakeinp); + } + } else { + result = _cmd_execute(window, command, inp); + } + free(inp_cpy); - switch (window->type) { - case WIN_CHAT: - { - ProfChatWin *chatwin = (ProfChatWin*)window; - assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); - cl_ev_send_msg(chatwin, inp, NULL); - break; - } - case WIN_PRIVATE: - { - ProfPrivateWin *privatewin = (ProfPrivateWin*)window; - assert(privatewin->memcheck == PROFPRIVATEWIN_MEMCHECK); - cl_ev_send_priv_msg(privatewin, inp, NULL); - break; - } - case WIN_MUC: - { - ProfMucWin *mucwin = (ProfMucWin*)window; - assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); - cl_ev_send_muc_msg(mucwin, inp, NULL); - break; - } - case WIN_XML: - { - connection_send_stanza(inp); - break; - } - default: - break; + // call a default handler if input didn't start with '/' + } else { + result = _cmd_execute_default(window, inp); } - return TRUE; + return result; } -gboolean -cmd_execute_alias(ProfWin *window, const char *const inp, gboolean *ran) -{ - if (inp[0] != '/') { - ran = FALSE; - return TRUE; - } +// Command execution - char *alias = strdup(inp+1); - char *value = prefs_get_alias(alias); - free(alias); - if (value) { - *ran = TRUE; - gboolean result = cmd_process_input(window, value); - prefs_free_string(value); - return result; - } - - *ran = FALSE; - return TRUE; +void +cmd_execute_connect(ProfWin *window, const char *const account) +{ + GString *command = g_string_new("/connect "); + g_string_append(command, account); + cmd_process_input(window, command->str); + g_string_free(command, TRUE); } gboolean @@ -1522,21 +1486,7 @@ _cmd_help_cmd_list(const char *const tag) } g_list_free(plugins_cmds); } else { - GHashTableIter iter; - gpointer key; - gpointer value; - - g_hash_table_iter_init(&iter, commands); - while (g_hash_table_iter_next(&iter, &key, &value)) { - Command *pcmd = (Command *)value; - if (tag) { - if (cmd_has_tag(pcmd, tag)) { - ordered_commands = g_list_insert_sorted(ordered_commands, pcmd->cmd, (GCompareFunc)g_strcmp0); - } - } else { - ordered_commands = g_list_insert_sorted(ordered_commands, pcmd->cmd, (GCompareFunc)g_strcmp0); - } - } + ordered_commands = cmd_get_ordered(tag); // add plugins if showing all commands if (!tag) { @@ -1607,7 +1557,7 @@ cmd_help(ProfWin *window, const char *const command, gchar **args) char cmd_with_slash[1 + strlen(cmd) + 1]; sprintf(cmd_with_slash, "/%s", cmd); - Command *command = g_hash_table_lookup(commands, cmd_with_slash); + Command *command = cmd_get(cmd_with_slash); if (command) { cons_show_help(cmd_with_slash, &command->help); } else { @@ -3860,7 +3810,7 @@ cmd_form(ProfWin *window, const char *const command, gchar **args) mucconfwin_form_help(confwin); const gchar **help_text = NULL; - Command *command = g_hash_table_lookup(commands, "/form"); + Command *command = cmd_get("/form"); if (command) { help_text = command->help.synopsis; @@ -3882,7 +3832,7 @@ cmd_form(ProfWin *window, const char *const command, gchar **args) if ((g_strcmp0(args[0], "submit") == 0) || (g_strcmp0(args[0], "cancel") == 0)) { if (confwin->form) { - cmd_autocomplete_remove_form_fields(confwin->form); + cmd_ac_remove_form_fields(confwin->form); } int num = wins_get_num(window); @@ -4627,14 +4577,14 @@ cmd_alias(ProfWin *window, const char *const command, gchar **args) cons_bad_cmd_usage(command); g_string_free(ac_value, TRUE); return TRUE; - } else if (cmd_exists(ac_value->str)) { + } else if (cmd_ac_exists(ac_value->str)) { cons_show("Command or alias '%s' already exists.", ac_value->str); g_string_free(ac_value, TRUE); return TRUE; } else { prefs_add_alias(alias_p, value); - cmd_autocomplete_add(ac_value->str); - cmd_alias_add(alias_p); + cmd_ac_add(ac_value->str); + cmd_ac_add_alias_value(alias_p); cons_show("Command alias added %s -> %s", ac_value->str, value); g_string_free(ac_value, TRUE); return TRUE; @@ -4655,8 +4605,8 @@ cmd_alias(ProfWin *window, const char *const command, gchar **args) } else { GString *ac_value = g_string_new("/"); g_string_append(ac_value, alias); - cmd_autocomplete_remove(ac_value->str); - cmd_alias_remove(alias); + cmd_ac_remove(ac_value->str); + cmd_ac_remove_alias_value(alias); g_string_free(ac_value, TRUE); cons_show("Command alias removed -> /%s", alias); } @@ -6800,6 +6750,156 @@ cmd_encwarn(ProfWin *window, const char *const command, gchar **args) return TRUE; } +static gboolean +_cmd_execute(ProfWin *window, const char *const command, const char *const inp) +{ + if (g_str_has_prefix(command, "/field") && window->type == WIN_MUC_CONFIG) { + gboolean result = FALSE; + gchar **args = parse_args_with_freetext(inp, 1, 2, &result); + if (!result) { + ui_current_print_formatted_line('!', 0, "Invalid command, see /form help"); + result = TRUE; + } else { + gchar **tokens = g_strsplit(inp, " ", 2); + char *field = tokens[0] + 1; + result = cmd_form_field(window, field, args); + g_strfreev(tokens); + } + + g_strfreev(args); + return result; + } + + Command *cmd = cmd_get(command); + gboolean result = FALSE; + + if (cmd) { + gchar **args = cmd->parser(inp, cmd->min_args, cmd->max_args, &result); + if (result == FALSE) { + ui_invalid_command_usage(cmd->cmd, cmd->setting_func); + return TRUE; + } + if (args[0] && cmd->sub_funcs[0][0]) { + int i = 0; + while (cmd->sub_funcs[i][0]) { + if (g_strcmp0(args[0], (char*)cmd->sub_funcs[i][0]) == 0) { + gboolean (*func)(ProfWin *window, const char *const command, gchar **args) = cmd->sub_funcs[i][1]; + gboolean result = func(window, command, args); + g_strfreev(args); + return result; + } + i++; + } + } + if (!cmd->func) { + ui_invalid_command_usage(cmd->cmd, cmd->setting_func); + return TRUE; + } + gboolean result = cmd->func(window, command, args); + g_strfreev(args); + return result; + } else if (plugins_run_command(inp)) { + return TRUE; + } else { + gboolean ran_alias = FALSE; + gboolean alias_result = _cmd_execute_alias(window, inp, &ran_alias); + if (!ran_alias) { + return _cmd_execute_default(window, inp); + } else { + return alias_result; + } + } +} + +static gboolean +_cmd_execute_default(ProfWin *window, const char *inp) +{ + // handle escaped commands - treat as normal message + if (g_str_has_prefix(inp, "//")) { + inp++; + + // handle unknown commands + } else if ((inp[0] == '/') && (!g_str_has_prefix(inp, "/me "))) { + cons_show("Unknown command: %s", inp); + cons_alert(); + return TRUE; + } + + // handle non commands in non chat or plugin windows + if (window->type != WIN_CHAT && window->type != WIN_MUC && window->type != WIN_PRIVATE && window->type != WIN_PLUGIN && window->type != WIN_XML) { + cons_show("Unknown command: %s", inp); + return TRUE; + } + + // handle plugin window + if (window->type == WIN_PLUGIN) { + ProfPluginWin *pluginwin = (ProfPluginWin*)window; + plugins_win_process_line(pluginwin->tag, inp); + return TRUE; + } + + jabber_conn_status_t status = connection_get_status(); + if (status != JABBER_CONNECTED) { + ui_current_print_line("You are not currently connected."); + return TRUE; + } + + switch (window->type) { + case WIN_CHAT: + { + ProfChatWin *chatwin = (ProfChatWin*)window; + assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); + cl_ev_send_msg(chatwin, inp, NULL); + break; + } + case WIN_PRIVATE: + { + ProfPrivateWin *privatewin = (ProfPrivateWin*)window; + assert(privatewin->memcheck == PROFPRIVATEWIN_MEMCHECK); + cl_ev_send_priv_msg(privatewin, inp, NULL); + break; + } + case WIN_MUC: + { + ProfMucWin *mucwin = (ProfMucWin*)window; + assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); + cl_ev_send_muc_msg(mucwin, inp, NULL); + break; + } + case WIN_XML: + { + connection_send_stanza(inp); + break; + } + default: + break; + } + + return TRUE; +} + +static gboolean +_cmd_execute_alias(ProfWin *window, const char *const inp, gboolean *ran) +{ + if (inp[0] != '/') { + ran = FALSE; + return TRUE; + } + + char *alias = strdup(inp+1); + char *value = prefs_get_alias(alias); + free(alias); + if (value) { + *ran = TRUE; + gboolean result = cmd_process_input(window, value); + prefs_free_string(value); + return result; + } + + *ran = FALSE; + return TRUE; +} + // helper function for status change commands static void _update_presence(const resource_presence_t resource_presence, diff --git a/src/command/commands.h b/src/command/cmd_funcs.h index 24828989..0856f5be 100644 --- a/src/command/commands.h +++ b/src/command/cmd_funcs.h @@ -1,5 +1,5 @@ /* - * commands.h + * cmd_funcs.h * * Copyright (C) 2012 - 2016 James Booth <boothj5@gmail.com> * @@ -32,8 +32,8 @@ * */ -#ifndef COMMANDS_H -#define COMMANDS_H +#ifndef CMD_FUNCS_H +#define CMD_FUNCS_H #include "ui/win_types.h" @@ -69,22 +69,11 @@ typedef struct cmd_t { CommandHelp help; } Command; -gboolean cmd_execute_alias(ProfWin *window, const char *const inp, gboolean *ran); -gboolean cmd_execute_default(ProfWin *window, const char *inp); -gboolean cmd_about(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_account(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_account_list(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_account_show(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_account_add(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_account_remove(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_account_enable(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_account_disable(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_account_rename(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_account_default(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_account_set(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_account_clear(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_process_input(ProfWin *window, char *inp); +void cmd_execute_connect(ProfWin *window, const char *const account); +gboolean cmd_about(ProfWin *window, const char *const command, gchar **args); gboolean cmd_autoaway(ProfWin *window, const char *const command, gchar **args); gboolean cmd_autoconnect(ProfWin *window, const char *const command, gchar **args); gboolean cmd_autoping(ProfWin *window, const char *const command, gchar **args); @@ -96,14 +85,6 @@ gboolean cmd_chlog(ProfWin *window, const char *const command, gchar **args); gboolean cmd_clear(ProfWin *window, const char *const command, gchar **args); gboolean cmd_close(ProfWin *window, const char *const command, gchar **args); gboolean cmd_connect(ProfWin *window, const char *const command, gchar **args); - -gboolean cmd_tls_certpath(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_tls_trust(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_tls_trusted(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_tls_revoke(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_tls_show(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_tls_cert(ProfWin *window, const char *const command, gchar **args); - gboolean cmd_decline(ProfWin *window, const char *const command, gchar **args); gboolean cmd_disco(ProfWin *window, const char *const command, gchar **args); gboolean cmd_sendfile(ProfWin *window, const char *const command, gchar **args); @@ -130,22 +111,6 @@ gboolean cmd_msg(ProfWin *window, const char *const command, gchar **args); gboolean cmd_nick(ProfWin *window, const char *const command, gchar **args); gboolean cmd_notify(ProfWin *window, const char *const command, gchar **args); gboolean cmd_online(ProfWin *window, const char *const command, gchar **args); - -gboolean cmd_otr_char(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_otr_log(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_otr_libver(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_otr_policy(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_otr_gen(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_otr_myfp(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_otr_theirfp(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_otr_start(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_otr_end(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_otr_trust(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_otr_untrust(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_otr_secret(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_otr_question(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_otr_answer(ProfWin *window, const char *const command, gchar **args); - gboolean cmd_pgp(ProfWin *window, const char *const command, gchar **args); gboolean cmd_outtype(ProfWin *window, const char *const command, gchar **args); gboolean cmd_prefs(ProfWin *window, const char *const command, gchar **args); @@ -168,14 +133,6 @@ gboolean cmd_titlebar(ProfWin *window, const char *const command, gchar **args); gboolean cmd_vercheck(ProfWin *window, const char *const command, gchar **args); gboolean cmd_who(ProfWin *window, const char *const command, gchar **args); gboolean cmd_win(ProfWin *window, const char *const command, gchar **args); - -gboolean cmd_wins(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_wins_unread(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_wins_tidy(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_wins_prune(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_wins_swap(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_wins_autotidy(ProfWin *window, const char *const command, gchar **args); - gboolean cmd_xa(ProfWin *window, const char *const command, gchar **args); gboolean cmd_alias(ProfWin *window, const char *const command, gchar **args); gboolean cmd_xmlconsole(ProfWin *window, const char *const command, gchar **args); @@ -201,6 +158,47 @@ gboolean cmd_console(ProfWin *window, const char *const command, gchar **args); gboolean cmd_plugins(ProfWin *window, const char *const command, gchar **args); gboolean cmd_blocked(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_account(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_account_list(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_account_show(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_account_add(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_account_remove(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_account_enable(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_account_disable(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_account_rename(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_account_default(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_account_set(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_account_clear(ProfWin *window, const char *const command, gchar **args); + +gboolean cmd_tls_certpath(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_tls_trust(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_tls_trusted(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_tls_revoke(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_tls_show(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_tls_cert(ProfWin *window, const char *const command, gchar **args); + +gboolean cmd_otr_char(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_otr_log(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_otr_libver(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_otr_policy(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_otr_gen(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_otr_myfp(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_otr_theirfp(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_otr_start(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_otr_end(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_otr_trust(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_otr_untrust(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_otr_secret(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_otr_question(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_otr_answer(ProfWin *window, const char *const command, gchar **args); + +gboolean cmd_wins(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_wins_unread(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_wins_tidy(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_wins_prune(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_wins_swap(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_wins_autotidy(ProfWin *window, const char *const command, gchar **args); + gboolean cmd_form_field(ProfWin *window, char *tag, gchar **args); #endif diff --git a/src/command/command.c b/src/command/command.c deleted file mode 100644 index 7495506f..00000000 --- a/src/command/command.c +++ /dev/null @@ -1,5279 +0,0 @@ -/* - * command.c - * - * Copyright (C) 2012 - 2016 James Booth <boothj5@gmail.com> - * - * This file is part of Profanity. - * - * Profanity is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Profanity is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Profanity. If not, see <http://www.gnu.org/licenses/>. - * - * In addition, as a special exception, the copyright holders give permission to - * link the code of portions of this program with the OpenSSL library under - * certain conditions as described in each individual source file, and - * distribute linked combinations including the two. - * - * You must obey the GNU General Public License in all respects for all of the - * code used other than OpenSSL. If you modify file(s) with this exception, you - * may extend this exception to your version of the file(s), but you are not - * obligated to do so. If you do not wish to do so, delete this exception - * statement from your version. If you delete this exception statement from all - * source files in the program, then also delete it here. - * - */ - -#define _GNU_SOURCE 1 - -#include "config.h" - -#include <assert.h> -#include <errno.h> -#include <limits.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <libgen.h> - -#include <dirent.h> -#include <sys/types.h> - -#include <glib.h> - -#include "chat_session.h" -#include "command/command.h" -#include "command/commands.h" -#include "common.h" -#include "config/accounts.h" -#include "config/preferences.h" -#include "config/theme.h" -#include "config/tlscerts.h" -#include "config/scripts.h" -#include "contact.h" -#include "roster_list.h" -#include "jid.h" -#include "log.h" -#include "muc.h" -#include "plugins/plugins.h" -#ifdef HAVE_LIBOTR -#include "otr/otr.h" -#endif -#ifdef HAVE_LIBGPGME -#include "pgp/gpg.h" -#endif -#include "profanity.h" -#include "tools/autocomplete.h" -#include "tools/parser.h" -#include "tools/tinyurl.h" -#include "xmpp/xmpp.h" -#include "ui/ui.h" -#include "window_list.h" - -static gboolean _cmd_execute(ProfWin *window, const char *const command, const char *const inp); - -static char* _cmd_complete_parameters(ProfWin *window, const char *const input); - -static char* _script_autocomplete_func(const char *const prefix); - -static char* _sub_autocomplete(ProfWin *window, const char *const input); -static char* _notify_autocomplete(ProfWin *window, const char *const input); -static char* _theme_autocomplete(ProfWin *window, const char *const input); -static char* _autoaway_autocomplete(ProfWin *window, const char *const input); -static char* _autoconnect_autocomplete(ProfWin *window, const char *const input); -static char* _account_autocomplete(ProfWin *window, const char *const input); -static char* _who_autocomplete(ProfWin *window, const char *const input); -static char* _roster_autocomplete(ProfWin *window, const char *const input); -static char* _group_autocomplete(ProfWin *window, const char *const input); -static char* _bookmark_autocomplete(ProfWin *window, const char *const input); -static char* _otr_autocomplete(ProfWin *window, const char *const input); -static char* _pgp_autocomplete(ProfWin *window, const char *const input); -static char* _connect_autocomplete(ProfWin *window, const char *const input); -static char* _statuses_autocomplete(ProfWin *window, const char *const input); -static char* _alias_autocomplete(ProfWin *window, const char *const input); -static char* _join_autocomplete(ProfWin *window, const char *const input); -static char* _log_autocomplete(ProfWin *window, const char *const input); -static char* _form_autocomplete(ProfWin *window, const char *const input); -static char* _form_field_autocomplete(ProfWin *window, const char *const input); -static char* _occupants_autocomplete(ProfWin *window, const char *const input); -static char* _kick_autocomplete(ProfWin *window, const char *const input); -static char* _ban_autocomplete(ProfWin *window, const char *const input); -static char* _affiliation_autocomplete(ProfWin *window, const char *const input); -static char* _role_autocomplete(ProfWin *window, const char *const input); -static char* _resource_autocomplete(ProfWin *window, const char *const input); -static char* _titlebar_autocomplete(ProfWin *window, const char *const input); -static char* _inpblock_autocomplete(ProfWin *window, const char *const input); -static char* _time_autocomplete(ProfWin *window, const char *const input); -static char* _receipts_autocomplete(ProfWin *window, const char *const input); -static char* _help_autocomplete(ProfWin *window, const char *const input); -static char* _wins_autocomplete(ProfWin *window, const char *const input); -static char* _tls_autocomplete(ProfWin *window, const char *const input); -static char* _script_autocomplete(ProfWin *window, const char *const input); -static char* _subject_autocomplete(ProfWin *window, const char *const input); -static char* _console_autocomplete(ProfWin *window, const char *const input); -static char* _win_autocomplete(ProfWin *window, const char *const input); -static char* _close_autocomplete(ProfWin *window, const char *const input); -static char* _plugins_autocomplete(ProfWin *window, const char *const input); -static char* _sendfile_autocomplete(ProfWin *window, const char *const input); -static char* _blocked_autocomplete(ProfWin *window, const char *const input); -static char *_tray_autocomplete(ProfWin *window, const char *const input); - -GHashTable *commands = NULL; - -#define CMD_TAG_CHAT "chat" -#define CMD_TAG_GROUPCHAT "groupchat" -#define CMD_TAG_ROSTER "roster" -#define CMD_TAG_PRESENCE "presence" -#define CMD_TAG_CONNECTION "connection" -#define CMD_TAG_DISCOVERY "discovery" -#define CMD_TAG_UI "ui" -#define CMD_TAG_PLUGINS "plugins" - -#define CMD_MAINFUNC(func) func, -#define CMD_NOMAINFUNC NULL, -#define CMD_SUBFUNCS(...) { __VA_ARGS__, { NULL, NULL } }, -#define CMD_NOSUBFUNCS { { NULL, NULL } }, - -#define CMD_NOTAGS { { NULL }, -#define CMD_TAGS(...) { { __VA_ARGS__, NULL }, -#define CMD_SYN(...) { __VA_ARGS__, NULL }, -#define CMD_DESC(desc) desc, -#define CMD_NOARGS { { NULL, NULL } }, -#define CMD_ARGS(...) { __VA_ARGS__, { NULL, NULL } }, -#define CMD_NOEXAMPLES { NULL } } -#define CMD_EXAMPLES(...) { __VA_ARGS__, NULL } } - -/* - * Command list - */ -static struct cmd_t command_defs[] = -{ - { "/help", - parse_args, 0, 2, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_help) - CMD_NOTAGS - CMD_SYN( - "/help [<area>|<command>]") - CMD_DESC( - "Help on using Profanity. Passing no arguments list help areas. " - "For command help, optional arguments are shown using square brackets e.g. [argument], " - "arguments representing variables rather than a literal name are surrounded by angle brackets " - "e.g. <argument>. " - "Arguments that may be one of a number of values are separated by a pipe " - "e.g. val1|val2|val3.") - CMD_ARGS( - { "<area>", "Summary help for commands in a certain area of functionality." }, - { "<command>", "Full help for a specific command, for example '/help connect'." }) - CMD_EXAMPLES( - "/help commands", - "/help presence", - "/help who") - }, - - { "/about", - parse_args, 0, 0, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_about) - CMD_NOTAGS - CMD_SYN( - "/about") - CMD_DESC( - "Show version and license information.") - CMD_NOARGS - CMD_NOEXAMPLES - }, - - { "/connect", - parse_args, 0, 7, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_connect) - CMD_TAGS( - CMD_TAG_CONNECTION) - CMD_SYN( - "/connect [<account>]", - "/connect <account> [server <server>] [port <port>] [tls force|allow|disable]") - CMD_DESC( - "Login to a chat service. " - "If no account is specified, the default is used if one is configured. " - "A local account is created with the JID as it's name if it doesn't already exist.") - CMD_ARGS( - { "<account>", "The local account you wish to connect with, or a JID if connecting for the first time." }, - { "server <server>", "Supply a server if it is different to the domain part of your JID." }, - { "port <port>", "The port to use if different to the default (5222, or 5223 for SSL)." }, - { "tls force", "Force TLS connection, and fail if one cannot be established, this is default behaviour." }, - { "tls allow", "Use TLS for the connection if it is available." }, - { "tls disable", "Disable TLS for the connection." }) - CMD_EXAMPLES( - "/connect", - "/connect myuser@gmail.com", - "/connect myuser@mycompany.com server talk.google.com", - "/connect bob@someplace port 5678", - "/connect me@localhost.test.org server 127.0.0.1 tls disable", - "/connect me@chatty server chatty.com port 5443") - }, - - { "/tls", - parse_args, 1, 3, NULL, - CMD_SUBFUNCS( - { "certpath", cmd_tls_certpath }, - { "trust", cmd_tls_trust }, - { "trusted", cmd_tls_trusted }, - { "revoke", cmd_tls_revoke }, - { "show", cmd_tls_show }, - { "cert", cmd_tls_cert }) - CMD_NOMAINFUNC - CMD_TAGS( - CMD_TAG_CONNECTION, - CMD_TAG_UI) - CMD_SYN( - "/tls allow", - "/tls always", - "/tls deny", - "/tls cert [<fingerprint>]", - "/tls trust", - "/tls trusted", - "/tls revoke <fingerprint>", - "/tls certpath", - "/tls certpath set <path>", - "/tls certpath clear", - "/tls show on|off") - CMD_DESC( - "Handle TLS certificates. ") - CMD_ARGS( - { "allow", "Allow connection to continue with TLS certificate." }, - { "always", "Always allow connections with TLS certificate." }, - { "deny", "Abort connection." }, - { "cert", "Show the current TLS certificate." }, - { "cert <fingerprint>", "Show details of trusted certificate." }, - { "trust", "Add the current TLS certificate to manually trusted certificates." }, - { "trusted", "List summary of manually trusted certificates (with '/tls always' or '/tls trust')." }, - { "revoke <fingerprint>", "Remove a manually trusted certificate." }, - { "certpath", "Show the trusted certificate path." }, - { "certpath set <path>", "Specify filesystem path containing trusted certificates." }, - { "certpath clear", "Clear the trusted certificate path." }, - { "show on|off", "Show or hide the TLS indicator in the titlebar." }) - CMD_NOEXAMPLES - }, - - { "/disconnect", - parse_args, 0, 0, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_disconnect) - CMD_TAGS( - CMD_TAG_CONNECTION) - CMD_SYN( - "/disconnect") - CMD_DESC( - "Disconnect from the current chat service.") - CMD_NOARGS - CMD_NOEXAMPLES - }, - - { "/msg", - parse_args_with_freetext, 1, 2, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_msg) - CMD_TAGS( - CMD_TAG_CHAT) - CMD_SYN( - "/msg <contact> [<message>]", - "/msg <nick> [<message>]") - CMD_DESC( - "Send a one to one chat message, or a private message to a chat room occupant. " - "If the message is omitted, a new chat window will be opened without sending a message. " - "Use quotes if the nickname includes spaces.") - CMD_ARGS( - { "<contact>", "Open chat window with contact, by JID or nickname." }, - { "<contact> [<message>]", "Send message to contact, by JID or nickname." }, - { "<nick>", "Open private chat window with chat room occupant." }, - { "<nick> [<message>]", "Send a private message to a chat room occupant." }) - CMD_EXAMPLES( - "/msg myfriend@server.com Hey, here's a message!", - "/msg otherfriend@server.com", - "/msg Bob Here is a private message", - "/msg \"My Friend\" Hi, how are you?") - }, - - { "/roster", - parse_args_with_freetext, 0, 4, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_roster) - CMD_TAGS( - CMD_TAG_ROSTER, - CMD_TAG_UI) - CMD_SYN( - "/roster", - "/roster online", - "/roster show [offline|resource|presence|status|empty|priority|contacts|rooms]", - "/roster hide [offline|resource|presence|status|empty|priority|contacts|rooms]", - "/roster by group|presence|none", - "/roster count unread|items|off", - "/roster count zero on|off", - "/roster order name|presence", - "/roster unread before|after|off", - "/roster room char <char>|none", - "/roster room private char <char>|none", - "/roster room position first|last", - "/roster room by service|none", - "/roster room order name|unread", - "/roster room unread before|after|off", - "/roster private room|group|off", - "/roster private char <char>|none", - "/roster header char <char>|none", - "/roster presence indent <indent>", - "/roster contact char <char>|none", - "/roster contact indent <indent>", - "/roster resource char <char>|none", - "/roster resource indent <indent>", - "/roster resource join on|off", - "/roster size <percent>", - "/roster wrap on|off", - "/roster add <jid> [<nick>]", - "/roster remove <jid>", - "/roster remove_all contacts", - "/roster nick <jid> <nick>", - "/roster clearnick <jid>") - CMD_DESC( - "Manage your roster, and roster display settings. " - "Passing no arguments lists all contacts in your roster.") - CMD_ARGS( - { "online", "Show all online contacts in console." }, - { "show", "Show the roster panel." }, - { "show offline", "Show offline contacts in roster panel." }, - { "show resource", "Show contact's connected resources in roster panel." }, - { "show presence", "Show contact's presence in roster panel." }, - { "show status", "Show contact's status message in roster panel." }, - { "show empty", "Show empty groups in roster panel." }, - { "show priority", "Show resource priority in roster panel." }, - { "show contacts", "Show contacts in roster panel." }, - { "show rooms", "Show chat rooms in roster panel." }, - { "hide", "Hide the roster panel." }, - { "hide offline", "Hide offline contacts in roster panel." }, - { "hide resource", "Hide contact's connected resources in roster panel." }, - { "hide presence", "Hide contact's presence in roster panel." }, - { "hide status", "Hide contact's status message in roster panel." }, - { "hide empty", "Hide empty groups in roster panel." }, - { "hide priority", "Hide resource priority in roster panel." }, - { "hide contacts", "Hide contacts in roster panel." }, - { "hide rooms", "Hide chat rooms in roster panel." }, - { "by group", "Group contacts in roster panel by roster group." }, - { "by presence", "Group contacts in roster panel by presence." }, - { "by none", "No grouping in roster panel." }, - { "count unread", "Show unread message count with roster headers." }, - { "count items", "Show item count with roster headers." }, - { "count off", "Do not show any count with roster headers." }, - { "count zero on", "Show roster header count when 0." }, - { "count zero off", "Hide roster header count when 0." }, - { "order name", "Order roster contacts by name only." }, - { "order presence", "Order roster contacts by presence, and then by name." }, - { "unread before", "Show unread message count before contact." }, - { "unread after", "Show unread message count after contact." }, - { "unread off", "Do not show unread message count for contacts." }, - { "room char <char>", "Prefix rooms with specified character." }, - { "room char none", "Remove room character prefix." }, - { "room private char <char>", "Prefix private room chat with specified character when displayed with room." }, - { "room private char none", "Remove private room chat character prefix when displayed with room." }, - { "room position first", "Show rooms first in roster." }, - { "room position last", "Show rooms last in roster." }, - { "room by service", "Group rooms by chat service." }, - { "room by none", "Do not group rooms." }, - { "room order name", "Order rooms by name." }, - { "room order unread", "Order rooms by unread messages, and then by name." }, - { "room unread before", "Show unread message count before room." }, - { "room unread after", "Show unread message count after room." }, - { "room unread off", "Do not show unread message count for rooms." }, - { "private room", "Show room private chats with the room." }, - { "private group", "Show room private chats as a separate roster group." }, - { "private off", "Do not show room private chats." }, - { "private char <char>", "Prefix private room chats with specified character when displayed in separate group." }, - { "private char none", "Remove private room chat character prefix." }, - { "header char <char>", "Prefix roster headers with specified character." }, - { "header char none", "Remove roster header character prefix." }, - { "contact char <char>", "Prefix roster contacts with specified character." }, - { "contact char none", "Remove roster contact character prefix." }, - { "contact indent <indent>", "Indent contact line by <indent> spaces (0 to 10)." }, - { "resource char <char>", "Prefix roster resources with specified character." }, - { "resource char none", "Remove roster resource character prefix." }, - { "resource indent <indent>", "Indent resource line by <indent> spaces (0 to 10)." }, - { "resource join on|off", "Join resource with previous line when only one available resource." }, - { "presence indent <indent>", "Indent presence line by <indent> spaces (-1 to 10), a value of -1 will show presence on the previous line." }, - { "size <precent>", "Percentage of the screen taken up by the roster (1-99)." }, - { "wrap on|off", "Enable or disable line wrapping in roster panel." }, - { "add <jid> [<nick>]", "Add a new item to the roster." }, - { "remove <jid>", "Removes an item from the roster." }, - { "remove_all contacts", "Remove all items from roster." }, - { "nick <jid> <nick>", "Change a contacts nickname." }, - { "clearnick <jid>", "Removes the current nickname." }) - CMD_EXAMPLES( - "/roster", - "/roster add someone@contacts.org", - "/roster add someone@contacts.org Buddy", - "/roster remove someone@contacts.org", - "/roster nick myfriend@chat.org My Friend", - "/roster clearnick kai@server.com", - "/roster size 15") - }, - - { "/blocked", - parse_args, 0, 2, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_blocked) - CMD_TAGS( - CMD_TAG_ROSTER, - CMD_TAG_CHAT) - CMD_SYN( - "/blocked", - "/blocked add [<jid>]", - "/blocked remove <jid>") - CMD_DESC( - "Manage blocked users, calling with no arguments shows the current list of blocked users.") - CMD_ARGS( - { "add [<jid>]", "Block the specified Jabber ID, if in a chat window, and not jid specified, the current recipient will be blocked." }, - { "remove <jid>", "Remove the specified Jabber ID from the blocked list." }) - CMD_EXAMPLES( - "/blocked add spammer@spam.org") - }, - - { "/group", - parse_args_with_freetext, 0, 3, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_group) - CMD_TAGS( - CMD_TAG_ROSTER, - CMD_TAG_UI) - CMD_SYN( - "/group", - "/group show <group>", - "/group add <group> <contat>", - "/group remove <group> <contact>") - CMD_DESC( - "View, add to, and remove from roster groups. " - "Passing no argument will list all roster groups.") - CMD_ARGS( - { "show <group>", "List all roster items a group." }, - { "add <group> <contact>", "Add a contact to a group." }, - { "remove <group> <contact>", "Remove a contact from a group." }) - CMD_EXAMPLES( - "/group", - "/group show friends", - "/group add friends newfriend@server.org", - "/group add family Brother", - "/group remove colleagues boss@work.com") - }, - - { "/info", - parse_args, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_info) - CMD_TAGS( - CMD_TAG_ROSTER, - CMD_TAG_CHAT, - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/info", - "/info <contact>|<nick>") - CMD_DESC( - "Show information about a contact, room, or room member. " - "Passing no argument in a chat window will use the current recipient. " - "Passing no argument in a chat room will display information about the room.") - CMD_ARGS( - { "<contact>", "The contact you wish to view information about." }, - { "<nick>", "When in a chat room, the occupant you wish to view information about." }) - CMD_EXAMPLES( - "/info mybuddy@chat.server.org", - "/info kai") - }, - - { "/caps", - parse_args, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_caps) - CMD_TAGS( - CMD_TAG_DISCOVERY, - CMD_TAG_CHAT, - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/caps", - "/caps <fulljid>|<nick>") - CMD_DESC( - "Find out a contacts, or room members client software capabilities. " - "If in private chat initiated from a chat room, no parameter is required.") - CMD_ARGS( - { "<fulljid>", "If in the console or a chat window, the full JID for which you wish to see capabilities." }, - { "<nick>", "If in a chat room, nickname for which you wish to see capabilities." }) - CMD_EXAMPLES( - "/caps mybuddy@chat.server.org/laptop", - "/caps mybuddy@chat.server.org/phone", - "/caps bruce") - }, - - { "/software", - parse_args, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_software) - CMD_TAGS( - CMD_TAG_DISCOVERY, - CMD_TAG_CHAT, - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/software", - "/software <fulljid>|<nick>") - CMD_DESC( - "Find out a contact, or room members software version information. " - "If in private chat initiated from a chat room, no parameter is required. " - "If the contact's software does not support software version requests, nothing will be displayed.") - CMD_ARGS( - { "<fulljid>", "If in the console or a chat window, the full JID for which you wish to see software information." }, - { "<nick>", "If in a chat room, nickname for which you wish to see software information." }) - CMD_EXAMPLES( - "/software mybuddy@chat.server.org/laptop", - "/software mybuddy@chat.server.org/phone", - "/software bruce") - }, - - { "/status", - parse_args, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_status) - CMD_TAGS( - CMD_TAG_CHAT, - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/status", - "/status <contact>|<nick>") - CMD_DESC( - "Find out a contact, or room members presence information. " - "If in a chat window the parameter is not required, the current recipient will be used.") - CMD_ARGS( - { "<contact>", "The contact who's presence you which to see." }, - { "<nick>", "If in a chat room, the occupant who's presence you wish to see." }) - CMD_EXAMPLES( - "/status buddy@server.com", - "/status jon") - }, - - { "/resource", - parse_args, 1, 2, &cons_resource_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_resource) - CMD_TAGS( - CMD_TAG_CHAT, - CMD_TAG_UI) - CMD_SYN( - "/resource set <resource>", - "/resource off", - "/resource title on|off", - "/resource message on|off") - CMD_DESC( - "Override chat session resource, and manage resource display settings.") - CMD_ARGS( - { "set <resource>", "Set the resource to which messages will be sent." }, - { "off", "Let the server choose which resource to route messages to." }, - { "title on|off", "Show or hide the current resource in the titlebar." }, - { "message on|off", "Show or hide the resource when showing an incoming message." }) - CMD_NOEXAMPLES - }, - - { "/join", - parse_args, 0, 5, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_join) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/join", - "/join <room> [nick <nick>] [password <password>]") - CMD_DESC( - "Join a chat room at the conference server. " - "If no room is supplied, a generated name will be used with the format private-chat-[UUID]. " - "If the domain part is not included in the room name, the account preference 'muc.service' will be used. " - "If no nickname is specified the account preference 'muc.nick' will be used which by default is the localpart of your JID. " - "If the room doesn't exist, and the server allows it, a new one will be created.") - CMD_ARGS( - { "<room>", "The chat room to join." }, - { "nick <nick>", "Nickname to use in the room." }, - { "password <password>", "Password if the room requires one." }) - CMD_EXAMPLES( - "/join", - "/join jdev@conference.jabber.org", - "/join jdev@conference.jabber.org nick mynick", - "/join private@conference.jabber.org nick mynick password mypassword", - "/join jdev") - }, - - { "/leave", - parse_args, 0, 0, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_leave) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/leave") - CMD_DESC( - "Leave the current chat room.") - CMD_NOARGS - CMD_NOEXAMPLES - }, - - { "/invite", - parse_args_with_freetext, 1, 2, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_invite) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/invite <contact> [<message>]") - CMD_DESC( - "Send an invite to a contact for the current chat room.") - CMD_ARGS( - { "<contact>", "The contact you wish to invite." }, - { "<message>", "An optional message to send with the invite." }) - CMD_NOEXAMPLES - }, - - { "/invites", - parse_args_with_freetext, 0, 0, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_invites) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/invites") - CMD_DESC( - "Show all rooms that you have been invited to, and not accepted or declined.") - CMD_NOARGS - CMD_NOEXAMPLES - }, - - { "/decline", - parse_args_with_freetext, 1, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_decline) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/decline <room>") - CMD_DESC( - "Decline a chat room invitation.") - CMD_ARGS( - { "<room>", "The room for the invite you wish to decline." }) - CMD_NOEXAMPLES - }, - - { "/room", - parse_args, 1, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_room) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/room accept|destroy|config") - CMD_DESC( - "Chat room configuration.") - CMD_ARGS( - { "accept", "Accept default room configuration." }, - { "destroy", "Reject default room configuration, and destroy the room." }, - { "config", "Edit room configuration." }) - CMD_NOEXAMPLES - }, - - { "/kick", - parse_args_with_freetext, 1, 2, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_kick) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/kick <nick> [<reason>]") - CMD_DESC( - "Kick occupant from chat room.") - CMD_ARGS( - { "<nick>", "Nickname of the occupant to kick from the room." }, - { "<reason>", "Optional reason for kicking the occupant." }) - CMD_NOEXAMPLES - }, - - { "/ban", - parse_args_with_freetext, 1, 2, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_ban) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/ban <jid> [<reason>]") - CMD_DESC( - "Ban user from chat room.") - CMD_ARGS( - { "<jid>", "Bare JID of the user to ban from the room." }, - { "<reason>", "Optional reason for banning the user." }) - CMD_NOEXAMPLES - }, - - { "/subject", - parse_args_with_freetext, 0, 2, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_subject) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/subject set <subject>", - "/subject edit <subject>", - "/subject prepend <text>", - "/subject append <text>", - "/subject clear") - CMD_DESC( - "Set, modify, or clear room subject.") - CMD_ARGS( - { "set <subject>", "Set the room subject." }, - { "edit <subject>", "Edit the current room subject, tab autocompletion will display the subject to edit." }, - { "prepend <text>", "Prepend text to the current room subject, use double quotes if a trailing space is needed." }, - { "append <text>", "Append text to the current room subject, use double quotes if a preceding space is needed." }, - { "clear", "Clear the room subject." }) - CMD_NOEXAMPLES - }, - - { "/affiliation", - parse_args_with_freetext, 1, 4, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_affiliation) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/affiliation set <affiliation> <jid> [<reason>]", - "/affiliation list [<affiliation>]") - CMD_DESC( - "Manage room affiliations. " - "Affiliation may be one of owner, admin, member, outcast or none.") - CMD_ARGS( - { "set <affiliation> <jid> [<reason>]", "Set the affiliation of user with jid, with an optional reason." }, - { "list [<affiliation>]", "List all users with the specified affiliation, or all if none specified." }) - CMD_NOEXAMPLES - }, - - { "/role", - parse_args_with_freetext, 1, 4, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_role) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/role set <role> <nick> [<reason>]", - "/role list [<role>]") - CMD_DESC( - "Manage room roles. " - "Role may be one of moderator, participant, visitor or none.") - CMD_ARGS( - { "set <role> <nick> [<reason>]", "Set the role of occupant with nick, with an optional reason." }, - { "list [<role>]", "List all occupants with the specified role, or all if none specified." }) - CMD_NOEXAMPLES - }, - - { "/occupants", - parse_args, 1, 3, cons_occupants_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_occupants) - CMD_TAGS( - CMD_TAG_GROUPCHAT, - CMD_TAG_UI) - CMD_SYN( - "/occupants show|hide [jid]", - "/occupants default show|hide [jid]", - "/occupants size [<percent>]") - CMD_DESC( - "Show or hide room occupants, and occupants panel display settings.") - CMD_ARGS( - { "show", "Show the occupants panel in current room." }, - { "hide", "Hide the occupants panel in current room." }, - { "show jid", "Show jid in the occupants panel in current room." }, - { "hide jid", "Hide jid in the occupants panel in current room." }, - { "default show|hide", "Whether occupants are shown by default in new rooms." }, - { "default show|hide jid", "Whether occupants jids are shown by default in new rooms." }, - { "size <percent>", "Percentage of the screen taken by the occupants list in rooms (1-99)." }) - CMD_NOEXAMPLES - }, - - { "/form", - parse_args, 1, 2, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_form) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/form show", - "/form submit", - "/form cancel", - "/form help [<tag>]") - CMD_DESC( - "Form configuration.") - CMD_ARGS( - { "show", "Show the current form." }, - { "submit", "Submit the current form." }, - { "cancel", "Cancel changes to the current form." }, - { "help [<tag>]", "Display help for form, or a specific field." }) - CMD_NOEXAMPLES - }, - - { "/rooms", - parse_args, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_rooms) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/rooms [<service>]") - CMD_DESC( - "List the chat rooms available at the specified conference service. " - "If no argument is supplied, the account preference 'muc.service' is used, 'conference.<domain-part>' by default.") - CMD_ARGS( - { "<service>", "The conference service to query." }) - CMD_EXAMPLES( - "/rooms conference.jabber.org") - }, - - { "/bookmark", - parse_args, 0, 8, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_bookmark) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/bookmark", - "/bookmark list", - "/bookmark add <room> [nick <nick>] [password <password>] [autojoin on|off]", - "/bookmark update <room> [nick <nick>] [password <password>] [autojoin on|off]", - "/bookmark remove <room>", - "/bookmark join <room>") - CMD_DESC( - "Manage bookmarks and join bookmarked rooms. " - "In a chat room, no arguments will bookmark the current room, setting autojoin to \"on\".") - CMD_ARGS( - { "list", "List all bookmarks." }, - { "add <room>", "Add a bookmark." }, - { "remove <room>", "Remove a bookmark." }, - { "update <room>", "Update the properties associated with a bookmark." }, - { "nick <nick>", "Nickname used in the chat room." }, - { "password <password>", "Password if required, may be stored in plaintext on your server." }, - { "autojoin on|off", "Whether to join the room automatically on login." }, - { "join <room>", "Join room using the properties associated with the bookmark." }) - CMD_NOEXAMPLES - }, - - { "/disco", - parse_args, 1, 2, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_disco) - CMD_TAGS( - CMD_TAG_DISCOVERY) - CMD_SYN( - "/disco info [<jid>]", - "/disco items [<jid>]") - CMD_DESC( - "Find out information about an entities supported services. " - "Calling with no arguments will query the server you are currently connected to.") - CMD_ARGS( - { "info [<jid>]", "List protocols and features supported by an entity." }, - { "items [<jid>]", "List items associated with an entity." }) - CMD_EXAMPLES( - "/disco info", - "/disco items myserver.org", - "/disco items conference.jabber.org", - "/disco info myfriend@server.com/laptop") - }, - - { "/sendfile", - parse_args_with_freetext, 1, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_sendfile) - CMD_TAGS( - CMD_TAG_CHAT, - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/sendfile <file>") - CMD_DESC( - "Send a file using XEP-0363 HTTP file transfer.") - CMD_ARGS( - { "<file>", "Path to the file." }) - CMD_EXAMPLES( - "/sendfile /etc/hosts", - "/sendfile ~/images/sweet_cat.jpg") - }, - - { "/lastactivity", - parse_args, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_lastactivity) - CMD_TAGS( - CMD_TAG_PRESENCE) - CMD_SYN( - "/lastactivity on|off", - "/lastactivity [<jid>]") - CMD_DESC( - "Enable/disable sending last activity, and send last activity requests.") - CMD_ARGS( - { "on|off", "Enable or disable sending of last activity." }, - { "<jid>", "The JID of the entity to query, omitting the JID will query your server." }) - CMD_EXAMPLES( - "/lastactivity", - "/lastactivity off", - "/lastactivity alice@securechat.org", - "/lastactivity alice@securechat.org/laptop", - "/lastactivity someserver.com") - }, - - { "/nick", - parse_args_with_freetext, 1, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_nick) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/nick <nickname>") - CMD_DESC( - "Change your nickname in the current chat room.") - CMD_ARGS( - { "<nickname>", "Your new nickname." }) - CMD_NOEXAMPLES - }, - - { "/win", - parse_args, 1, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_win) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/win console", - "/win <num>", - "/win <barejid>", - "/win <nick>", - "/win <roomjid>", - "/win <roomoccupantjid>", - "/win xmlconsole") - CMD_DESC( - "Move to the specified window.") - CMD_ARGS( - { "console", "Go to the Console window." }, - { "<num>", "Go to specified window number." }, - { "<barejid>", "Go to chat window with contact by JID if open." }, - { "<nick>", "Go to chat window with contact by nickname if open." }, - { "<roomjid>", "Go to chat room window with roomjid if open." }, - { "<roomoccupantjid>", "Go to private chat roomoccupantjid if open." }, - { "xmlconsole", "Go to the XML Console window if open." }) - CMD_EXAMPLES( - "/win console", - "/win 4", - "/win friend@chat.org", - "/win Eddie", - "/win bigroom@conference.chat.org", - "/win bigroom@conference.chat.org/bruce") - }, - - { "/wins", - parse_args, 0, 3, NULL, - CMD_SUBFUNCS( - { "unread", cmd_wins_unread }, - { "tidy", cmd_wins_tidy }, - { "prune", cmd_wins_prune }, - { "swap", cmd_wins_swap }, - { "autotidy", cmd_wins_autotidy }) - CMD_MAINFUNC(cmd_wins) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/wins", - "/wins unread", - "/wins tidy", - "/wins autotidy on|off", - "/wins prune", - "/wins swap <source> <target>") - CMD_DESC( - "Manage windows. " - "Passing no argument will list all currently active windows and information about their usage.") - CMD_ARGS( - { "unread", "List windows with unread messages." }, - { "tidy", "Move windows so there are no gaps." }, - { "autotidy on|off", "Automatically remove gaps when closing windows." }, - { "prune", "Close all windows with no unread messages, and then tidy so there are no gaps." }, - { "swap <source> <target>", "Swap windows, target may be an empty position." }) - CMD_NOEXAMPLES - }, - - { "/sub", - parse_args, 1, 2, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_sub) - CMD_TAGS( - CMD_TAG_ROSTER) - CMD_SYN( - "/sub request [<jid>]", - "/sub allow [<jid>]", - "/sub deny [<jid>]", - "/sub show [<jid>]", - "/sub sent", - "/sub received") - CMD_DESC( - "Manage subscriptions to contact presence. " - "If jid is omitted, the contact of the current window is used.") - CMD_ARGS( - { "request [<jid>]", "Send a subscription request to the user." }, - { "allow [<jid>]", "Approve a contact's subscription request." }, - { "deny [<jid>]", "Remove subscription for a contact, or deny a request." }, - { "show [<jid>]", "Show subscription status for a contact." }, - { "sent", "Show all sent subscription requests pending a response." }, - { "received", "Show all received subscription requests awaiting your response." }) - CMD_EXAMPLES( - "/sub request myfriend@jabber.org", - "/sub allow myfriend@jabber.org", - "/sub request", - "/sub sent") - }, - - { "/tiny", - parse_args, 1, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_tiny) - CMD_TAGS( - CMD_TAG_CHAT, - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/tiny <url>") - CMD_DESC( - "Send url as tinyurl in current chat.") - CMD_ARGS( - { "<url>", "The url to make tiny." }) - CMD_EXAMPLES( - "Example: /tiny http://www.profanity.im") - }, - - { "/who", - parse_args, 0, 2, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_who) - CMD_TAGS( - CMD_TAG_CHAT, - CMD_TAG_GROUPCHAT, - CMD_TAG_ROSTER) - CMD_SYN( - "/who", - "/who online|offline|away|dnd|xa|chat|available|unavailable|any [<group>]", - "/who moderator|participant|visitor", - "/who owner|admin|member") - CMD_DESC( - "Show contacts or room occupants with chosen status, role or affiliation") - CMD_ARGS( - { "offline|away|dnd|xa|chat", "Show contacts or room occupants with specified presence." }, - { "online", "Contacts that are online, chat, away, xa, dnd." }, - { "available", "Contacts that are available for chat - online, chat." }, - { "unavailable", "Contacts that are not available for chat - offline, away, xa, dnd." }, - { "any", "Contacts with any status (same as calling with no argument)." }, - { "<group>", "Filter the results by the specified roster group, not applicable in chat rooms." }, - { "moderator|participant|visitor", "Room occupants with the specified role." }, - { "owner|admin|member", "Room occupants with the specified affiliation." }) - CMD_EXAMPLES( - "/who", - "/who xa", - "/who online friends", - "/who any family", - "/who participant", - "/who admin") - }, - - { "/close", - parse_args, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_close) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/close", - "/close <num>", - "/close <barejid>", - "/close <nick>", - "/close <roomjid>", - "/close <roomoccupantjid>", - "/close xmlconsole", - "/close all|read") - CMD_DESC( - "Close windows. " - "Passing no argument closes the current window.") - CMD_ARGS( - { "<num>", "Close specified window number." }, - { "<barejid>", "Close chat window with contact by JID if open." }, - { "<nick>", "Close chat window with contact by nickname if open." }, - { "<roomjid>", "Close chat room window with roomjid if open." }, - { "<roomoccupantjid>", "Close private chat roomoccupantjid if open." }, - { "xmlconsole", "Close the XML Console window if open." }, - { "all", "Close all windows." }, - { "read", "Close all windows that have no unread messages." }) - CMD_NOEXAMPLES - }, - - { "/clear", - parse_args, 0, 0, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_clear) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/clear") - CMD_DESC( - "Clear the current window.") - CMD_NOARGS - CMD_NOEXAMPLES - }, - - { "/quit", - parse_args, 0, 0, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_quit) - CMD_NOTAGS - CMD_SYN( - "/quit") - CMD_DESC( - "Logout of any current session, and quit Profanity.") - CMD_NOARGS - CMD_NOEXAMPLES - }, - - { "/privileges", - parse_args, 1, 1, &cons_privileges_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_privileges) - CMD_TAGS( - CMD_TAG_GROUPCHAT, - CMD_TAG_UI) - CMD_SYN( - "/privileges on|off") - CMD_DESC( - "Group occupants panel by role, and show role information in chat rooms.") - CMD_ARGS( - { "on|off", "Enable or disable privilege information." }) - CMD_NOEXAMPLES - }, - - { "/charset", - parse_args, 0, 0, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_charset) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/charset") - CMD_DESC( - "Display information about the current character set supported by the terminal. ") - CMD_NOARGS - CMD_NOEXAMPLES - }, - - { "/beep", - parse_args, 1, 1, &cons_beep_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_beep) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/beep on|off") - CMD_DESC( - "Switch the terminal bell on or off. " - "The bell will sound when incoming messages are received. " - "If the terminal does not support sounds, it may attempt to flash the screen instead.") - CMD_ARGS( - { "on|off", "Enable or disable terminal bell." }) - CMD_NOEXAMPLES - }, - - { "/console", - parse_args, 2, 2, &cons_console_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_console) - CMD_TAGS( - CMD_TAG_UI, - CMD_TAG_CHAT, - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/console chat all|first|none", - "/console muc all|first|none", - "/console private all|first|none") - CMD_DESC( - "Configure what is displayed in the console window when messages are received. " - "The default is set to 'all' for all types of messages.") - CMD_ARGS( - { "chat all", "Indicate all new chat messages in the console." }, - { "chat first", "Indicate only the first new message per chat in the console." }, - { "chat none", "Do not show any new chat messages in the console window." }, - { "muc all", "Indicate all new chat room messages in the console." }, - { "muc first", "Indicate only the first new message in each room in the console." }, - { "muc none", "Do not show any new chat room messages in the console window." }, - { "private all", "Indicate all new private room messages in the console." }, - { "private first", "Indicate only the first private room message in the console." }, - { "private none", "Do not show any new private room messages in the console window." }) - CMD_NOEXAMPLES - }, - - { "/encwarn", - parse_args, 1, 1, &cons_encwarn_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_encwarn) - CMD_TAGS( - CMD_TAG_CHAT, - CMD_TAG_UI) - CMD_SYN( - "/encwarn on|off") - CMD_DESC( - "Titlebar encryption warning.") - CMD_ARGS( - { "on|off", "Enable or disable the unencrypted warning message in the titlebar." }) - CMD_NOEXAMPLES - }, - - { "/presence", - parse_args, 1, 1, &cons_presence_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_presence) - CMD_TAGS( - CMD_TAG_UI, - CMD_TAG_CHAT) - CMD_SYN( - "/presence on|off") - CMD_DESC( - "Show the contacts presence in the titlebar.") - CMD_ARGS( - { "on|off", "Switch display of the contacts presence in the titlebar on or off." }) - CMD_NOEXAMPLES - }, - - { "/wrap", - parse_args, 1, 1, &cons_wrap_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_wrap) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/wrap on|off") - CMD_DESC( - "Word wrapping.") - CMD_ARGS( - { "on|off", "Enable or disable word wrapping in the main window." }) - CMD_NOEXAMPLES - }, - - { "/time", - parse_args, 1, 3, &cons_time_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_time) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/time console|chat|muc|mucconfig|private|xml set <format>", - "/time console|chat|muc|mucconfig|private|xml off", - "/time statusbar set <format>", - "/time statusbar off", - "/time lastactivity set <format>") - CMD_DESC( - "Configure time display preferences. " - "Time formats are strings supported by g_date_time_format. " - "See https://developer.gnome.org/glib/stable/glib-GDateTime.html#g-date-time-format for more details. " - "Setting the format to an unsupported string, will display the string. " - "If the format contains spaces, it must be surrounded with double quotes.") - CMD_ARGS( - { "console set <format>", "Set time format for console window." }, - { "console off", "Do not show time in console window." }, - { "chat set <format>", "Set time format for chat windows." }, - { "chat off", "Do not show time in chat windows." }, - { "muc set <format>", "Set time format for chat room windows." }, - { "muc off", "Do not show time in chat room windows." }, - { "mucconfig set <format>", "Set time format for chat room config windows." }, - { "mucconfig off", "Do not show time in chat room config windows." }, - { "private set <format>", "Set time format for private chat windows." }, - { "private off", "Do not show time in private chat windows." }, - { "xml set <format>", "Set time format for XML console window." }, - { "xml off", "Do not show time in XML console window." }, - { "statusbar set <format>", "Change time format in statusbar." }, - { "statusbar off", "Do not show time in status bar." }, - { "lastactivity set <format>", "Change time format for last activity." }) - CMD_EXAMPLES( - "/time console set %H:%M:%S", - "/time chat set \"%d-%m-%y %H:%M:%S\"", - "/time xml off", - "/time statusbar set %H:%M", - "/time lastactivity set \"%d-%m-%y %H:%M:%S\"") - }, - - { "/inpblock", - parse_args, 2, 2, &cons_inpblock_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_inpblock) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/inpblock timeout <millis>", - "/inpblock dynamic on|off") - CMD_DESC( - "How long to wait for keyboard input before checking for new messages or checking for state changes such as 'idle'.") - CMD_ARGS( - { "timeout <millis>", "Time to wait (1-1000) in milliseconds before reading input from the terminal buffer, default: 1000." }, - { "dynamic on|off", "Start with 0 millis and dynamically increase up to timeout when no activity, default: on." }) - CMD_NOEXAMPLES - }, - - { "/notify", - parse_args_with_freetext, 0, 4, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_notify) - CMD_TAGS( - CMD_TAG_UI, - CMD_TAG_CHAT, - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/notify chat on|off", - "/notify chat current on|off", - "/notify chat text on|off", - "/notify room on|off", - "/notify room mention on|off", - "/notify room mention case_sensitive|case_insensitive", - "/notify room mention word_whole|word_part", - "/notify room current on|off", - "/notify room text on|off", - "/notify room trigger add <text>", - "/notify room trigger remove <text>", - "/notify room trigger list", - "/notify room trigger on|off", - "/notify on|off", - "/notify mention on|off", - "/notify trigger on|off", - "/notify reset", - "/notify remind <seconds>", - "/notify typing on|off", - "/notify typing current on|off", - "/notify invite on|off", - "/notify sub on|off") - CMD_DESC( - "Settings for various kinds of desktop notifications.") - CMD_ARGS( - { "chat on|off", "Notifications for regular chat messages." }, - { "chat current on|off", "Whether to show regular chat message notifications when the window is focussed." }, - { "chat text on|off", "Show message text in regular message notifications." }, - { "room on|off", "Notifications for all chat room messages, 'mention' only notifies when your nick is mentioned." }, - { "room mention on|off", "Notifications for all chat room messages when your nick is mentioned." }, - { "room mention case_sensitive", "Set room mention notifications as case sensitive." }, - { "room mention case_insensitive", "Set room mention notifications as case insensitive." }, - { "room mention word_whole", "Set room mention notifications only on whole word match, i.e. when nickname is not part of a larger word." }, - { "room mention word_part", "Set room mention notifications on partial word match, i.e. nickname may be part of a larger word." }, - { "room current on|off", "Whether to show all chat room messages notifications when the window is focussed." }, - { "room text on|off", "Show message text in chat room message notifications." }, - { "room trigger add <text>", "Notify when specified text included in all chat room messages." }, - { "room trigger remove <text>", "Remove chat room notification trigger." }, - { "room trigger list", "List all chat room triggers." }, - { "room trigger on|off", "Enable or disable all chat room notification triggers." }, - { "on|off", "Override the global message setting for the current chat room." }, - { "mention on|off", "Override the global 'mention' setting for the current chat room." }, - { "trigger on|off", "Override the global 'trigger' setting for the current chat room." }, - { "reset", "Reset to global notification settings for the current chat room." }, - { "remind <seconds>", "Notification reminder period for unread messages, use 0 to disable." }, - { "typing on|off", "Notifications when contacts are typing." }, - { "typing current on|off", "Whether typing notifications are triggered for the current window." }, - { "invite on|off", "Notifications for chat room invites." }, - { "sub on|off", "Notifications for subscription requests." }) - CMD_EXAMPLES( - "/notify chat on", - "/notify chat text on", - "/notify room mention on", - "/notify room trigger add beer", - "/notify room trigger on", - "/notify room current off", - "/notify room text off", - "/notify remind 60", - "/notify typing on", - "/notify invite on") - }, - - { "/flash", - parse_args, 1, 1, &cons_flash_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_flash) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/flash on|off") - CMD_DESC( - "Make the terminal flash when incoming messages are received in another window. " - "If the terminal doesn't support flashing, it may attempt to beep.") - CMD_ARGS( - { "on|off", "Enable or disable terminal flash." }) - CMD_NOEXAMPLES - }, - - { "/tray", - parse_args, 1, 2, &cons_tray_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_tray) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/tray on|off", - "/tray read on|off", - "/tray timer <seconds>") - CMD_DESC( - "Display an icon in the tray that will indicate new messages.") - CMD_ARGS( - { "on|off", "Show tray icon." }, - { "read on|off", "Show tray icon when no unread messages." }, - { "timer <seconds>", "Set tray icon timer, seconds must be between 1-10" }) - CMD_NOEXAMPLES - }, - - { "/intype", - parse_args, 1, 1, &cons_intype_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_intype) - CMD_TAGS( - CMD_TAG_UI, - CMD_TAG_CHAT) - CMD_SYN( - "/intype on|off") - CMD_DESC( - "Show when a contact is typing in the console, and in active message window.") - CMD_ARGS( - { "on|off", "Enable or disable contact typing messages." }) - CMD_NOEXAMPLES - }, - - { "/splash", - parse_args, 1, 1, &cons_splash_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_splash) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/splash on|off") - CMD_DESC( - "Switch on or off the ascii logo on start up and when the /about command is called.") - CMD_ARGS( - { "on|off", "Enable or disable splash logo." }) - CMD_NOEXAMPLES - }, - - { "/autoconnect", - parse_args, 1, 2, &cons_autoconnect_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_autoconnect) - CMD_TAGS( - CMD_TAG_CONNECTION) - CMD_SYN( - "/autoconnect set <account>", - "/autoconnect off") - CMD_DESC( - "Enable or disable autoconnect on start up. " - "The setting can be overridden by the -a (--account) command line option.") - CMD_ARGS( - { "set <account>", "Connect with account on start up." }, - { "off", "Disable autoconnect." }) - CMD_EXAMPLES( - "/autoconnect set jc@stuntteam.org", - "/autoconnect off") - }, - - { "/vercheck", - parse_args, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_vercheck) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/vercheck on|off") - CMD_DESC( - "Check for new versions when Profanity starts, and when the /about command is run.") - CMD_ARGS( - { "on|off", "Enable or disable the version check." }) - CMD_NOEXAMPLES - }, - - { "/titlebar", - parse_args, 2, 2, &cons_titlebar_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_titlebar) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/titlebar show on|off", - "/titlebar goodbye on|off") - CMD_DESC( - "Allow Profanity to modify the window title bar.") - CMD_ARGS( - { "show on|off", "Show current logged in user, and unread messages as the window title." }, - { "goodbye on|off", "Show a message in the title when exiting profanity." }) - CMD_NOEXAMPLES - }, - - { "/alias", - parse_args_with_freetext, 1, 3, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_alias) - CMD_NOTAGS - CMD_SYN( - "/alias list", - "/alias add <name> <value>", - "/alias remove <name>") - CMD_DESC( - "Add, remove or list command aliases.") - CMD_ARGS( - { "list", "List all aliases." }, - { "add <name> <value>", "Add a new command alias." }, - { "remove <name>", "Remove a command alias." }) - CMD_EXAMPLES( - "/alias add friends /who online friends", - "/alias add /q /quit", - "/alias a /away \"I'm in a meeting.\"", - "/alias remove q", - "/alias list") - }, - - { "/chlog", - parse_args, 1, 1, &cons_chlog_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_chlog) - CMD_TAGS( - CMD_TAG_CHAT) - CMD_SYN( - "/chlog on|off") - CMD_DESC( - "Switch chat logging on or off. " - "This setting will be enabled if /history is set to on. " - "When disabling this option, /history will also be disabled. " - "See the /grlog setting for enabling logging of chat room (groupchat) messages.") - CMD_ARGS( - { "on|off", "Enable or disable chat logging." }) - CMD_NOEXAMPLES - }, - - { "/grlog", - parse_args, 1, 1, &cons_grlog_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_grlog) - CMD_TAGS( - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/grlog on|off") - CMD_DESC( - "Switch chat room logging on or off. " - "See the /chlog setting for enabling logging of one to one chat.") - CMD_ARGS( - { "on|off", "Enable or disable chat room logging." }) - CMD_NOEXAMPLES - }, - - { "/states", - parse_args, 1, 1, &cons_states_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_states) - CMD_TAGS( - CMD_TAG_CHAT) - CMD_SYN( - "/states on|off") - CMD_DESC( - "Send chat state notifications to recipient during chat sessions, such as typing, paused, active, gone.") - CMD_ARGS( - { "on|off", "Enable or disable sending of chat state notifications." }) - CMD_NOEXAMPLES - }, - - { "/pgp", - parse_args, 1, 3, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_pgp) - CMD_TAGS( - CMD_TAG_CHAT, - CMD_TAG_UI) - CMD_SYN( - "/pgp libver", - "/pgp keys", - "/pgp contacts", - "/pgp setkey <contact> <keyid>", - "/pgp start [<contact>]", - "/pgp end", - "/pgp log on|off|redact", - "/pgp char <char>") - CMD_DESC( - "Open PGP commands to manage keys, and perform PGP encryption during chat sessions. " - "See the /account command to set your own PGP key.") - CMD_ARGS( - { "libver", "Show which version of the libgpgme library is being used." }, - { "keys", "List all keys known to the system." }, - { "contacts", "Show contacts with assigned public keys." }, - { "setkey <contact> <keyid>", "Manually associate a contact with a public key." }, - { "start [<contact>]", "Start PGP encrypted chat, current contact will be used if not specified." }, - { "end", "End PGP encrypted chat with the current recipient." }, - { "log on|off", "Enable or disable plaintext logging of PGP encrypted messages." }, - { "log redact", "Log PGP encrypted messages, but replace the contents with [redacted]. This is the default." }, - { "char <char>", "Set the character to be displayed next to PGP encrypted messages." }) - CMD_EXAMPLES( - "/pgp log off", - "/pgp setkey buddy@buddychat.org BA19CACE5A9592C5", - "/pgp start buddy@buddychat.org", - "/pgp end", - "/pgp char P") - }, - - { "/otr", - parse_args, 1, 3, NULL, - CMD_SUBFUNCS( - { "char", cmd_otr_char }, - { "log", cmd_otr_log }, - { "libver", cmd_otr_libver }, - { "policy", cmd_otr_policy }, - { "gen", cmd_otr_gen }, - { "myfp", cmd_otr_myfp }, - { "theirfp", cmd_otr_theirfp }, - { "start", cmd_otr_start }, - { "end", cmd_otr_end }, - { "trust", cmd_otr_trust }, - { "untrust", cmd_otr_untrust }, - { "secret", cmd_otr_secret }, - { "question", cmd_otr_question }, - { "answer", cmd_otr_answer }) - CMD_NOMAINFUNC - CMD_TAGS( - CMD_TAG_CHAT, - CMD_TAG_UI) - CMD_SYN( - "/otr libver", - "/otr gen", - "/otr myfp|theirfp", - "/otr start [<contact>]", - "/otr end", - "/otr trust|untrust", - "/otr secret <secret>", - "/otr question <question> <answer>", - "/otr answer <answer>", - "/otr policy manual|opportunistic|always [<contact>]", - "/otr log on|off|redact", - "/otr char <char>") - CMD_DESC( - "Off The Record (OTR) commands to manage keys, and perform OTR encryption during chat sessions.") - CMD_ARGS( - { "libver", "Show which version of the libotr library is being used." }, - { "gen", "Generate your private key." }, - { "myfp", "Show your fingerprint." }, - { "theirfp", "Show contacts fingerprint." }, - { "start [<contact>]", "Start an OTR session with contact, or current recipient if omitted." }, - { "end", "End the current OTR session," }, - { "trust|untrust", "Indicate whether or not you trust the contact's fingerprint." }, - { "secret <secret>", "Verify a contact's identity using a shared secret." }, - { "question <question> <answer>", "Verify a contact's identity using a question and expected answer." }, - { "answer <answer>", "Respond to a question answer verification request with your answer." }, - { "policy manual", "Set the global OTR policy to manual, OTR sessions must be started manually." }, - { "policy manual <contact>", "Set the OTR policy to manual for a specific contact." }, - { "policy opportunistic", "Set the global OTR policy to opportunistic, an OTR session will be attempted upon starting a conversation." }, - { "policy opportunistic <contact>", "Set the OTR policy to opportunistic for a specific contact." }, - { "policy always", "Set the global OTR policy to always, an error will be displayed if an OTR session cannot be initiated upon starting a conversation." }, - { "policy always <contact>", "Set the OTR policy to always for a specific contact." }, - { "log on|off", "Enable or disable plaintext logging of OTR encrypted messages." }, - { "log redact", "Log OTR encrypted messages, but replace the contents with [redacted]. This is the default." }, - { "char <char>", "Set the character to be displayed next to OTR encrypted messages." }) - CMD_EXAMPLES( - "/otr log off", - "/otr policy manual", - "/otr policy opportunistic mrfriend@workchat.org", - "/otr gen", - "/otr start buddy@buddychat.org", - "/otr myfp", - "/otr theirfp", - "/otr question \"What is the name of my rabbit?\" fiffi", - "/otr end", - "/otr char *") - }, - - { "/outtype", - parse_args, 1, 1, &cons_outtype_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_outtype) - CMD_TAGS( - CMD_TAG_CHAT) - CMD_SYN( - "/outtype on|off") - CMD_DESC( - "Send typing notifications, chat states (/states) will be enabled if this setting is enabled.") - CMD_ARGS( - { "on|off", "Enable or disable sending typing notifications." }) - CMD_NOEXAMPLES - }, - - { "/gone", - parse_args, 1, 1, &cons_gone_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_gone) - CMD_TAGS( - CMD_TAG_CHAT) - CMD_SYN( - "/gone <minutes>") - CMD_DESC( - "Send a 'gone' state to the recipient after the specified number of minutes. " - "Chat states (/states) will be enabled if this setting is set.") - CMD_ARGS( - { "<minutes>", "Number of minutes of inactivity before sending the 'gone' state, a value of 0 will disable sending this state." }) - CMD_NOEXAMPLES - }, - - { "/history", - parse_args, 1, 1, &cons_history_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_history) - CMD_TAGS( - CMD_TAG_UI, - CMD_TAG_CHAT) - CMD_SYN( - "/history on|off") - CMD_DESC( - "Switch chat history on or off, /chlog will automatically be enabled when this setting is on. " - "When history is enabled, previous messages are shown in chat windows.") - CMD_ARGS( - { "on|off", "Enable or disable showing chat history." }) - CMD_NOEXAMPLES - }, - - { "/log", - parse_args, 1, 2, &cons_log_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_log) - CMD_NOTAGS - CMD_SYN( - "/log where", - "/log rotate on|off", - "/log maxsize <bytes>", - "/log shared on|off") - CMD_DESC( - "Manage profanity log settings.") - CMD_ARGS( - { "where", "Show the current log file location." }, - { "rotate on|off", "Rotate log, default on." }, - { "maxsize <bytes>", "With rotate enabled, specifies the max log size, defaults to 1048580 (1MB)." }, - { "shared on|off", "Share logs between all instances, default: on. When off, the process id will be included in the log." }) - CMD_NOEXAMPLES - }, - - { "/carbons", - parse_args, 1, 1, &cons_carbons_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_carbons) - CMD_TAGS( - CMD_TAG_CHAT) - CMD_SYN( - "/carbons on|off") - CMD_DESC( - "Enable or disable message carbons. " - "Message carbons ensure that both sides of all conversations are shared with all the user's clients that implement this protocol.") - CMD_ARGS( - { "on|off", "Enable or disable message carbons." }) - CMD_NOEXAMPLES - }, - - { "/receipts", - parse_args, 2, 2, &cons_receipts_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_receipts) - CMD_TAGS( - CMD_TAG_CHAT) - CMD_SYN( - "/receipts request on|off", - "/receipts send on|off") - CMD_DESC( - "Enable or disable message delivery receipts. The interface will indicate when a message has been received.") - CMD_ARGS( - { "request on|off", "Whether or not to request a receipt upon sending a message." }, - { "send on|off", "Whether or not to send a receipt if one has been requested with a received message." }) - CMD_NOEXAMPLES - }, - - { "/reconnect", - parse_args, 1, 1, &cons_reconnect_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_reconnect) - CMD_TAGS( - CMD_TAG_CONNECTION) - CMD_SYN( - "/reconnect <seconds>") - CMD_DESC( - "Set the reconnect attempt interval for when the connection is lost.") - CMD_ARGS( - { "<seconds>", "Number of seconds before attempting to reconnect, a value of 0 disables reconnect." }) - CMD_NOEXAMPLES - }, - - { "/autoping", - parse_args, 2, 2, &cons_autoping_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_autoping) - CMD_TAGS( - CMD_TAG_CONNECTION) - CMD_SYN( - "/autoping set <seconds>", - "/autoping timeout <seconds>") - CMD_DESC( - "Set the interval between sending ping requests to the server to ensure the connection is kept alive.") - CMD_ARGS( - { "set <seconds>", "Number of seconds between sending pings, a value of 0 disables autoping." }, - { "timeout <seconds>", "Seconds to wait for autoping responses, after which the connection is considered broken." }) - CMD_NOEXAMPLES - }, - - { "/ping", - parse_args, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_ping) - CMD_TAGS( - CMD_TAG_CONNECTION) - CMD_SYN( - "/ping [<jid>]") - CMD_DESC( - "Sends an IQ ping stanza to the specified JID. " - "If no JID is supplied, your chat server will be pinged.") - CMD_ARGS( - { "<jid>", "The Jabber ID to send the ping request to." }) - CMD_NOEXAMPLES - }, - - { "/autoaway", - parse_args_with_freetext, 2, 3, &cons_autoaway_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_autoaway) - CMD_TAGS( - CMD_TAG_PRESENCE) - CMD_SYN( - "/autoaway mode idle|away|off", - "/autoaway time away|xa <minutes>", - "/autoaway message away|xa <message>|off", - "/autoaway check on|off") - CMD_DESC( - "Manage autoway settings for idle time.") - CMD_ARGS( - { "mode idle", "Sends idle time, status remains online." }, - { "mode away", "Sends away and xa presence as well as idle time." }, - { "mode off", "Disabled (default)." }, - { "time away <minutes>", "Number of minutes before the away presence is sent, default: 15." }, - { "time xa <minutes>", "Number of minutes before the xa presence is sent, default: 0 (disabled)." }, - { "message away <message>", "Optional message to send with the away presence, default: off (disabled)." }, - { "message xa <message>", "Optional message to send with the xa presence, default: off (disabled)." }, - { "message away off", "Send no message with away presence." }, - { "message xa off", "Send no message with xa presence." }, - { "check on|off", "When enabled, checks for activity and sends online presence, default: on." }) - CMD_EXAMPLES( - "/autoaway mode away", - "/autoaway time away 30", - "/autoaway message away Away from computer for a while", - "/autoaway time xa 120", - "/autoaway message xa Away from computer for a very long time", - "/autoaway check off") - }, - - { "/priority", - parse_args, 1, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_priority) - CMD_TAGS( - CMD_TAG_PRESENCE) - CMD_SYN( - "/priority <priority>") - CMD_DESC( - "Set priority for the current account. " - "See the /account command for specific priority settings per presence status.") - CMD_ARGS( - { "<priority>", "Number between -128 and 127, default: 0." }) - CMD_NOEXAMPLES - }, - - { "/account", - parse_args, 0, 4, NULL, - CMD_SUBFUNCS( - { "list", cmd_account_list }, - { "show", cmd_account_show }, - { "add", cmd_account_add }, - { "remove", cmd_account_remove }, - { "enable", cmd_account_enable }, - { "disable", cmd_account_disable }, - { "rename", cmd_account_rename }, - { "default", cmd_account_default }, - { "set", cmd_account_set }, - { "clear", cmd_account_clear }) - CMD_MAINFUNC(cmd_account) - CMD_TAGS( - CMD_TAG_CONNECTION - CMD_TAG_PRESENCE, - CMD_TAG_CHAT, - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/account", - "/account list", - "/account show <account>", - "/account enable|disable <account>", - "/account default set <account>", - "/account default off", - "/account add <account>", - "/account remove <account>", - "/account rename <account> <newaccount>", - "/account set <account> jid <jid>", - "/account set <account> server <server>", - "/account set <account> port <port>", - "/account set <account> status <presence>", - "/account set <account> status last", - "/account set <account> <presence> <priority>", - "/account set <account> resource <resource>", - "/account set <account> password <password>", - "/account set <account> eval_password <command>", - "/account set <account> muc <service>", - "/account set <account> nick <nick>", - "/account set <account> otr <policy>", - "/account set <account> pgpkeyid <pgpkeyid>", - "/account set <account> startscript <script>", - "/account set <account> tls force|allow|disable", - "/account set <account> theme <theme>", - "/account clear <account> password", - "/account clear <account> eval_password", - "/account clear <account> server", - "/account clear <account> port", - "/account clear <account> otr", - "/account clear <account> pgpkeyid", - "/account clear <account> startscript") - CMD_DESC( - "Commands for creating and managing accounts. " - "Calling with no arguments will display information for the current account.") - CMD_ARGS( - { "list", "List all accounts." }, - { "enable <account>", "Enable the account, it will be used for autocompletion." }, - { "show <account>", "Show details for the specified account." }, - { "disable <account>", "Disable the account." }, - { "default set <account>", "Set the default account, used when no argument passed to the /connect command." }, - { "default off", "Clear the default account setting." }, - { "add <account>", "Create a new account." }, - { "remove <account>", "Remove an account." }, - { "rename <account> <newaccount>", "Rename 'account' to 'newaccount'." }, - { "set <account> jid <jid>", "Set the Jabber ID for the account, account name will be used if not set." }, - { "set <account> server <server>", "The chat server, if different to the domainpart of the JID." }, - { "set <account> port <port>", "The port used for connecting if not the default (5222, or 5223 for SSL)." }, - { "set <account> status <presence>", "The presence status to use on login." }, - { "set <account> status last", "Use your last status before logging out, when logging in." }, - { "set <account> <presence> <priority>", "Set the priority (-128..127) to use for the specified presence." }, - { "set <account> resource <resource>", "The resource to be used for this account." }, - { "set <account> password <password>", "Password for the account, note this is currently stored in plaintext if set." }, - { "set <account> eval_password <command>", "Shell command evaluated to retrieve password for the account. Can be used to retrieve password from keyring." }, - { "set <account> muc <service>", "The default MUC chat service to use, defaults to 'conference.<domainpart>' where the domain part is from the account JID." }, - { "set <account> nick <nick>", "The default nickname to use when joining chat rooms." }, - { "set <account> otr <policy>", "Override global OTR policy for this account, see /otr." }, - { "set <account> pgpkeyid <pgpkeyid>", "Set the ID of the PGP key for this account, see /pgp." }, - { "set <account> startscript <script>", "Set the script to execute after connecting." }, - { "set <account> tls force", "Force TLS connection, and fail if one cannot be established, this is default behaviour." }, - { "set <account> tls allow", "Use TLS for the connection if it is available." }, - { "set <account> tls disable", "Disable TLS for the connection." }, - { "set <account> <theme>", "Set the UI theme for the account." }, - { "clear <account> server", "Remove the server setting for this account." }, - { "clear <account> port", "Remove the port setting for this account." }, - { "clear <account> password", "Remove the password setting for this account." }, - { "clear <account> eval_password", "Remove the eval_password setting for this account." }, - { "clear <account> otr", "Remove the OTR policy setting for this account." }, - { "clear <account> pgpkeyid", "Remove pgpkeyid associated with this account." }, - { "clear <account> startscript", "Remove startscript associated with this account." }, - { "clear <account> theme", "Clear the theme setting for the account, the global theme will be used." }) - CMD_EXAMPLES( - "/account add me", - "/account set me jid me@chatty", - "/account set me server talk.chat.com", - "/account set me port 5111", - "/account set me muc chatservice.mycompany.com", - "/account set me nick dennis", - "/account set me status dnd", - "/account set me dnd -1", - "/account rename me gtalk") - }, - - { "/plugins", - parse_args, 0, 2, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_plugins) - CMD_NOTAGS - CMD_SYN( - "/plugins", - "/plugins load <plugin>") - CMD_DESC( - "Manage plugins. Passing no arguments lists currently loaded plugins.") - CMD_ARGS( - { "load <plugin>", "Load a plugin." }) - CMD_EXAMPLES( - "/plugin load browser.py") - }, - - { "/prefs", - parse_args, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_prefs) - CMD_NOTAGS - CMD_SYN( - "/prefs [ui|desktop|chat|log|conn|presence|otr|pgp]") - CMD_DESC( - "Show preferences for different areas of functionality. " - "Passing no arguments shows all preferences.") - CMD_ARGS( - { "ui", "User interface preferences." }, - { "desktop", "Desktop notification preferences." }, - { "chat", "Chat state preferences." }, - { "log", "Logging preferences." }, - { "conn", "Connection handling preferences." }, - { "presence", "Chat presence preferences." }, - { "otr", "Off The Record preferences." }, - { "pgp", "OpenPGP preferences." }) - CMD_NOEXAMPLES - }, - - { "/theme", - parse_args, 1, 2, &cons_theme_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_theme) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/theme list", - "/theme load <theme>", - "/theme colours", - "/theme properties") - CMD_DESC( - "Load a theme, includes colours and UI options.") - CMD_ARGS( - { "list", "List all available themes." }, - { "load <theme>", "Load the specified theme. 'default' will reset to the default theme." }, - { "colours", "Show colour values as rendered by the terminal." }, - { "properties", "Show colour settings for current theme." }) - CMD_EXAMPLES( - "/theme list", - "/theme load forest") - }, - - { "/statuses", - parse_args, 2, 2, &cons_statuses_setting, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_statuses) - CMD_TAGS( - CMD_TAG_UI, - CMD_TAG_CHAT, - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/statuses console|chat|muc all|online|none") - CMD_DESC( - "Configure which presence changes are displayed in various windows. " - "The default is 'all' for all windows.") - CMD_ARGS( - { "console", "Configure what is displayed in the console window." }, - { "chat", "Configure what is displayed in chat windows." }, - { "muc", "Configure what is displayed in chat room windows." }, - { "all", "Show all presence changes." }, - { "online", "Show only online/offline changes." }, - { "none", "Don't show any presence changes." }) - CMD_EXAMPLES( - "/statuses console none", - "/statuses chat online", - "/statuses muc all") - }, - - { "/xmlconsole", - parse_args, 0, 0, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_xmlconsole) - CMD_TAGS( - CMD_TAG_UI) - CMD_SYN( - "/xmlconsole") - CMD_DESC( - "Open the XML console to view incoming and outgoing XMPP traffic.") - CMD_NOARGS - CMD_NOEXAMPLES - }, - - { "/away", - parse_args_with_freetext, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_away) - CMD_TAGS( - CMD_TAG_PRESENCE) - CMD_SYN( - "/away [<message>]") - CMD_DESC( - "Set your status to 'away'.") - CMD_ARGS( - { "<message>", "Optional message to use with the status." }) - CMD_EXAMPLES( - "/away", - "/away Gone for lunch") - }, - - { "/chat", - parse_args_with_freetext, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_chat) - CMD_TAGS( - CMD_TAG_PRESENCE) - CMD_SYN( - "/chat [<message>]") - CMD_DESC( - "Set your status to 'chat' (available for chat).") - CMD_ARGS( - { "<message>", "Optional message to use with the status." }) - CMD_EXAMPLES( - "/chat", - "/chat Please talk to me!") - }, - - { "/dnd", - parse_args_with_freetext, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_dnd) - CMD_TAGS( - CMD_TAG_PRESENCE) - CMD_SYN( - "/dnd [<message>]") - CMD_DESC( - "Set your status to 'dnd' (do not disturb).") - CMD_ARGS( - { "<message>", "Optional message to use with the status." }) - CMD_EXAMPLES( - "/dnd", - "/dnd I'm in the zone") - }, - - { "/online", - parse_args_with_freetext, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_online) - CMD_TAGS( - CMD_TAG_PRESENCE) - CMD_SYN( - "/online [<message>]") - CMD_DESC( - "Set your status to 'online'.") - CMD_ARGS( - { "<message>", "Optional message to use with the status." }) - CMD_EXAMPLES( - "/online", - "/online Up the Irons!") - }, - - { "/xa", - parse_args_with_freetext, 0, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_xa) - CMD_TAGS( - CMD_TAG_PRESENCE) - CMD_SYN( - "/xa [<message>]") - CMD_DESC( - "Set your status to 'xa' (extended away).") - CMD_ARGS( - { "<message>", "Optional message to use with the status." }) - CMD_EXAMPLES( - "/xa", - "/xa This meeting is going to be a long one") - }, - - { "/script", - parse_args, 1, 2, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_script) - CMD_NOTAGS - CMD_SYN( - "/script run <script>", - "/script list", - "/script show <script>") - CMD_DESC( - "Run command scripts. " - "Scripts are stored in $XDG_DATA_HOME/profanity/scripts/ which is usually $HOME/.local/share/profanity/scripts/.") - CMD_ARGS( - { "script run <script>", "Execute a script." }, - { "script list", "List all scripts TODO." }, - { "script show <script>", "Show the commands in script TODO." }) - CMD_EXAMPLES( - "/script list", - "/script run myscript", - "/script show somescript") - }, - - { "/export", - parse_args, 1, 1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_export) - CMD_NOTAGS - CMD_SYN( - "/export <filepath>") - CMD_DESC( - "Exports contacts to a csv file.") - CMD_ARGS( - { "<filepath>", "Path to the output file." }) - CMD_EXAMPLES( - "/export /path/to/output.csv", - "/export ~/contacts.csv") - }, -}; - -static Autocomplete commands_ac; -static Autocomplete who_room_ac; -static Autocomplete who_roster_ac; -static Autocomplete help_ac; -static Autocomplete help_commands_ac; -static Autocomplete notify_ac; -static Autocomplete notify_chat_ac; -static Autocomplete notify_room_ac; -static Autocomplete notify_typing_ac; -static Autocomplete notify_mention_ac; -static Autocomplete notify_trigger_ac; -static Autocomplete prefs_ac; -static Autocomplete sub_ac; -static Autocomplete log_ac; -static Autocomplete autoaway_ac; -static Autocomplete autoaway_mode_ac; -static Autocomplete autoaway_presence_ac; -static Autocomplete autoconnect_ac; -static Autocomplete titlebar_ac; -static Autocomplete theme_ac; -static Autocomplete theme_load_ac; -static Autocomplete account_ac; -static Autocomplete account_set_ac; -static Autocomplete account_clear_ac; -static Autocomplete account_default_ac; -static Autocomplete account_status_ac; -static Autocomplete disco_ac; -static Autocomplete wins_ac; -static Autocomplete roster_ac; -static Autocomplete roster_show_ac; -static Autocomplete roster_by_ac; -static Autocomplete roster_count_ac; -static Autocomplete roster_order_ac; -static Autocomplete roster_header_ac; -static Autocomplete roster_contact_ac; -static Autocomplete roster_resource_ac; -static Autocomplete roster_presence_ac; -static Autocomplete roster_char_ac; -static Autocomplete roster_remove_all_ac; -static Autocomplete roster_room_ac; -static Autocomplete roster_room_position_ac; -static Autocomplete roster_room_by_ac; -static Autocomplete roster_room_order_ac; -static Autocomplete roster_unread_ac; -static Autocomplete roster_private_ac; -static Autocomplete group_ac; -static Autocomplete bookmark_ac; -static Autocomplete bookmark_property_ac; -static Autocomplete otr_ac; -static Autocomplete otr_log_ac; -static Autocomplete otr_policy_ac; -static Autocomplete connect_property_ac; -static Autocomplete tls_property_ac; -static Autocomplete statuses_ac; -static Autocomplete statuses_setting_ac; -static Autocomplete alias_ac; -static Autocomplete aliases_ac; -static Autocomplete join_property_ac; -static Autocomplete room_ac; -static Autocomplete affiliation_ac; -static Autocomplete role_ac; -static Autocomplete privilege_cmd_ac; -static Autocomplete subject_ac; -static Autocomplete form_ac; -static Autocomplete form_field_multi_ac; -static Autocomplete occupants_ac; -static Autocomplete occupants_default_ac; -static Autocomplete occupants_show_ac; -static Autocomplete time_ac; -static Autocomplete time_format_ac; -static Autocomplete resource_ac; -static Autocomplete inpblock_ac; -static Autocomplete receipts_ac; -static Autocomplete pgp_ac; -static Autocomplete pgp_log_ac; -static Autocomplete tls_ac; -static Autocomplete tls_certpath_ac; -static Autocomplete script_ac; -static Autocomplete script_show_ac; -static Autocomplete console_ac; -static Autocomplete console_msg_ac; -static Autocomplete autoping_ac; -static Autocomplete plugins_ac; -static Autocomplete plugins_load_ac; -static Autocomplete sendfile_ac; -static Autocomplete blocked_ac; -static Autocomplete tray_ac; - -/* - * Initialise command autocompleter and history - */ -void -cmd_init(void) -{ - log_info("Initialising commands"); - - commands_ac = autocomplete_new(); - aliases_ac = autocomplete_new(); - - help_ac = autocomplete_new(); - autocomplete_add(help_ac, "commands"); - autocomplete_add(help_ac, "navigation"); - - // load command defs into hash table - commands = g_hash_table_new(g_str_hash, g_str_equal); - unsigned int i; - for (i = 0; i < ARRAY_SIZE(command_defs); i++) { - Command *pcmd = command_defs+i; - - // add to hash - g_hash_table_insert(commands, pcmd->cmd, pcmd); - - // add to commands and help autocompleters - autocomplete_add(commands_ac, pcmd->cmd); - autocomplete_add(help_ac, pcmd->cmd+1); - } - - // load aliases - GList *aliases = prefs_get_aliases(); - GList *curr = aliases; - while (curr) { - ProfAlias *alias = curr->data; - GString *ac_alias = g_string_new("/"); - g_string_append(ac_alias, alias->name); - autocomplete_add(commands_ac, ac_alias->str); - autocomplete_add(aliases_ac, alias->name); - g_string_free(ac_alias, TRUE); - curr = g_list_next(curr); - } - prefs_free_aliases(aliases); - - help_commands_ac = autocomplete_new(); - autocomplete_add(help_commands_ac, "chat"); - autocomplete_add(help_commands_ac, "groupchat"); - autocomplete_add(help_commands_ac, "roster"); - autocomplete_add(help_commands_ac, "presence"); - autocomplete_add(help_commands_ac, "discovery"); - autocomplete_add(help_commands_ac, "connection"); - autocomplete_add(help_commands_ac, "ui"); - autocomplete_add(help_commands_ac, "plugins"); - - prefs_ac = autocomplete_new(); - autocomplete_add(prefs_ac, "ui"); - autocomplete_add(prefs_ac, "desktop"); - autocomplete_add(prefs_ac, "chat"); - autocomplete_add(prefs_ac, "log"); - autocomplete_add(prefs_ac, "conn"); - autocomplete_add(prefs_ac, "presence"); - autocomplete_add(prefs_ac, "otr"); - autocomplete_add(prefs_ac, "pgp"); - - notify_ac = autocomplete_new(); - autocomplete_add(notify_ac, "chat"); - autocomplete_add(notify_ac, "room"); - autocomplete_add(notify_ac, "typing"); - autocomplete_add(notify_ac, "remind"); - autocomplete_add(notify_ac, "invite"); - autocomplete_add(notify_ac, "sub"); - autocomplete_add(notify_ac, "on"); - autocomplete_add(notify_ac, "off"); - autocomplete_add(notify_ac, "mention"); - autocomplete_add(notify_ac, "trigger"); - autocomplete_add(notify_ac, "reset"); - - notify_chat_ac = autocomplete_new(); - autocomplete_add(notify_chat_ac, "on"); - autocomplete_add(notify_chat_ac, "off"); - autocomplete_add(notify_chat_ac, "current"); - autocomplete_add(notify_chat_ac, "text"); - - notify_room_ac = autocomplete_new(); - autocomplete_add(notify_room_ac, "on"); - autocomplete_add(notify_room_ac, "off"); - autocomplete_add(notify_room_ac, "mention"); - autocomplete_add(notify_room_ac, "current"); - autocomplete_add(notify_room_ac, "text"); - autocomplete_add(notify_room_ac, "trigger"); - - notify_typing_ac = autocomplete_new(); - autocomplete_add(notify_typing_ac, "on"); - autocomplete_add(notify_typing_ac, "off"); - autocomplete_add(notify_typing_ac, "current"); - - notify_mention_ac = autocomplete_new(); - autocomplete_add(notify_mention_ac, "on"); - autocomplete_add(notify_mention_ac, "off"); - autocomplete_add(notify_mention_ac, "case_sensitive"); - autocomplete_add(notify_mention_ac, "case_insensitive"); - autocomplete_add(notify_mention_ac, "word_whole"); - autocomplete_add(notify_mention_ac, "word_part"); - - notify_trigger_ac = autocomplete_new(); - autocomplete_add(notify_trigger_ac, "add"); - autocomplete_add(notify_trigger_ac, "remove"); - autocomplete_add(notify_trigger_ac, "list"); - autocomplete_add(notify_trigger_ac, "on"); - autocomplete_add(notify_trigger_ac, "off"); - - sub_ac = autocomplete_new(); - autocomplete_add(sub_ac, "request"); - autocomplete_add(sub_ac, "allow"); - autocomplete_add(sub_ac, "deny"); - autocomplete_add(sub_ac, "show"); - autocomplete_add(sub_ac, "sent"); - autocomplete_add(sub_ac, "received"); - - titlebar_ac = autocomplete_new(); - autocomplete_add(titlebar_ac, "show"); - autocomplete_add(titlebar_ac, "goodbye"); - - log_ac = autocomplete_new(); - autocomplete_add(log_ac, "maxsize"); - autocomplete_add(log_ac, "rotate"); - autocomplete_add(log_ac, "shared"); - autocomplete_add(log_ac, "where"); - - autoaway_ac = autocomplete_new(); - autocomplete_add(autoaway_ac, "mode"); - autocomplete_add(autoaway_ac, "time"); - autocomplete_add(autoaway_ac, "message"); - autocomplete_add(autoaway_ac, "check"); - - autoaway_mode_ac = autocomplete_new(); - autocomplete_add(autoaway_mode_ac, "away"); - autocomplete_add(autoaway_mode_ac, "idle"); - autocomplete_add(autoaway_mode_ac, "off"); - - autoaway_presence_ac = autocomplete_new(); - autocomplete_add(autoaway_presence_ac, "away"); - autocomplete_add(autoaway_presence_ac, "xa"); - - autoconnect_ac = autocomplete_new(); - autocomplete_add(autoconnect_ac, "set"); - autocomplete_add(autoconnect_ac, "off"); - - theme_ac = autocomplete_new(); - autocomplete_add(theme_ac, "load"); - autocomplete_add(theme_ac, "list"); - autocomplete_add(theme_ac, "colours"); - autocomplete_add(theme_ac, "properties"); - - disco_ac = autocomplete_new(); - autocomplete_add(disco_ac, "info"); - autocomplete_add(disco_ac, "items"); - - account_ac = autocomplete_new(); - autocomplete_add(account_ac, "list"); - autocomplete_add(account_ac, "show"); - autocomplete_add(account_ac, "add"); - autocomplete_add(account_ac, "remove"); - autocomplete_add(account_ac, "enable"); - autocomplete_add(account_ac, "disable"); - autocomplete_add(account_ac, "default"); - autocomplete_add(account_ac, "rename"); - autocomplete_add(account_ac, "set"); - autocomplete_add(account_ac, "clear"); - - account_set_ac = autocomplete_new(); - autocomplete_add(account_set_ac, "jid"); - autocomplete_add(account_set_ac, "server"); - autocomplete_add(account_set_ac, "port"); - autocomplete_add(account_set_ac, "status"); - autocomplete_add(account_set_ac, "online"); - autocomplete_add(account_set_ac, "chat"); - autocomplete_add(account_set_ac, "away"); - autocomplete_add(account_set_ac, "xa"); - autocomplete_add(account_set_ac, "dnd"); - autocomplete_add(account_set_ac, "resource"); - autocomplete_add(account_set_ac, "password"); - autocomplete_add(account_set_ac, "eval_password"); - autocomplete_add(account_set_ac, "muc"); - autocomplete_add(account_set_ac, "nick"); - autocomplete_add(account_set_ac, "otr"); - autocomplete_add(account_set_ac, "pgpkeyid"); - autocomplete_add(account_set_ac, "startscript"); - autocomplete_add(account_set_ac, "tls"); - autocomplete_add(account_set_ac, "theme"); - - account_clear_ac = autocomplete_new(); - autocomplete_add(account_clear_ac, "password"); - autocomplete_add(account_clear_ac, "eval_password"); - autocomplete_add(account_clear_ac, "server"); - autocomplete_add(account_clear_ac, "port"); - autocomplete_add(account_clear_ac, "otr"); - autocomplete_add(account_clear_ac, "pgpkeyid"); - autocomplete_add(account_clear_ac, "startscript"); - autocomplete_add(account_clear_ac, "theme"); - - account_default_ac = autocomplete_new(); - autocomplete_add(account_default_ac, "set"); - autocomplete_add(account_default_ac, "off"); - - account_status_ac = autocomplete_new(); - autocomplete_add(account_status_ac, "online"); - autocomplete_add(account_status_ac, "chat"); - autocomplete_add(account_status_ac, "away"); - autocomplete_add(account_status_ac, "xa"); - autocomplete_add(account_status_ac, "dnd"); - autocomplete_add(account_status_ac, "last"); - - wins_ac = autocomplete_new(); - autocomplete_add(wins_ac, "unread"); - autocomplete_add(wins_ac, "prune"); - autocomplete_add(wins_ac, "tidy"); - autocomplete_add(wins_ac, "autotidy"); - autocomplete_add(wins_ac, "swap"); - - roster_ac = autocomplete_new(); - autocomplete_add(roster_ac, "add"); - autocomplete_add(roster_ac, "online"); - autocomplete_add(roster_ac, "nick"); - autocomplete_add(roster_ac, "clearnick"); - autocomplete_add(roster_ac, "remove"); - autocomplete_add(roster_ac, "remove_all"); - autocomplete_add(roster_ac, "show"); - autocomplete_add(roster_ac, "hide"); - autocomplete_add(roster_ac, "by"); - autocomplete_add(roster_ac, "count"); - autocomplete_add(roster_ac, "order"); - autocomplete_add(roster_ac, "unread"); - autocomplete_add(roster_ac, "room"); - autocomplete_add(roster_ac, "size"); - autocomplete_add(roster_ac, "wrap"); - autocomplete_add(roster_ac, "header"); - autocomplete_add(roster_ac, "contact"); - autocomplete_add(roster_ac, "resource"); - autocomplete_add(roster_ac, "presence"); - autocomplete_add(roster_ac, "private"); - - roster_private_ac = autocomplete_new(); - autocomplete_add(roster_private_ac, "room"); - autocomplete_add(roster_private_ac, "group"); - autocomplete_add(roster_private_ac, "off"); - autocomplete_add(roster_private_ac, "char"); - - roster_header_ac = autocomplete_new(); - autocomplete_add(roster_header_ac, "char"); - - roster_contact_ac = autocomplete_new(); - autocomplete_add(roster_contact_ac, "char"); - autocomplete_add(roster_contact_ac, "indent"); - - roster_resource_ac = autocomplete_new(); - autocomplete_add(roster_resource_ac, "char"); - autocomplete_add(roster_resource_ac, "indent"); - autocomplete_add(roster_resource_ac, "join"); - - roster_presence_ac = autocomplete_new(); - autocomplete_add(roster_presence_ac, "indent"); - - roster_char_ac = autocomplete_new(); - autocomplete_add(roster_char_ac, "none"); - - roster_show_ac = autocomplete_new(); - autocomplete_add(roster_show_ac, "offline"); - autocomplete_add(roster_show_ac, "resource"); - autocomplete_add(roster_show_ac, "presence"); - autocomplete_add(roster_show_ac, "status"); - autocomplete_add(roster_show_ac, "empty"); - autocomplete_add(roster_show_ac, "priority"); - autocomplete_add(roster_show_ac, "contacts"); - autocomplete_add(roster_show_ac, "unsubscribed"); - autocomplete_add(roster_show_ac, "rooms"); - - roster_by_ac = autocomplete_new(); - autocomplete_add(roster_by_ac, "group"); - autocomplete_add(roster_by_ac, "presence"); - autocomplete_add(roster_by_ac, "none"); - - roster_count_ac = autocomplete_new(); - autocomplete_add(roster_count_ac, "unread"); - autocomplete_add(roster_count_ac, "items"); - autocomplete_add(roster_count_ac, "off"); - autocomplete_add(roster_count_ac, "zero"); - - roster_order_ac = autocomplete_new(); - autocomplete_add(roster_order_ac, "name"); - autocomplete_add(roster_order_ac, "presence"); - - roster_unread_ac = autocomplete_new(); - autocomplete_add(roster_unread_ac, "before"); - autocomplete_add(roster_unread_ac, "after"); - autocomplete_add(roster_unread_ac, "off"); - - roster_room_ac = autocomplete_new(); - autocomplete_add(roster_room_ac, "char"); - autocomplete_add(roster_room_ac, "position"); - autocomplete_add(roster_room_ac, "by"); - autocomplete_add(roster_room_ac, "order"); - autocomplete_add(roster_room_ac, "unread"); - autocomplete_add(roster_room_ac, "private"); - - roster_room_by_ac = autocomplete_new(); - autocomplete_add(roster_room_by_ac, "service"); - autocomplete_add(roster_room_by_ac, "none"); - - roster_room_order_ac = autocomplete_new(); - autocomplete_add(roster_room_order_ac, "name"); - autocomplete_add(roster_room_order_ac, "unread"); - - roster_room_position_ac = autocomplete_new(); - autocomplete_add(roster_room_position_ac, "first"); - autocomplete_add(roster_room_position_ac, "last"); - - roster_remove_all_ac = autocomplete_new(); - autocomplete_add(roster_remove_all_ac, "contacts"); - - group_ac = autocomplete_new(); - autocomplete_add(group_ac, "show"); - autocomplete_add(group_ac, "add"); - autocomplete_add(group_ac, "remove"); - - theme_load_ac = NULL; - plugins_load_ac = NULL; - - who_roster_ac = autocomplete_new(); - autocomplete_add(who_roster_ac, "chat"); - autocomplete_add(who_roster_ac, "online"); - autocomplete_add(who_roster_ac, "away"); - autocomplete_add(who_roster_ac, "xa"); - autocomplete_add(who_roster_ac, "dnd"); - autocomplete_add(who_roster_ac, "offline"); - autocomplete_add(who_roster_ac, "available"); - autocomplete_add(who_roster_ac, "unavailable"); - autocomplete_add(who_roster_ac, "any"); - - who_room_ac = autocomplete_new(); - autocomplete_add(who_room_ac, "chat"); - autocomplete_add(who_room_ac, "online"); - autocomplete_add(who_room_ac, "away"); - autocomplete_add(who_room_ac, "xa"); - autocomplete_add(who_room_ac, "dnd"); - autocomplete_add(who_room_ac, "available"); - autocomplete_add(who_room_ac, "unavailable"); - autocomplete_add(who_room_ac, "moderator"); - autocomplete_add(who_room_ac, "participant"); - autocomplete_add(who_room_ac, "visitor"); - autocomplete_add(who_room_ac, "owner"); - autocomplete_add(who_room_ac, "admin"); - autocomplete_add(who_room_ac, "member"); - - bookmark_ac = autocomplete_new(); - autocomplete_add(bookmark_ac, "list"); - autocomplete_add(bookmark_ac, "add"); - autocomplete_add(bookmark_ac, "update"); - autocomplete_add(bookmark_ac, "remove"); - autocomplete_add(bookmark_ac, "join"); - - bookmark_property_ac = autocomplete_new(); - autocomplete_add(bookmark_property_ac, "nick"); - autocomplete_add(bookmark_property_ac, "password"); - autocomplete_add(bookmark_property_ac, "autojoin"); - - otr_ac = autocomplete_new(); - autocomplete_add(otr_ac, "gen"); - autocomplete_add(otr_ac, "start"); - autocomplete_add(otr_ac, "end"); - autocomplete_add(otr_ac, "myfp"); - autocomplete_add(otr_ac, "theirfp"); - autocomplete_add(otr_ac, "trust"); - autocomplete_add(otr_ac, "untrust"); - autocomplete_add(otr_ac, "secret"); - autocomplete_add(otr_ac, "log"); - autocomplete_add(otr_ac, "libver"); - autocomplete_add(otr_ac, "policy"); - autocomplete_add(otr_ac, "question"); - autocomplete_add(otr_ac, "answer"); - autocomplete_add(otr_ac, "char"); - - otr_log_ac = autocomplete_new(); - autocomplete_add(otr_log_ac, "on"); - autocomplete_add(otr_log_ac, "off"); - autocomplete_add(otr_log_ac, "redact"); - - otr_policy_ac = autocomplete_new(); - autocomplete_add(otr_policy_ac, "manual"); - autocomplete_add(otr_policy_ac, "opportunistic"); - autocomplete_add(otr_policy_ac, "always"); - - connect_property_ac = autocomplete_new(); - autocomplete_add(connect_property_ac, "server"); - autocomplete_add(connect_property_ac, "port"); - autocomplete_add(connect_property_ac, "tls"); - - tls_property_ac = autocomplete_new(); - autocomplete_add(tls_property_ac, "force"); - autocomplete_add(tls_property_ac, "allow"); - autocomplete_add(tls_property_ac, "disable"); - - join_property_ac = autocomplete_new(); - autocomplete_add(join_property_ac, "nick"); - autocomplete_add(join_property_ac, "password"); - - statuses_ac = autocomplete_new(); - autocomplete_add(statuses_ac, "console"); - autocomplete_add(statuses_ac, "chat"); - autocomplete_add(statuses_ac, "muc"); - - statuses_setting_ac = autocomplete_new(); - autocomplete_add(statuses_setting_ac, "all"); - autocomplete_add(statuses_setting_ac, "online"); - autocomplete_add(statuses_setting_ac, "none"); - - alias_ac = autocomplete_new(); - autocomplete_add(alias_ac, "add"); - autocomplete_add(alias_ac, "remove"); - autocomplete_add(alias_ac, "list"); - - room_ac = autocomplete_new(); - autocomplete_add(room_ac, "accept"); - autocomplete_add(room_ac, "destroy"); - autocomplete_add(room_ac, "config"); - - affiliation_ac = autocomplete_new(); - autocomplete_add(affiliation_ac, "owner"); - autocomplete_add(affiliation_ac, "admin"); - autocomplete_add(affiliation_ac, "member"); - autocomplete_add(affiliation_ac, "none"); - autocomplete_add(affiliation_ac, "outcast"); - - role_ac = autocomplete_new(); - autocomplete_add(role_ac, "moderator"); - autocomplete_add(role_ac, "participant"); - autocomplete_add(role_ac, "visitor"); - autocomplete_add(role_ac, "none"); - - privilege_cmd_ac = autocomplete_new(); - autocomplete_add(privilege_cmd_ac, "list"); - autocomplete_add(privilege_cmd_ac, "set"); - - subject_ac = autocomplete_new(); - autocomplete_add(subject_ac, "set"); - autocomplete_add(subject_ac, "edit"); - autocomplete_add(subject_ac, "prepend"); - autocomplete_add(subject_ac, "append"); - autocomplete_add(subject_ac, "clear"); - - form_ac = autocomplete_new(); - autocomplete_add(form_ac, "submit"); - autocomplete_add(form_ac, "cancel"); - autocomplete_add(form_ac, "show"); - autocomplete_add(form_ac, "help"); - - form_field_multi_ac = autocomplete_new(); - autocomplete_add(form_field_multi_ac, "add"); - autocomplete_add(form_field_multi_ac, "remove"); - - occupants_ac = autocomplete_new(); - autocomplete_add(occupants_ac, "show"); - autocomplete_add(occupants_ac, "hide"); - autocomplete_add(occupants_ac, "default"); - autocomplete_add(occupants_ac, "size"); - - occupants_default_ac = autocomplete_new(); - autocomplete_add(occupants_default_ac, "show"); - autocomplete_add(occupants_default_ac, "hide"); - - occupants_show_ac = autocomplete_new(); - autocomplete_add(occupants_show_ac, "jid"); - - time_ac = autocomplete_new(); - autocomplete_add(time_ac, "console"); - autocomplete_add(time_ac, "chat"); - autocomplete_add(time_ac, "muc"); - autocomplete_add(time_ac, "mucconfig"); - autocomplete_add(time_ac, "private"); - autocomplete_add(time_ac, "xml"); - autocomplete_add(time_ac, "statusbar"); - autocomplete_add(time_ac, "lastactivity"); - - time_format_ac = autocomplete_new(); - autocomplete_add(time_format_ac, "set"); - autocomplete_add(time_format_ac, "off"); - - resource_ac = autocomplete_new(); - autocomplete_add(resource_ac, "set"); - autocomplete_add(resource_ac, "off"); - autocomplete_add(resource_ac, "title"); - autocomplete_add(resource_ac, "message"); - - inpblock_ac = autocomplete_new(); - autocomplete_add(inpblock_ac, "timeout"); - autocomplete_add(inpblock_ac, "dynamic"); - - receipts_ac = autocomplete_new(); - autocomplete_add(receipts_ac, "send"); - autocomplete_add(receipts_ac, "request"); - - pgp_ac = autocomplete_new(); - autocomplete_add(pgp_ac, "keys"); - autocomplete_add(pgp_ac, "contacts"); - autocomplete_add(pgp_ac, "setkey"); - autocomplete_add(pgp_ac, "libver"); - autocomplete_add(pgp_ac, "start"); - autocomplete_add(pgp_ac, "end"); - autocomplete_add(pgp_ac, "log"); - autocomplete_add(pgp_ac, "char"); - - pgp_log_ac = autocomplete_new(); - autocomplete_add(pgp_log_ac, "on"); - autocomplete_add(pgp_log_ac, "off"); - autocomplete_add(pgp_log_ac, "redact"); - - tls_ac = autocomplete_new(); - autocomplete_add(tls_ac, "allow"); - autocomplete_add(tls_ac, "always"); - autocomplete_add(tls_ac, "deny"); - autocomplete_add(tls_ac, "cert"); - autocomplete_add(tls_ac, "trust"); - autocomplete_add(tls_ac, "trusted"); - autocomplete_add(tls_ac, "revoke"); - autocomplete_add(tls_ac, "certpath"); - autocomplete_add(tls_ac, "show"); - - tls_certpath_ac = autocomplete_new(); - autocomplete_add(tls_certpath_ac, "set"); - autocomplete_add(tls_certpath_ac, "clear"); - - script_ac = autocomplete_new(); - autocomplete_add(script_ac, "run"); - autocomplete_add(script_ac, "list"); - autocomplete_add(script_ac, "show"); - - script_show_ac = NULL; - - console_ac = autocomplete_new(); - autocomplete_add(console_ac, "chat"); - autocomplete_add(console_ac, "muc"); - autocomplete_add(console_ac, "private"); - - console_msg_ac = autocomplete_new(); - autocomplete_add(console_msg_ac, "all"); - autocomplete_add(console_msg_ac, "first"); - autocomplete_add(console_msg_ac, "none"); - - autoping_ac = autocomplete_new(); - autocomplete_add(autoping_ac, "set"); - autocomplete_add(autoping_ac, "timeout"); - - plugins_ac = autocomplete_new(); - autocomplete_add(plugins_ac, "load"); - - sendfile_ac = autocomplete_new(); - - blocked_ac = autocomplete_new(); - autocomplete_add(blocked_ac, "add"); - autocomplete_add(blocked_ac, "remove"); - - tray_ac = autocomplete_new(); - autocomplete_add(tray_ac, "on"); - autocomplete_add(tray_ac, "off"); - autocomplete_add(tray_ac, "read"); - autocomplete_add(tray_ac, "timer"); -} - -void -cmd_uninit(void) -{ - autocomplete_free(commands_ac); - autocomplete_free(who_room_ac); - autocomplete_free(who_roster_ac); - autocomplete_free(help_ac); - autocomplete_free(help_commands_ac); - autocomplete_free(notify_ac); - autocomplete_free(notify_chat_ac); - autocomplete_free(notify_room_ac); - autocomplete_free(notify_typing_ac); - autocomplete_free(notify_mention_ac); - autocomplete_free(notify_trigger_ac); - autocomplete_free(sub_ac); - autocomplete_free(titlebar_ac); - autocomplete_free(log_ac); - autocomplete_free(prefs_ac); - autocomplete_free(autoaway_ac); - autocomplete_free(autoaway_mode_ac); - autocomplete_free(autoaway_presence_ac); - autocomplete_free(autoconnect_ac); - autocomplete_free(theme_ac); - autocomplete_free(theme_load_ac); - autocomplete_free(account_ac); - autocomplete_free(account_set_ac); - autocomplete_free(account_clear_ac); - autocomplete_free(account_default_ac); - autocomplete_free(account_status_ac); - autocomplete_free(disco_ac); - autocomplete_free(wins_ac); - autocomplete_free(roster_ac); - autocomplete_free(roster_header_ac); - autocomplete_free(roster_contact_ac); - autocomplete_free(roster_resource_ac); - autocomplete_free(roster_presence_ac); - autocomplete_free(roster_char_ac); - autocomplete_free(roster_show_ac); - autocomplete_free(roster_by_ac); - autocomplete_free(roster_count_ac); - autocomplete_free(roster_order_ac); - autocomplete_free(roster_room_ac); - autocomplete_free(roster_room_by_ac); - autocomplete_free(roster_unread_ac); - autocomplete_free(roster_room_position_ac); - autocomplete_free(roster_room_order_ac); - autocomplete_free(roster_remove_all_ac); - autocomplete_free(roster_private_ac); - autocomplete_free(group_ac); - autocomplete_free(bookmark_ac); - autocomplete_free(bookmark_property_ac); - autocomplete_free(otr_ac); - autocomplete_free(otr_log_ac); - autocomplete_free(otr_policy_ac); - autocomplete_free(connect_property_ac); - autocomplete_free(tls_property_ac); - autocomplete_free(statuses_ac); - autocomplete_free(statuses_setting_ac); - autocomplete_free(alias_ac); - autocomplete_free(aliases_ac); - autocomplete_free(join_property_ac); - autocomplete_free(room_ac); - autocomplete_free(affiliation_ac); - autocomplete_free(role_ac); - autocomplete_free(privilege_cmd_ac); - autocomplete_free(subject_ac); - autocomplete_free(form_ac); - autocomplete_free(form_field_multi_ac); - autocomplete_free(occupants_ac); - autocomplete_free(occupants_default_ac); - autocomplete_free(occupants_show_ac); - autocomplete_free(time_ac); - autocomplete_free(time_format_ac); - autocomplete_free(resource_ac); - autocomplete_free(inpblock_ac); - autocomplete_free(receipts_ac); - autocomplete_free(pgp_ac); - autocomplete_free(pgp_log_ac); - autocomplete_free(tls_ac); - autocomplete_free(tls_certpath_ac); - autocomplete_free(script_ac); - autocomplete_free(script_show_ac); - autocomplete_free(console_ac); - autocomplete_free(console_msg_ac); - autocomplete_free(autoping_ac); - autocomplete_free(plugins_ac); - autocomplete_free(plugins_load_ac); - autocomplete_free(sendfile_ac); - autocomplete_free(blocked_ac); - autocomplete_free(tray_ac); -} - -gboolean -cmd_exists(char *cmd) -{ - if (commands_ac == NULL) { - return FALSE; - } else { - return autocomplete_contains(commands_ac, cmd); - } -} - -void -cmd_autocomplete_add(const char *const value) -{ - if (commands_ac) { - autocomplete_add(commands_ac, value); - } -} - -void -cmd_help_autocomplete_add(const char *const value) -{ - if (help_ac) { - autocomplete_add(help_ac, value); - } -} - -void -cmd_autocomplete_add_form_fields(DataForm *form) -{ - if (form == NULL) { - return; - } - - GSList *fields = autocomplete_create_list(form->tag_ac); - GSList *curr_field = fields; - while (curr_field) { - GString *field_str = g_string_new("/"); - g_string_append(field_str, curr_field->data); - cmd_autocomplete_add(field_str->str); - g_string_free(field_str, TRUE); - curr_field = g_slist_next(curr_field); - } - g_slist_free_full(fields, free); -} - -void -cmd_autocomplete_remove_form_fields(DataForm *form) -{ - if (form == NULL) { - return; - } - - GSList *fields = autocomplete_create_list(form->tag_ac); - GSList *curr_field = fields; - while (curr_field) { - GString *field_str = g_string_new("/"); - g_string_append(field_str, curr_field->data); - cmd_autocomplete_remove(field_str->str); - g_string_free(field_str, TRUE); - curr_field = g_slist_next(curr_field); - } - g_slist_free_full(fields, free); -} - -void -cmd_autocomplete_remove(const char *const value) -{ - if (commands_ac) { - autocomplete_remove(commands_ac, value); - } -} - -void -cmd_alias_add(char *value) -{ - if (aliases_ac) { - autocomplete_add(aliases_ac, value); - } -} - -void -cmd_alias_remove(char *value) -{ - if (aliases_ac) { - autocomplete_remove(aliases_ac, value); - } -} - -// Command autocompletion functions -char* -cmd_autocomplete(ProfWin *window, const char *const input) -{ - // autocomplete command - if ((strncmp(input, "/", 1) == 0) && (!str_contains(input, strlen(input), ' '))) { - char *found = NULL; - found = autocomplete_complete(commands_ac, input, TRUE); - if (found) { - return found; - } - - // autocomplete parameters - } else { - char *found = _cmd_complete_parameters(window, input); - if (found) { - return found; - } - } - - return NULL; -} - -void -cmd_reset_autocomplete(ProfWin *window) -{ - jabber_conn_status_t conn_status = connection_get_status(); - if (conn_status == JABBER_CONNECTED) { - roster_reset_search_attempts(); - - if (window->type == WIN_CHAT) { - ProfChatWin *chatwin = (ProfChatWin*)window; - assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); - PContact contact = roster_get_contact(chatwin->barejid); - if (contact) { - p_contact_resource_ac_reset(contact); - } - } - } - - muc_invites_reset_ac(); - accounts_reset_all_search(); - accounts_reset_enabled_search(); - tlscerts_reset_ac(); - prefs_reset_boolean_choice(); - presence_reset_sub_request_search(); -#ifdef HAVE_LIBGPGME - p_gpg_autocomplete_key_reset(); -#endif - autocomplete_reset(help_ac); - autocomplete_reset(help_commands_ac); - autocomplete_reset(notify_ac); - autocomplete_reset(notify_chat_ac); - autocomplete_reset(notify_room_ac); - autocomplete_reset(notify_typing_ac); - autocomplete_reset(notify_mention_ac); - autocomplete_reset(notify_trigger_ac); - autocomplete_reset(sub_ac); - autocomplete_reset(sendfile_ac); - - autocomplete_reset(who_room_ac); - autocomplete_reset(who_roster_ac); - autocomplete_reset(prefs_ac); - autocomplete_reset(log_ac); - autocomplete_reset(commands_ac); - autocomplete_reset(autoaway_ac); - autocomplete_reset(autoaway_mode_ac); - autocomplete_reset(autoaway_presence_ac); - autocomplete_reset(autoconnect_ac); - autocomplete_reset(theme_ac); - if (theme_load_ac) { - autocomplete_free(theme_load_ac); - theme_load_ac = NULL; - } - if (plugins_load_ac) { - autocomplete_free(plugins_load_ac); - plugins_load_ac = NULL; - } - autocomplete_reset(account_ac); - autocomplete_reset(account_set_ac); - autocomplete_reset(account_clear_ac); - autocomplete_reset(account_default_ac); - autocomplete_reset(account_status_ac); - autocomplete_reset(disco_ac); - autocomplete_reset(wins_ac); - autocomplete_reset(roster_ac); - autocomplete_reset(roster_header_ac); - autocomplete_reset(roster_contact_ac); - autocomplete_reset(roster_resource_ac); - autocomplete_reset(roster_presence_ac); - autocomplete_reset(roster_char_ac); - autocomplete_reset(roster_show_ac); - autocomplete_reset(roster_by_ac); - autocomplete_reset(roster_count_ac); - autocomplete_reset(roster_order_ac); - autocomplete_reset(roster_room_ac); - autocomplete_reset(roster_room_by_ac); - autocomplete_reset(roster_unread_ac); - autocomplete_reset(roster_room_position_ac); - autocomplete_reset(roster_room_order_ac); - autocomplete_reset(roster_remove_all_ac); - autocomplete_reset(roster_private_ac); - autocomplete_reset(group_ac); - autocomplete_reset(titlebar_ac); - autocomplete_reset(bookmark_ac); - autocomplete_reset(bookmark_property_ac); - autocomplete_reset(otr_ac); - autocomplete_reset(otr_log_ac); - autocomplete_reset(otr_policy_ac); - autocomplete_reset(connect_property_ac); - autocomplete_reset(tls_property_ac); - autocomplete_reset(statuses_ac); - autocomplete_reset(statuses_setting_ac); - autocomplete_reset(alias_ac); - autocomplete_reset(aliases_ac); - autocomplete_reset(join_property_ac); - autocomplete_reset(room_ac); - autocomplete_reset(affiliation_ac); - autocomplete_reset(role_ac); - autocomplete_reset(privilege_cmd_ac); - autocomplete_reset(subject_ac); - autocomplete_reset(form_ac); - autocomplete_reset(form_field_multi_ac); - autocomplete_reset(occupants_ac); - autocomplete_reset(occupants_default_ac); - autocomplete_reset(occupants_show_ac); - autocomplete_reset(time_ac); - autocomplete_reset(time_format_ac); - autocomplete_reset(resource_ac); - autocomplete_reset(inpblock_ac); - autocomplete_reset(receipts_ac); - autocomplete_reset(pgp_ac); - autocomplete_reset(pgp_log_ac); - autocomplete_reset(tls_ac); - autocomplete_reset(tls_certpath_ac); - autocomplete_reset(console_ac); - autocomplete_reset(console_msg_ac); - autocomplete_reset(autoping_ac); - autocomplete_reset(plugins_ac); - autocomplete_reset(blocked_ac); - autocomplete_reset(tray_ac); - autocomplete_reset(script_ac); - if (script_show_ac) { - autocomplete_free(script_show_ac); - script_show_ac = NULL; - } - - if (window->type == WIN_MUC) { - ProfMucWin *mucwin = (ProfMucWin*)window; - assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); - muc_autocomplete_reset(mucwin->roomjid); - muc_jid_autocomplete_reset(mucwin->roomjid); - } - - if (window->type == WIN_MUC_CONFIG) { - ProfMucConfWin *confwin = (ProfMucConfWin*)window; - assert(confwin->memcheck == PROFCONFWIN_MEMCHECK); - if (confwin->form) { - form_reset_autocompleters(confwin->form); - } - } - - bookmark_autocomplete_reset(); - blocked_ac_reset(); - prefs_reset_room_trigger_ac(); - win_reset_search_attempts(); - win_close_reset_search_attempts(); - plugins_reset_autocomplete(); -} - -gboolean -cmd_valid_tag(const char *const str) -{ - return ((g_strcmp0(str, CMD_TAG_CHAT) == 0) || - (g_strcmp0(str, CMD_TAG_GROUPCHAT) == 0) || - (g_strcmp0(str, CMD_TAG_PRESENCE) == 0) || - (g_strcmp0(str, CMD_TAG_ROSTER) == 0) || - (g_strcmp0(str, CMD_TAG_DISCOVERY) == 0) || - (g_strcmp0(str, CMD_TAG_CONNECTION) == 0) || - (g_strcmp0(str, CMD_TAG_UI) == 0) || - (g_strcmp0(str, CMD_TAG_PLUGINS) == 0)); -} - -gboolean -cmd_has_tag(Command *pcmd, const char *const tag) -{ - int i = 0; - for (i = 0; pcmd->help.tags[i] != NULL; i++) { - if (g_strcmp0(tag, pcmd->help.tags[i]) == 0) { - return TRUE; - } - } - - return FALSE; -} - -/* - * Take a line of input and process it, return TRUE if profanity is to - * continue, FALSE otherwise - */ -gboolean -cmd_process_input(ProfWin *window, char *inp) -{ - log_debug("Input received: %s", inp); - gboolean result = FALSE; - g_strchomp(inp); - - // just carry on if no input - if (strlen(inp) == 0) { - result = TRUE; - - // handle command if input starts with a '/' - } else if (inp[0] == '/') { - char *inp_cpy = strdup(inp); - char *command = strtok(inp_cpy, " "); - char *question_mark = strchr(command, '?'); - if (question_mark) { - *question_mark = '\0'; - char *fakeinp; - if (asprintf(&fakeinp, "/help %s", command+1)) { - result = _cmd_execute(window, "/help", fakeinp); - free(fakeinp); - } - } else { - result = _cmd_execute(window, command, inp); - } - free(inp_cpy); - - // call a default handler if input didn't start with '/' - } else { - result = cmd_execute_default(window, inp); - } - - return result; -} - -// Command execution - -void -cmd_execute_connect(ProfWin *window, const char *const account) -{ - GString *command = g_string_new("/connect "); - g_string_append(command, account); - cmd_process_input(window, command->str); - g_string_free(command, TRUE); -} - -static gboolean -_cmd_execute(ProfWin *window, const char *const command, const char *const inp) -{ - if (g_str_has_prefix(command, "/field") && window->type == WIN_MUC_CONFIG) { - gboolean result = FALSE; - gchar **args = parse_args_with_freetext(inp, 1, 2, &result); - if (!result) { - ui_current_print_formatted_line('!', 0, "Invalid command, see /form help"); - result = TRUE; - } else { - gchar **tokens = g_strsplit(inp, " ", 2); - char *field = tokens[0] + 1; - result = cmd_form_field(window, field, args); - g_strfreev(tokens); - } - - g_strfreev(args); - return result; - } - - Command *cmd = g_hash_table_lookup(commands, command); - gboolean result = FALSE; - - if (cmd) { - gchar **args = cmd->parser(inp, cmd->min_args, cmd->max_args, &result); - if (result == FALSE) { - ui_invalid_command_usage(cmd->cmd, cmd->setting_func); - return TRUE; - } - if (args[0] && cmd->sub_funcs[0][0]) { - int i = 0; - while (cmd->sub_funcs[i][0]) { - if (g_strcmp0(args[0], (char*)cmd->sub_funcs[i][0]) == 0) { - gboolean (*func)(ProfWin *window, const char *const command, gchar **args) = cmd->sub_funcs[i][1]; - gboolean result = func(window, command, args); - g_strfreev(args); - return result; - } - i++; - } - } - if (!cmd->func) { - ui_invalid_command_usage(cmd->cmd, cmd->setting_func); - return TRUE; - } - gboolean result = cmd->func(window, command, args); - g_strfreev(args); - return result; - } else if (plugins_run_command(inp)) { - return TRUE; - } else { - gboolean ran_alias = FALSE; - gboolean alias_result = cmd_execute_alias(window, inp, &ran_alias); - if (!ran_alias) { - return cmd_execute_default(window, inp); - } else { - return alias_result; - } - } -} - -static char* -_cmd_complete_parameters(ProfWin *window, const char *const input) -{ - int i; - char *result = NULL; - - jabber_conn_status_t conn_status = connection_get_status(); - - // autocomplete boolean settings - gchar *boolean_choices[] = { "/beep", "/intype", "/states", "/outtype", "/flash", "/splash", "/chlog", "/grlog", - "/history", "/vercheck", "/privileges", "/presence", "/wrap", "/winstidy", "/carbons", "/encwarn", - "/lastactivity" }; - - for (i = 0; i < ARRAY_SIZE(boolean_choices); i++) { - result = autocomplete_param_with_func(input, boolean_choices[i], prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - } - - // autocomplete nickname in chat rooms - if (window->type == WIN_MUC) { - ProfMucWin *mucwin = (ProfMucWin*)window; - assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); - Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid); - if (nick_ac) { - gchar *nick_choices[] = { "/msg", "/info", "/caps", "/status", "/software" } ; - - // Remove quote character before and after names when doing autocomplete - char *unquoted = strip_arg_quotes(input); - for (i = 0; i < ARRAY_SIZE(nick_choices); i++) { - result = autocomplete_param_with_ac(unquoted, nick_choices[i], nick_ac, TRUE); - if (result) { - free(unquoted); - return result; - } - } - free(unquoted); - } - - // otherwise autocomplete using roster - } else if (conn_status == JABBER_CONNECTED) { - gchar *contact_choices[] = { "/msg", "/info", "/status" }; - // Remove quote character before and after names when doing autocomplete - char *unquoted = strip_arg_quotes(input); - for (i = 0; i < ARRAY_SIZE(contact_choices); i++) { - result = autocomplete_param_with_func(unquoted, contact_choices[i], roster_contact_autocomplete); - if (result) { - free(unquoted); - return result; - } - } - free(unquoted); - - gchar *resource_choices[] = { "/caps", "/software", "/ping" }; - for (i = 0; i < ARRAY_SIZE(resource_choices); i++) { - result = autocomplete_param_with_func(input, resource_choices[i], roster_fulljid_autocomplete); - if (result) { - return result; - } - } - } - - if (conn_status == JABBER_CONNECTED) { - result = autocomplete_param_with_func(input, "/invite", roster_contact_autocomplete); - if (result) { - return result; - } - } - - gchar *invite_choices[] = { "/decline", "/join" }; - for (i = 0; i < ARRAY_SIZE(invite_choices); i++) { - result = autocomplete_param_with_func(input, invite_choices[i], muc_invites_find); - if (result) { - return result; - } - } - - gchar *cmds[] = { "/prefs", "/disco", "/room", "/autoping" }; - Autocomplete completers[] = { prefs_ac, disco_ac, room_ac, autoping_ac }; - - for (i = 0; i < ARRAY_SIZE(cmds); i++) { - result = autocomplete_param_with_ac(input, cmds[i], completers[i], TRUE); - if (result) { - return result; - } - } - - GHashTable *ac_funcs = g_hash_table_new(g_str_hash, g_str_equal); - g_hash_table_insert(ac_funcs, "/help", _help_autocomplete); - g_hash_table_insert(ac_funcs, "/who", _who_autocomplete); - g_hash_table_insert(ac_funcs, "/sub", _sub_autocomplete); - g_hash_table_insert(ac_funcs, "/notify", _notify_autocomplete); - g_hash_table_insert(ac_funcs, "/autoaway", _autoaway_autocomplete); - g_hash_table_insert(ac_funcs, "/theme", _theme_autocomplete); - g_hash_table_insert(ac_funcs, "/log", _log_autocomplete); - g_hash_table_insert(ac_funcs, "/account", _account_autocomplete); - g_hash_table_insert(ac_funcs, "/roster", _roster_autocomplete); - g_hash_table_insert(ac_funcs, "/group", _group_autocomplete); - g_hash_table_insert(ac_funcs, "/bookmark", _bookmark_autocomplete); - g_hash_table_insert(ac_funcs, "/autoconnect", _autoconnect_autocomplete); - g_hash_table_insert(ac_funcs, "/otr", _otr_autocomplete); - g_hash_table_insert(ac_funcs, "/pgp", _pgp_autocomplete); - g_hash_table_insert(ac_funcs, "/connect", _connect_autocomplete); - g_hash_table_insert(ac_funcs, "/statuses", _statuses_autocomplete); - g_hash_table_insert(ac_funcs, "/alias", _alias_autocomplete); - g_hash_table_insert(ac_funcs, "/join", _join_autocomplete); - g_hash_table_insert(ac_funcs, "/form", _form_autocomplete); - g_hash_table_insert(ac_funcs, "/occupants", _occupants_autocomplete); - g_hash_table_insert(ac_funcs, "/kick", _kick_autocomplete); - g_hash_table_insert(ac_funcs, "/ban", _ban_autocomplete); - g_hash_table_insert(ac_funcs, "/affiliation", _affiliation_autocomplete); - g_hash_table_insert(ac_funcs, "/role", _role_autocomplete); - g_hash_table_insert(ac_funcs, "/resource", _resource_autocomplete); - g_hash_table_insert(ac_funcs, "/titlebar", _titlebar_autocomplete); - g_hash_table_insert(ac_funcs, "/inpblock", _inpblock_autocomplete); - g_hash_table_insert(ac_funcs, "/time", _time_autocomplete); - g_hash_table_insert(ac_funcs, "/receipts", _receipts_autocomplete); - g_hash_table_insert(ac_funcs, "/wins", _wins_autocomplete); - g_hash_table_insert(ac_funcs, "/tls", _tls_autocomplete); - g_hash_table_insert(ac_funcs, "/script", _script_autocomplete); - g_hash_table_insert(ac_funcs, "/subject", _subject_autocomplete); - g_hash_table_insert(ac_funcs, "/console", _console_autocomplete); - g_hash_table_insert(ac_funcs, "/win", _win_autocomplete); - g_hash_table_insert(ac_funcs, "/close", _close_autocomplete); - g_hash_table_insert(ac_funcs, "/plugins", _plugins_autocomplete); - g_hash_table_insert(ac_funcs, "/sendfile", _sendfile_autocomplete); - g_hash_table_insert(ac_funcs, "/blocked", _blocked_autocomplete); - g_hash_table_insert(ac_funcs, "/tray", _tray_autocomplete); - - int len = strlen(input); - char parsed[len+1]; - i = 0; - while (i < len) { - if (input[i] == ' ') { - break; - } else { - parsed[i] = input[i]; - } - i++; - } - parsed[i] = '\0'; - - char * (*ac_func)(ProfWin*, const char * const) = g_hash_table_lookup(ac_funcs, parsed); - if (ac_func) { - result = ac_func(window, input); - if (result) { - g_hash_table_destroy(ac_funcs); - return result; - } - } - g_hash_table_destroy(ac_funcs); - - result = plugins_autocomplete(input); - if (result) { - return result; - } - - if (g_str_has_prefix(input, "/field")) { - result = _form_field_autocomplete(window, input); - if (result) { - return result; - } - } - - return NULL; -} - -static char* -_sub_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - result = autocomplete_param_with_func(input, "/sub allow", presence_sub_request_find); - if (result) { - return result; - } - result = autocomplete_param_with_func(input, "/sub deny", presence_sub_request_find); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/sub", sub_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_tray_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - result = autocomplete_param_with_func(input, "/tray read", prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/tray", tray_ac, FALSE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_who_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - if (window->type == WIN_MUC) { - result = autocomplete_param_with_ac(input, "/who", who_room_ac, TRUE); - if (result) { - return result; - } - } else { - jabber_conn_status_t conn_status = connection_get_status(); - if (conn_status == JABBER_CONNECTED) { - int i = 0; - gchar *group_commands[] = { "/who any", "/who online", "/who offline", - "/who chat", "/who away", "/who xa", "/who dnd", "/who available", - "/who unavailable" }; - - for (i = 0; i < ARRAY_SIZE(group_commands); i++) { - result = autocomplete_param_with_func(input, group_commands[i], roster_group_autocomplete); - if (result) { - return result; - } - } - } - - result = autocomplete_param_with_ac(input, "/who", who_roster_ac, TRUE); - if (result) { - return result; - } - } - - return result; -} - -static char* -_roster_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - result = autocomplete_param_with_ac(input, "/roster room private char", roster_char_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster room private", roster_header_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster header char", roster_char_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster contact char", roster_char_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster room char", roster_char_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster private char", roster_char_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster resource char", roster_char_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_func(input, "/roster resource join", prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster room position", roster_room_position_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster room by", roster_room_by_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster room order", roster_room_order_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster room unread", roster_unread_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_func(input, "/roster count zero", prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - - jabber_conn_status_t conn_status = connection_get_status(); - if (conn_status == JABBER_CONNECTED) { - result = autocomplete_param_with_func(input, "/roster nick", roster_barejid_autocomplete); - if (result) { - return result; - } - result = autocomplete_param_with_func(input, "/roster clearnick", roster_barejid_autocomplete); - if (result) { - return result; - } - result = autocomplete_param_with_func(input, "/roster remove", roster_barejid_autocomplete); - if (result) { - return result; - } - } - - result = autocomplete_param_with_ac(input, "/roster remove_all", roster_remove_all_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster show", roster_show_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster hide", roster_show_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster by", roster_by_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster count", roster_count_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster order", roster_order_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster unread", roster_unread_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster room", roster_room_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_func(input, "/roster wrap", prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster header", roster_header_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster contact", roster_contact_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster resource", roster_resource_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster presence", roster_presence_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster private", roster_private_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/roster", roster_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_group_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - jabber_conn_status_t conn_status = connection_get_status(); - - if (conn_status == JABBER_CONNECTED) { - result = autocomplete_param_with_func(input, "/group show", roster_group_autocomplete); - if (result) { - return result; - } - result = autocomplete_param_no_with_func(input, "/group add", 4, roster_contact_autocomplete); - if (result) { - return result; - } - result = autocomplete_param_no_with_func(input, "/group remove", 4, roster_contact_autocomplete); - if (result) { - return result; - } - result = autocomplete_param_with_func(input, "/group add", roster_group_autocomplete); - if (result) { - return result; - } - result = autocomplete_param_with_func(input, "/group remove", roster_group_autocomplete); - if (result) { - return result; - } - } - - result = autocomplete_param_with_ac(input, "/group", group_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_blocked_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - result = autocomplete_param_with_func(input, "/blocked remove", blocked_ac_find); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/blocked", blocked_ac, FALSE); - if (result) { - return result; - } - - return NULL; -} - - -static char* -_bookmark_autocomplete(ProfWin *window, const char *const input) -{ - char *found = NULL; - - gboolean result; - gchar **args = parse_args(input, 3, 8, &result); - gboolean handle_options = result && (g_strv_length(args) > 2); - - if (handle_options && ((strcmp(args[0], "add") == 0) || (strcmp(args[0], "update") == 0)) ) { - GString *beginning = g_string_new("/bookmark"); - gboolean autojoin = FALSE; - int num_args = g_strv_length(args); - - g_string_append(beginning, " "); - g_string_append(beginning, args[0]); - g_string_append(beginning, " "); - g_string_append(beginning, args[1]); - if (num_args == 4 && g_strcmp0(args[2], "autojoin") == 0) { - g_string_append(beginning, " "); - g_string_append(beginning, args[2]); - autojoin = TRUE; - } - - if (num_args > 4) { - g_string_append(beginning, " "); - g_string_append(beginning, args[2]); - g_string_append(beginning, " "); - g_string_append(beginning, args[3]); - if (num_args == 6 && g_strcmp0(args[4], "autojoin") == 0) { - g_string_append(beginning, " "); - g_string_append(beginning, args[4]); - autojoin = TRUE; - } - } - - if (num_args > 6) { - g_string_append(beginning, " "); - g_string_append(beginning, args[4]); - g_string_append(beginning, " "); - g_string_append(beginning, args[5]); - if (num_args == 8 && g_strcmp0(args[6], "autojoin") == 0) { - g_string_append(beginning, " "); - g_string_append(beginning, args[6]); - autojoin = TRUE; - } - } - - if (autojoin) { - found = autocomplete_param_with_func(input, beginning->str, prefs_autocomplete_boolean_choice); - } else { - found = autocomplete_param_with_ac(input, beginning->str, bookmark_property_ac, TRUE); - } - g_string_free(beginning, TRUE); - if (found) { - g_strfreev(args); - return found; - } - } - - g_strfreev(args); - - found = autocomplete_param_with_func(input, "/bookmark remove", bookmark_find); - if (found) { - return found; - } - found = autocomplete_param_with_func(input, "/bookmark join", bookmark_find); - if (found) { - return found; - } - found = autocomplete_param_with_func(input, "/bookmark update", bookmark_find); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/bookmark", bookmark_ac, TRUE); - return found; -} - -static char* -_notify_autocomplete(ProfWin *window, const char *const input) -{ - int i = 0; - char *result = NULL; - - result = autocomplete_param_with_func(input, "/notify room trigger remove", prefs_autocomplete_room_trigger); - if (result) { - return result; - } - - gchar *boolean_choices1[] = { "/notify room current", "/notify chat current", "/notify typing current", - "/notify room text", "/notify chat text" }; - for (i = 0; i < ARRAY_SIZE(boolean_choices1); i++) { - result = autocomplete_param_with_func(input, boolean_choices1[i], prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - } - - result = autocomplete_param_with_ac(input, "/notify room mention", notify_mention_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/notify room trigger", notify_trigger_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/notify room", notify_room_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/notify chat", notify_chat_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/notify typing", notify_typing_ac, TRUE); - if (result) { - return result; - } - - gchar *boolean_choices2[] = { "/notify invite", "/notify sub", "/notify mention", "/notify trigger"}; - for (i = 0; i < ARRAY_SIZE(boolean_choices2); i++) { - result = autocomplete_param_with_func(input, boolean_choices2[i], prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - } - - result = autocomplete_param_with_ac(input, "/notify", notify_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_autoaway_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - result = autocomplete_param_with_ac(input, "/autoaway mode", autoaway_mode_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/autoaway time", autoaway_presence_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/autoaway message", autoaway_presence_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_func(input, "/autoaway check", prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/autoaway", autoaway_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_log_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - result = autocomplete_param_with_func(input, "/log rotate", - prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - result = autocomplete_param_with_func(input, "/log shared", - prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/log", log_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_autoconnect_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - result = autocomplete_param_with_func(input, "/autoconnect set", accounts_find_enabled); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/autoconnect", autoconnect_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_otr_autocomplete(ProfWin *window, const char *const input) -{ - char *found = NULL; - - jabber_conn_status_t conn_status = connection_get_status(); - - if (conn_status == JABBER_CONNECTED) { - found = autocomplete_param_with_func(input, "/otr start", roster_contact_autocomplete); - if (found) { - return found; - } - } - - found = autocomplete_param_with_ac(input, "/otr log", otr_log_ac, TRUE); - if (found) { - return found; - } - - // /otr policy always user@server.com - if (conn_status == JABBER_CONNECTED) { - gboolean result; - gchar **args = parse_args(input, 3, 3, &result); - if (result && (strcmp(args[0], "policy") == 0)) { - GString *beginning = g_string_new("/otr "); - g_string_append(beginning, args[0]); - g_string_append(beginning, " "); - g_string_append(beginning, args[1]); - - found = autocomplete_param_with_func(input, beginning->str, roster_contact_autocomplete); - g_string_free(beginning, TRUE); - if (found) { - g_strfreev(args); - return found; - } - } - g_strfreev(args); - } - - found = autocomplete_param_with_ac(input, "/otr policy", otr_policy_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/otr", otr_ac, TRUE); - if (found) { - return found; - } - - return NULL; -} - -static char* -_pgp_autocomplete(ProfWin *window, const char *const input) -{ - char *found = NULL; - - jabber_conn_status_t conn_status = connection_get_status(); - - if (conn_status == JABBER_CONNECTED) { - found = autocomplete_param_with_func(input, "/pgp start", roster_contact_autocomplete); - if (found) { - return found; - } - } - - found = autocomplete_param_with_ac(input, "/pgp log", pgp_log_ac, TRUE); - if (found) { - return found; - } - -#ifdef HAVE_LIBGPGME - gboolean result; - gchar **args = parse_args(input, 2, 3, &result); - if ((strncmp(input, "/pgp", 4) == 0) && (result == TRUE)) { - GString *beginning = g_string_new("/pgp "); - g_string_append(beginning, args[0]); - if (args[1]) { - g_string_append(beginning, " "); - g_string_append(beginning, args[1]); - } - found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key); - g_string_free(beginning, TRUE); - if (found) { - g_strfreev(args); - return found; - } - } - g_strfreev(args); -#endif - - if (conn_status == JABBER_CONNECTED) { - found = autocomplete_param_with_func(input, "/pgp setkey", roster_barejid_autocomplete); - if (found) { - return found; - } - } - - found = autocomplete_param_with_ac(input, "/pgp", pgp_ac, TRUE); - if (found) { - return found; - } - - return NULL; -} - -static char* -_plugins_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - if ((strncmp(input, "/plugins load ", 14) == 0) && (strlen(input) > 14)) { - if (plugins_load_ac == NULL) { - plugins_load_ac = autocomplete_new(); - GSList *plugins = plugins_unloaded_list(); - GSList *curr = plugins; - while (curr) { - autocomplete_add(plugins_load_ac, curr->data); - curr = g_slist_next(curr); - } - g_slist_free_full(plugins, g_free); - } - result = autocomplete_param_with_ac(input, "/plugins load", plugins_load_ac, TRUE); - if (result) { - return result; - } - } - result = autocomplete_param_with_ac(input, "/plugins", plugins_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_theme_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - if ((strncmp(input, "/theme load ", 12) == 0) && (strlen(input) > 12)) { - if (theme_load_ac == NULL) { - theme_load_ac = autocomplete_new(); - GSList *themes = theme_list(); - GSList *curr = themes; - while (curr) { - autocomplete_add(theme_load_ac, curr->data); - curr = g_slist_next(curr); - } - g_slist_free_full(themes, g_free); - autocomplete_add(theme_load_ac, "default"); - } - result = autocomplete_param_with_ac(input, "/theme load", theme_load_ac, TRUE); - if (result) { - return result; - } - } - result = autocomplete_param_with_ac(input, "/theme", theme_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_script_autocomplete_func(const char *const prefix) -{ - if (script_show_ac == NULL) { - script_show_ac = autocomplete_new(); - GSList *scripts = scripts_list(); - GSList *curr = scripts; - while (curr) { - autocomplete_add(script_show_ac, curr->data); - curr = g_slist_next(curr); - } - g_slist_free_full(scripts, g_free); - } - - return autocomplete_complete(script_show_ac, prefix, FALSE); -} - - -static char* -_script_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - if ((strncmp(input, "/script show ", 13) == 0) && (strlen(input) > 13)) { - result = autocomplete_param_with_func(input, "/script show", _script_autocomplete_func); - if (result) { - return result; - } - } - - if ((strncmp(input, "/script run ", 12) == 0) && (strlen(input) > 12)) { - result = autocomplete_param_with_func(input, "/script run", _script_autocomplete_func); - if (result) { - return result; - } - } - - result = autocomplete_param_with_ac(input, "/script", script_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_resource_autocomplete(ProfWin *window, const char *const input) -{ - char *found = NULL; - - jabber_conn_status_t conn_status = connection_get_status(); - if (conn_status == JABBER_CONNECTED && window->type == WIN_CHAT) { - ProfChatWin *chatwin = (ProfChatWin*)window; - assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); - PContact contact = roster_get_contact(chatwin->barejid); - if (contact) { - Autocomplete ac = p_contact_resource_ac(contact); - found = autocomplete_param_with_ac(input, "/resource set", ac, FALSE); - if (found) { - return found; - } - } - } - - found = autocomplete_param_with_func(input, "/resource title", prefs_autocomplete_boolean_choice); - if (found) { - return found; - } - - found = autocomplete_param_with_func(input, "/resource message", prefs_autocomplete_boolean_choice); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/resource", resource_ac, FALSE); - if (found) { - return found; - } - - return NULL; -} - -static char* -_titlebar_autocomplete(ProfWin *window, const char *const input) -{ - char *found = NULL; - - found = autocomplete_param_with_func(input, "/titlebar show", prefs_autocomplete_boolean_choice); - if (found) { - return found; - } - - found = autocomplete_param_with_func(input, "/titlebar goodbye", prefs_autocomplete_boolean_choice); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/titlebar", titlebar_ac, FALSE); - if (found) { - return found; - } - - return NULL; -} - -static char* -_inpblock_autocomplete(ProfWin *window, const char *const input) -{ - char *found = NULL; - - found = autocomplete_param_with_func(input, "/inpblock dynamic", prefs_autocomplete_boolean_choice); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/inpblock", inpblock_ac, FALSE); - if (found) { - return found; - } - - return NULL; -} - -static char* -_form_autocomplete(ProfWin *window, const char *const input) -{ - if (window->type != WIN_MUC_CONFIG) { - return NULL; - } - - char *found = NULL; - - ProfMucConfWin *confwin = (ProfMucConfWin*)window; - DataForm *form = confwin->form; - if (form) { - found = autocomplete_param_with_ac(input, "/form help", form->tag_ac, TRUE); - if (found) { - return found; - } - } - - found = autocomplete_param_with_ac(input, "/form", form_ac, TRUE); - if (found) { - return found; - } - - return NULL; -} - -static char* -_form_field_autocomplete(ProfWin *window, const char *const input) -{ - if (window->type != WIN_MUC_CONFIG) { - return NULL; - } - - char *found = NULL; - - ProfMucConfWin *confwin = (ProfMucConfWin*)window; - DataForm *form = confwin->form; - if (form == NULL) { - return NULL; - } - - gchar **split = g_strsplit(input, " ", 0); - - if (g_strv_length(split) == 3) { - char *field_tag = split[0]+1; - if (form_tag_exists(form, field_tag)) { - form_field_type_t field_type = form_get_field_type(form, field_tag); - Autocomplete value_ac = form_get_value_ac(form, field_tag);; - GString *beginning = g_string_new(split[0]); - g_string_append(beginning, " "); - g_string_append(beginning, split[1]); - - if (((g_strcmp0(split[1], "add") == 0) || (g_strcmp0(split[1], "remove") == 0)) - && field_type == FIELD_LIST_MULTI) { - found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE); - - } else if ((g_strcmp0(split[1], "remove") == 0) && field_type == FIELD_TEXT_MULTI) { - found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE); - - } else if ((g_strcmp0(split[1], "remove") == 0) && field_type == FIELD_JID_MULTI) { - found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE); - } - - g_string_free(beginning, TRUE); - } - - } else if (g_strv_length(split) == 2) { - char *field_tag = split[0]+1; - if (form_tag_exists(form, field_tag)) { - form_field_type_t field_type = form_get_field_type(form, field_tag); - Autocomplete value_ac = form_get_value_ac(form, field_tag);; - - switch (field_type) - { - case FIELD_BOOLEAN: - found = autocomplete_param_with_func(input, split[0], prefs_autocomplete_boolean_choice); - break; - case FIELD_LIST_SINGLE: - found = autocomplete_param_with_ac(input, split[0], value_ac, TRUE); - break; - case FIELD_LIST_MULTI: - case FIELD_JID_MULTI: - case FIELD_TEXT_MULTI: - found = autocomplete_param_with_ac(input, split[0], form_field_multi_ac, TRUE); - break; - default: - break; - } - } - } - - g_strfreev(split); - - return found; -} - -static char* -_occupants_autocomplete(ProfWin *window, const char *const input) -{ - char *found = NULL; - - found = autocomplete_param_with_ac(input, "/occupants default show", occupants_show_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/occupants default hide", occupants_show_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/occupants default", occupants_default_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/occupants show", occupants_show_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/occupants hide", occupants_show_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/occupants", occupants_ac, TRUE); - if (found) { - return found; - } - - return NULL; -} - -static char* -_time_autocomplete(ProfWin *window, const char *const input) -{ - char *found = NULL; - - found = autocomplete_param_with_ac(input, "/time statusbar", time_format_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/time lastactivity", time_format_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/time console", time_format_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/time chat", time_format_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/time muc", time_format_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/time mucconfig", time_format_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/time private", time_format_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/time xml", time_format_ac, TRUE); - if (found) { - return found; - } - - found = autocomplete_param_with_ac(input, "/time", time_ac, TRUE); - if (found) { - return found; - } - - return NULL; -} - -static char* -_kick_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - if (window->type == WIN_MUC) { - ProfMucWin *mucwin = (ProfMucWin*)window; - assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); - Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid); - - if (nick_ac) { - result = autocomplete_param_with_ac(input, "/kick", nick_ac, TRUE); - if (result) { - return result; - } - } - } - - return result; -} - -static char* -_ban_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - if (window->type == WIN_MUC) { - ProfMucWin *mucwin = (ProfMucWin*)window; - assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); - Autocomplete jid_ac = muc_roster_jid_ac(mucwin->roomjid); - - if (jid_ac) { - result = autocomplete_param_with_ac(input, "/ban", jid_ac, TRUE); - if (result) { - return result; - } - } - } - - return result; -} - -static char* -_affiliation_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - if (window->type == WIN_MUC) { - ProfMucWin *mucwin = (ProfMucWin*)window; - assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); - gboolean parse_result; - Autocomplete jid_ac = muc_roster_jid_ac(mucwin->roomjid); - - gchar **args = parse_args(input, 3, 3, &parse_result); - - if ((strncmp(input, "/affiliation", 12) == 0) && (parse_result == TRUE)) { - GString *beginning = g_string_new("/affiliation "); - g_string_append(beginning, args[0]); - g_string_append(beginning, " "); - g_string_append(beginning, args[1]); - - result = autocomplete_param_with_ac(input, beginning->str, jid_ac, TRUE); - g_string_free(beginning, TRUE); - if (result) { - g_strfreev(args); - return result; - } - } - - g_strfreev(args); - } - - result = autocomplete_param_with_ac(input, "/affiliation set", affiliation_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/affiliation list", affiliation_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/affiliation", privilege_cmd_ac, TRUE); - if (result) { - return result; - } - - return result; -} - -static char* -_role_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - if (window->type == WIN_MUC) { - ProfMucWin *mucwin = (ProfMucWin*)window; - assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); - gboolean parse_result; - Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid); - - gchar **args = parse_args(input, 3, 3, &parse_result); - - if ((strncmp(input, "/role", 5) == 0) && (parse_result == TRUE)) { - GString *beginning = g_string_new("/role "); - g_string_append(beginning, args[0]); - g_string_append(beginning, " "); - g_string_append(beginning, args[1]); - - result = autocomplete_param_with_ac(input, beginning->str, nick_ac, TRUE); - g_string_free(beginning, TRUE); - if (result) { - g_strfreev(args); - return result; - } - } - - g_strfreev(args); - } - - result = autocomplete_param_with_ac(input, "/role set", role_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/role list", role_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/role", privilege_cmd_ac, TRUE); - if (result) { - return result; - } - - return result; -} - -static char* -_statuses_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - result = autocomplete_param_with_ac(input, "/statuses console", statuses_setting_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/statuses chat", statuses_setting_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/statuses muc", statuses_setting_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/statuses", statuses_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_wins_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - result = autocomplete_param_with_func(input, "/wins autotidy", prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/wins", wins_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_tls_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - result = autocomplete_param_with_func(input, "/tls revoke", tlscerts_complete); - if (result) { - return result; - } - - result = autocomplete_param_with_func(input, "/tls cert", tlscerts_complete); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/tls certpath", tls_certpath_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_func(input, "/tls show", prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/tls", tls_ac, TRUE); - if (result) { - return result; - } - - return result; -} - -static char* -_receipts_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - result = autocomplete_param_with_func(input, "/receipts send", prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - - result = autocomplete_param_with_func(input, "/receipts request", prefs_autocomplete_boolean_choice); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/receipts", receipts_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_alias_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - result = autocomplete_param_with_ac(input, "/alias remove", aliases_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/alias", alias_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_connect_autocomplete(ProfWin *window, const char *const input) -{ - char *found = NULL; - gboolean result = FALSE; - - gchar **args = parse_args(input, 2, 6, &result); - - if ((strncmp(input, "/connect", 8) == 0) && (result == TRUE)) { - GString *beginning = g_string_new("/connect "); - g_string_append(beginning, args[0]); - if (args[1] && args[2]) { - g_string_append(beginning, " "); - g_string_append(beginning, args[1]); - g_string_append(beginning, " "); - g_string_append(beginning, args[2]); - if (args[3] && args[4]) { - g_string_append(beginning, " "); - g_string_append(beginning, args[3]); - g_string_append(beginning, " "); - g_string_append(beginning, args[4]); - } - } - found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE); - g_string_free(beginning, TRUE); - if (found) { - g_strfreev(args); - return found; - } - } - - g_strfreev(args); - - result = FALSE; - args = parse_args(input, 2, 7, &result); - - if ((strncmp(input, "/connect", 8) == 0) && (result == TRUE)) { - GString *beginning = g_string_new("/connect "); - g_string_append(beginning, args[0]); - int curr = 0; - if (args[1]) { - g_string_append(beginning, " "); - g_string_append(beginning, args[1]); - curr = 1; - if (args[2] && args[3]) { - g_string_append(beginning, " "); - g_string_append(beginning, args[2]); - g_string_append(beginning, " "); - g_string_append(beginning, args[3]); - curr = 3; - if (args[4] && args[5]) { - g_string_append(beginning, " "); - g_string_append(beginning, args[4]); - g_string_append(beginning, " "); - g_string_append(beginning, args[5]); - curr = 5; - } - } - } - if (curr != 0 && (g_strcmp0(args[curr], "tls") == 0)) { - found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE); - g_string_free(beginning, TRUE); - if (found) { - g_strfreev(args); - return found; - } - } else { - g_string_free(beginning, TRUE); - } - } - - g_strfreev(args); - - found = autocomplete_param_with_func(input, "/connect", accounts_find_enabled); - if (found) { - return found; - } - - return NULL; -} - -static char* -_help_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - result = autocomplete_param_with_ac(input, "/help commands", help_commands_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/help", help_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_join_autocomplete(ProfWin *window, const char *const input) -{ - char *found = NULL; - gboolean result = FALSE; - - found = autocomplete_param_with_func(input, "/join", bookmark_find); - if (found) { - return found; - } - - gchar **args = parse_args(input, 2, 4, &result); - - if ((strncmp(input, "/join", 5) == 0) && (result == TRUE)) { - GString *beginning = g_string_new("/join "); - g_string_append(beginning, args[0]); - if (args[1] && args[2]) { - g_string_append(beginning, " "); - g_string_append(beginning, args[1]); - g_string_append(beginning, " "); - g_string_append(beginning, args[2]); - } - found = autocomplete_param_with_ac(input, beginning->str, join_property_ac, TRUE); - g_string_free(beginning, TRUE); - if (found) { - g_strfreev(args); - return found; - } - } - - g_strfreev(args); - - return NULL; -} - -static char* -_console_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - result = autocomplete_param_with_ac(input, "/console chat", console_msg_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/console muc", console_msg_ac, TRUE); - if (result) { - return result; - } - result = autocomplete_param_with_ac(input, "/console private", console_msg_ac, TRUE); - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/console", console_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_win_autocomplete(ProfWin *window, const char *const input) -{ - char *found = NULL; - - found = autocomplete_param_with_func(input, "/win", win_autocomplete); - if (found) { - return found; - } - - return NULL; -} - -static char* -_close_autocomplete(ProfWin *window, const char *const input) -{ - char *found = NULL; - - found = autocomplete_param_with_func(input, "/close", win_close_autocomplete); - if (found) { - return found; - } - - return NULL; -} - -static char* -_sendfile_autocomplete(ProfWin *window, const char *const input) -{ - static char* last_directory = NULL; - - unsigned int output_off = 0; - - char *result = NULL; - char *tmp; - - // strip command - char *inpcp = (char*)input + 9; - while (*inpcp == ' ') { - inpcp++; - } - - inpcp = strdup(inpcp); - - // strip quotes - if (*inpcp == '"') { - tmp = strchr(inpcp+1, '"'); - if (tmp) { - *tmp = '\0'; - } - tmp = strdup(inpcp+1); - free(inpcp); - inpcp = tmp; - } - - // expand ~ to $HOME - if (inpcp[0] == '~' && inpcp[1] == '/') { - if (asprintf(&tmp, "%s/%sfoo", getenv("HOME"), inpcp+2) == -1) { - return NULL; - } - output_off = strlen(getenv("HOME"))+1; - } else { - if (asprintf(&tmp, "%sfoo", inpcp) == -1) { - return NULL; - } - } - free(inpcp); - inpcp = tmp; - - char* inpcp2 = strdup(inpcp); - char* foofile = strdup(basename(inpcp2)); - char* directory = strdup(dirname(inpcp)); - free(inpcp); - free(inpcp2); - - if (!last_directory || strcmp(last_directory, directory) != 0) { - free(last_directory); - last_directory = directory; - autocomplete_reset(sendfile_ac); - - struct dirent *dir; - - DIR *d = opendir(directory); - if (d) { - while ((dir = readdir(d)) != NULL) { - if (strcmp(dir->d_name, ".") == 0) { - continue; - } else if (strcmp(dir->d_name, "..") == 0) { - continue; - } else if (*(dir->d_name) == '.' && *foofile != '.') { - // only show hidden files on explicit request - continue; - } - char * acstring; - if (output_off) { - if (asprintf(&tmp, "%s/%s", directory, dir->d_name) == -1) { - return NULL; - } - if (asprintf(&acstring, "~/%s", tmp+output_off) == -1) { - return NULL; - } - free(tmp); - } else if (strcmp(directory, "/") == 0) { - if (asprintf(&acstring, "/%s", dir->d_name) == -1) { - return NULL; - } - } else { - if (asprintf(&acstring, "%s/%s", directory, dir->d_name) == -1) { - return NULL; - } - } - autocomplete_add(sendfile_ac, acstring); - free(acstring); - } - closedir(d); - } - } else { - free(foofile); - free(directory); - } - - result = autocomplete_param_with_ac(input, "/sendfile", sendfile_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - - -static char* -_subject_autocomplete(ProfWin *window, const char *const input) -{ - char *result = NULL; - - if (window->type == WIN_MUC) { - if ((g_strcmp0(input, "/subject e") == 0) - || (g_strcmp0(input, "/subject ed") == 0) - || (g_strcmp0(input, "/subject edi") == 0) - || (g_strcmp0(input, "/subject edit") == 0) - || (g_strcmp0(input, "/subject edit ") == 0) - || (g_strcmp0(input, "/subject edit \"") == 0)) { - ProfMucWin *mucwin = (ProfMucWin*)window; - assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); - - char *subject = muc_subject(mucwin->roomjid); - if (subject) { - GString *result_str = g_string_new("/subject edit \""); - g_string_append(result_str, subject); - g_string_append(result_str, "\""); - - result = result_str->str; - g_string_free(result_str, FALSE); - } - } - } - if (result) { - return result; - } - - result = autocomplete_param_with_ac(input, "/subject", subject_ac, TRUE); - if (result) { - return result; - } - - return NULL; -} - -static char* -_account_autocomplete(ProfWin *window, const char *const input) -{ - char *found = NULL; - gboolean result = FALSE; - - gchar **args = parse_args(input, 3, 4, &result); - - if ((strncmp(input, "/account set", 12) == 0) && (result == TRUE)) { - GString *beginning = g_string_new("/account set "); - g_string_append(beginning, args[1]); - if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "otr")) == 0) { - g_string_append(beginning, " "); - g_string_append(beginning, args[2]); - found = autocomplete_param_with_ac(input, beginning->str, otr_policy_ac, TRUE); - g_string_free(beginning, TRUE); - if (found) { - g_strfreev(args); - return found; - } - } else if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "status")) == 0) { - g_string_append(beginning, " "); - g_string_append(beginning, args[2]); - found = autocomplete_param_with_ac(input, beginning->str, account_status_ac, TRUE); - g_string_free(beginning, TRUE); - if (found) { - g_strfreev(args); - return found; - } - } else if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "tls")) == 0) { - g_string_append(beginning, " "); - g_string_append(beginning, args[2]); - found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE); - g_string_free(beginning, TRUE); - if (found) { - g_strfreev(args); - return found; - } - } else if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "startscript")) == 0) { - g_string_append(beginning, " "); - g_string_append(beginning, args[2]); - found = autocomplete_param_with_func(input, beginning->str, _script_autocomplete_func); - g_string_free(beginning, TRUE); - if (found) { - g_strfreev(args); - return found; - } - } else if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "theme")) == 0) { - g_string_append(beginning, " "); - g_string_append(beginning, args[2]); - if (theme_load_ac == NULL) { - theme_load_ac = autocomplete_new(); - GSList *themes = theme_list(); - GSList *curr = themes; - while (curr) { - autocomplete_add(theme_load_ac, curr->data); - curr = g_slist_next(curr); - } - g_slist_free_full(themes, g_free); - autocomplete_add(theme_load_ac, "default"); - } - found = autocomplete_param_with_ac(input, beginning->str, theme_load_ac, TRUE); - g_string_free(beginning, TRUE); - if (found) { - return found; - } -#ifdef HAVE_LIBGPGME - } else if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "pgpkeyid")) == 0) { - g_string_append(beginning, " "); - g_string_append(beginning, args[2]); - found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key); - g_string_free(beginning, TRUE); - if (found) { - g_strfreev(args); - return found; - } -#endif - } else { - found = autocomplete_param_with_ac(input, beginning->str, account_set_ac, TRUE); - g_string_free(beginning, TRUE); - if (found) { - g_strfreev(args); - return found; - } - } - } - - if ((strncmp(input, "/account clear", 14) == 0) && (result == TRUE)) { - GString *beginning = g_string_new("/account clear "); - g_string_append(beginning, args[1]); - found = autocomplete_param_with_ac(input, beginning->str, account_clear_ac, TRUE); - g_string_free(beginning, TRUE); - if (found) { - g_strfreev(args); - return found; - } - } - - g_strfreev(args); - - found = autocomplete_param_with_ac(input, "/account default", account_default_ac, TRUE); - if(found){ - return found; - } - - int i = 0; - gchar *account_choice[] = { "/account set", "/account show", "/account enable", - "/account disable", "/account rename", "/account clear", "/account remove", - "/account default set" }; - - for (i = 0; i < ARRAY_SIZE(account_choice); i++) { - found = autocomplete_param_with_func(input, account_choice[i], accounts_find_all); - if (found) { - return found; - } - } - - found = autocomplete_param_with_ac(input, "/account", account_ac, TRUE); - return found; -} - -static int -_cmp_command(Command *cmd1, Command *cmd2) -{ - return g_strcmp0(cmd1->cmd, cmd2->cmd); -} - -void -command_docgen(void) -{ - GList *cmds = NULL; - unsigned int i; - for (i = 0; i < ARRAY_SIZE(command_defs); i++) { - Command *pcmd = command_defs+i; - cmds = g_list_insert_sorted(cmds, pcmd, (GCompareFunc)_cmp_command); - } - - FILE *toc_fragment = fopen("toc_fragment.html", "w"); - FILE *main_fragment = fopen("main_fragment.html", "w"); - - fputs("<ul><li><ul><li>\n", toc_fragment); - fputs("<hr>\n", main_fragment); - - GList *curr = cmds; - while (curr) { - Command *pcmd = curr->data; - - fprintf(toc_fragment, "<a href=\"#%s\">%s</a>,\n", &pcmd->cmd[1], pcmd->cmd); - fprintf(main_fragment, "<a name=\"%s\"></a>\n", &pcmd->cmd[1]); - fprintf(main_fragment, "<h4>%s</h4>\n", pcmd->cmd); - - fputs("<p><b>Synopsis</b></p>\n", main_fragment); - fputs("<p><pre><code>", main_fragment); - int i = 0; - while (pcmd->help.synopsis[i]) { - char *str1 = str_replace(pcmd->help.synopsis[i], "<", "<"); - char *str2 = str_replace(str1, ">", ">"); - fprintf(main_fragment, "%s\n", str2); - i++; - } - fputs("</code></pre></p>\n", main_fragment); - - fputs("<p><b>Description</b></p>\n", main_fragment); - fputs("<p>", main_fragment); - fprintf(main_fragment, "%s\n", pcmd->help.desc); - fputs("</p>\n", main_fragment); - - if (pcmd->help.args[0][0] != NULL) { - fputs("<p><b>Arguments</b></p>\n", main_fragment); - fputs("<table>", main_fragment); - for (i = 0; pcmd->help.args[i][0] != NULL; i++) { - fputs("<tr>", main_fragment); - fputs("<td>", main_fragment); - fputs("<code>", main_fragment); - char *str1 = str_replace(pcmd->help.args[i][0], "<", "<"); - char *str2 = str_replace(str1, ">", ">"); - fprintf(main_fragment, "%s", str2); - fputs("</code>", main_fragment); - fputs("</td>", main_fragment); - fputs("<td>", main_fragment); - fprintf(main_fragment, "%s", pcmd->help.args[i][1]); - fputs("</td>", main_fragment); - fputs("</tr>", main_fragment); - } - fputs("</table>\n", main_fragment); - } - - if (pcmd->help.examples[0] != NULL) { - fputs("<p><b>Examples</b></p>\n", main_fragment); - fputs("<p><pre><code>", main_fragment); - int i = 0; - while (pcmd->help.examples[i]) { - fprintf(main_fragment, "%s\n", pcmd->help.examples[i]); - i++; - } - fputs("</code></pre></p>\n", main_fragment); - } - - fputs("<a href=\"#top\"><h5>back to top</h5></a><br><hr>\n", main_fragment); - fputs("\n", main_fragment); - - curr = g_list_next(curr); - } - - fputs("</ul></ul>\n", toc_fragment); - - fclose(toc_fragment); - fclose(main_fragment); - printf("\nProcessed %d commands.\n\n", g_list_length(cmds)); - g_list_free(cmds); -} diff --git a/src/config/scripts.c b/src/config/scripts.c index 0f8800d8..945aaec2 100644 --- a/src/config/scripts.c +++ b/src/config/scripts.c @@ -43,7 +43,7 @@ #include "common.h" #include "log.h" #include "window_list.h" -#include "command/command.h" +#include "command/cmd_defs.h" #include "ui/ui.h" #include "xmpp/xmpp.h" diff --git a/src/main.c b/src/main.c index 7f87c165..b15293d0 100644 --- a/src/main.c +++ b/src/main.c @@ -43,7 +43,7 @@ #include "profanity.h" #include "common.h" -#include "command/command.h" +#include "command/cmd_defs.h" static gboolean version = FALSE; static char *log = "INFO"; diff --git a/src/plugins/api.c b/src/plugins/api.c index 0a4b04af..326ec61d 100644 --- a/src/plugins/api.c +++ b/src/plugins/api.c @@ -49,7 +49,7 @@ #include "profanity.h" #include "ui/ui.h" #include "config/theme.h" -#include "command/command.h" +#include "command/cmd_defs.h" #include "window_list.h" #include "common.h" diff --git a/src/plugins/callbacks.c b/src/plugins/callbacks.c index eaca342a..2572f7a4 100644 --- a/src/plugins/callbacks.c +++ b/src/plugins/callbacks.c @@ -35,7 +35,8 @@ #include <string.h> #include <stdlib.h> -#include "command/command.h" +#include "command/cmd_defs.h" +#include "command/cmd_ac.h" #include "plugins/callbacks.h" #include "plugins/plugins.h" #include "tools/autocomplete.h" @@ -72,9 +73,8 @@ void callbacks_add_command(PluginCommand *command) { p_commands = g_slist_append(p_commands, command); - cmd_autocomplete_add(command->command_name); - cmd_help_autocomplete_add(&command->command_name[1]); - + cmd_ac_add(command->command_name); + cmd_ac_add_help(&command->command_name[1]); } void diff --git a/src/plugins/callbacks.h b/src/plugins/callbacks.h index dc6b78bb..9b175d0a 100644 --- a/src/plugins/callbacks.h +++ b/src/plugins/callbacks.h @@ -37,7 +37,7 @@ #include <glib.h> -#include "command/command.h" +#include "command/cmd_defs.h" typedef struct p_command { const char *command_name; diff --git a/src/plugins/plugins.h b/src/plugins/plugins.h index b7eb4c80..b03248ab 100644 --- a/src/plugins/plugins.h +++ b/src/plugins/plugins.h @@ -35,7 +35,7 @@ #ifndef PLUGINS_H #define PLUGINS_H -#include "command/command.h" +#include "command/cmd_defs.h" typedef enum { LANG_PYTHON, diff --git a/src/profanity.c b/src/profanity.c index 56f242ef..c9e19fa8 100644 --- a/src/profanity.c +++ b/src/profanity.c @@ -55,7 +55,7 @@ #include "config/preferences.h" #include "config/theme.h" #include "config/scripts.h" -#include "command/command.h" +#include "command/cmd_defs.h" #include "common.h" #include "contact.h" #include "roster_list.h" diff --git a/src/ui/console.c b/src/ui/console.c index cae0d637..a5ff3a76 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -43,7 +43,7 @@ #include <ncurses.h> #endif -#include "command/command.h" +#include "command/cmd_defs.h" #include "common.h" #include "log.h" #include "muc.h" diff --git a/src/ui/core.c b/src/ui/core.c index 0b761274..3a89008f 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -55,7 +55,8 @@ #endif #include "chat_session.h" -#include "command/command.h" +#include "command/cmd_defs.h" +#include "command/cmd_ac.h" #include "common.h" #include "config/preferences.h" #include "config/theme.h" @@ -651,12 +652,12 @@ ui_focus_win(ProfWin *window) ProfWin *old_current = wins_get_current(); if (old_current->type == WIN_MUC_CONFIG) { ProfMucConfWin *confwin = (ProfMucConfWin*)old_current; - cmd_autocomplete_remove_form_fields(confwin->form); + cmd_ac_remove_form_fields(confwin->form); } if (window->type == WIN_MUC_CONFIG) { ProfMucConfWin *confwin = (ProfMucConfWin*)window; - cmd_autocomplete_add_form_fields(confwin->form); + cmd_ac_add_form_fields(confwin->form); } int i = wins_get_num(window); @@ -679,7 +680,7 @@ ui_close_win(int index) if (window && window->type == WIN_MUC_CONFIG) { ProfMucConfWin *confwin = (ProfMucConfWin*)window; if (confwin->form) { - cmd_autocomplete_remove_form_fields(confwin->form); + cmd_ac_remove_form_fields(confwin->form); } } diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c index 2c7eae34..8f896dbe 100644 --- a/src/ui/inputwin.c +++ b/src/ui/inputwin.c @@ -53,7 +53,7 @@ #include <ncurses.h> #endif -#include "command/command.h" +#include "command/cmd_ac.h" #include "common.h" #include "config/accounts.h" #include "config/preferences.h" @@ -452,7 +452,7 @@ _inp_rl_getc(FILE *stream) int ch = rl_getc(stream); if (_inp_printable(ch)) { ProfWin *window = wins_get_current(); - cmd_reset_autocomplete(window); + cmd_ac_reset(window); } return ch; } @@ -482,7 +482,7 @@ _inp_rl_tab_handler(int count, int key) } } else if (strncmp(rl_line_buffer, "/", 1) == 0) { ProfWin *window = wins_get_current(); - char *result = cmd_autocomplete(window, rl_line_buffer); + char *result = cmd_ac_complete(window, rl_line_buffer); if (result) { rl_replace_line(result, 1); rl_point = rl_end; diff --git a/src/ui/ui.h b/src/ui/ui.h index 18a5864f..2213ccc1 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -37,7 +37,7 @@ #include "config.h" -#include "command/commands.h" +#include "command/cmd_funcs.h" #include "ui/win_types.h" #include "muc.h" #include "config/tlscerts.h" diff --git a/tests/unittests/test_cmd_account.c b/tests/unittests/test_cmd_account.c index 74781177..0b723bde 100644 --- a/tests/unittests/test_cmd_account.c +++ b/tests/unittests/test_cmd_account.c @@ -13,7 +13,7 @@ #include "config/accounts.h" -#include "command/commands.h" +#include "command/cmd_funcs.h" #define CMD_ACCOUNT "/account" diff --git a/tests/unittests/test_cmd_alias.c b/tests/unittests/test_cmd_alias.c index fd8f824f..d1cdaf01 100644 --- a/tests/unittests/test_cmd_alias.c +++ b/tests/unittests/test_cmd_alias.c @@ -13,8 +13,9 @@ #include "config/preferences.h" -#include "command/command.h" -#include "command/commands.h" +#include "command/cmd_defs.h" +#include "command/cmd_funcs.h" +#include "command/cmd_ac.h" #define CMD_ALIAS "/alias" @@ -77,7 +78,7 @@ void cmd_alias_add_shows_message_when_exists(void **state) cmd_init(); prefs_add_alias("hc", "/help commands"); - cmd_autocomplete_add("/hc"); + cmd_ac_add("/hc"); expect_cons_show("Command or alias '/hc' already exists."); diff --git a/tests/unittests/test_cmd_bookmark.c b/tests/unittests/test_cmd_bookmark.c index 8b8b4871..5b17c6e0 100644 --- a/tests/unittests/test_cmd_bookmark.c +++ b/tests/unittests/test_cmd_bookmark.c @@ -14,7 +14,7 @@ #include "muc.h" #include "common.h" -#include "command/commands.h" +#include "command/cmd_funcs.h" #include "xmpp/bookmark.h" diff --git a/tests/unittests/test_cmd_connect.c b/tests/unittests/test_cmd_connect.c index e4f01271..b2511183 100644 --- a/tests/unittests/test_cmd_connect.c +++ b/tests/unittests/test_cmd_connect.c @@ -11,7 +11,7 @@ #include "ui/ui.h" #include "ui/stub_ui.h" -#include "command/commands.h" +#include "command/cmd_funcs.h" #include "config/accounts.h" #define CMD_CONNECT "/connect" diff --git a/tests/unittests/test_cmd_disconnect.c b/tests/unittests/test_cmd_disconnect.c index ba73adf5..9bf78a7a 100644 --- a/tests/unittests/test_cmd_disconnect.c +++ b/tests/unittests/test_cmd_disconnect.c @@ -6,7 +6,7 @@ #include <string.h> #include "chat_session.h" -#include "command/commands.h" +#include "command/cmd_funcs.h" #include "xmpp/xmpp.h" #include "roster_list.h" diff --git a/tests/unittests/test_cmd_join.c b/tests/unittests/test_cmd_join.c index 8b71c5e5..709b4145 100644 --- a/tests/unittests/test_cmd_join.c +++ b/tests/unittests/test_cmd_join.c @@ -13,7 +13,7 @@ #include "config/accounts.h" -#include "command/commands.h" +#include "command/cmd_funcs.h" #include "muc.h" #define CMD_JOIN "/join" diff --git a/tests/unittests/test_cmd_otr.c b/tests/unittests/test_cmd_otr.c index 44703943..ab03e7d4 100644 --- a/tests/unittests/test_cmd_otr.c +++ b/tests/unittests/test_cmd_otr.c @@ -15,8 +15,8 @@ #include "config/preferences.h" -#include "command/command.h" -#include "command/commands.h" +#include "command/cmd_defs.h" +#include "command/cmd_funcs.h" #include "window_list.h" #include "xmpp/xmpp.h" diff --git a/tests/unittests/test_cmd_pgp.c b/tests/unittests/test_cmd_pgp.c index ec010cce..b2a1aa7e 100644 --- a/tests/unittests/test_cmd_pgp.c +++ b/tests/unittests/test_cmd_pgp.c @@ -8,7 +8,7 @@ #include "config.h" -#include "command/commands.h" +#include "command/cmd_funcs.h" #include "xmpp/xmpp.h" #include "ui/stub_ui.h" diff --git a/tests/unittests/test_cmd_rooms.c b/tests/unittests/test_cmd_rooms.c index 85a528b5..2cb6be6b 100644 --- a/tests/unittests/test_cmd_rooms.c +++ b/tests/unittests/test_cmd_rooms.c @@ -12,7 +12,7 @@ #include "ui/stub_ui.h" #include "config/accounts.h" -#include "command/commands.h" +#include "command/cmd_funcs.h" #define CMD_ROOMS "/rooms" diff --git a/tests/unittests/test_cmd_roster.c b/tests/unittests/test_cmd_roster.c index 8b194de4..6628147d 100644 --- a/tests/unittests/test_cmd_roster.c +++ b/tests/unittests/test_cmd_roster.c @@ -11,7 +11,7 @@ #include "xmpp/xmpp.h" #include "roster_list.h" -#include "command/commands.h" +#include "command/cmd_funcs.h" #define CMD_ROSTER "/roster" diff --git a/tests/unittests/test_cmd_statuses.c b/tests/unittests/test_cmd_statuses.c index bd5337c3..f4d8c067 100644 --- a/tests/unittests/test_cmd_statuses.c +++ b/tests/unittests/test_cmd_statuses.c @@ -11,7 +11,7 @@ #include "ui/ui.h" #include "ui/stub_ui.h" -#include "command/commands.h" +#include "command/cmd_funcs.h" #define CMD_STATUSES "/statuses" diff --git a/tests/unittests/test_cmd_sub.c b/tests/unittests/test_cmd_sub.c index a89e82bf..4afe8752 100644 --- a/tests/unittests/test_cmd_sub.c +++ b/tests/unittests/test_cmd_sub.c @@ -11,7 +11,7 @@ #include "ui/ui.h" #include "ui/stub_ui.h" -#include "command/commands.h" +#include "command/cmd_funcs.h" #define CMD_SUB "/sub" |