diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | src/command/command.c | 2 | ||||
-rw-r--r-- | src/command/commands.c | 43 | ||||
-rw-r--r-- | src/config/preferences.c | 89 | ||||
-rw-r--r-- | src/config/preferences.h | 11 | ||||
-rw-r--r-- | src/ui/console.c | 16 | ||||
-rw-r--r-- | src/ui/ui.h | 1 | ||||
-rw-r--r-- | tests/test_cmd_alias.c | 150 | ||||
-rw-r--r-- | tests/test_cmd_alias.h | 8 | ||||
-rw-r--r-- | tests/testsuite.c | 22 | ||||
-rw-r--r-- | tests/ui/mock_ui.c | 19 | ||||
-rw-r--r-- | tests/ui/mock_ui.h | 3 |
12 files changed, 356 insertions, 9 deletions
diff --git a/Makefile.am b/Makefile.am index 933a44f6..5d5e3fba 100644 --- a/Makefile.am +++ b/Makefile.am @@ -77,6 +77,7 @@ test_sources = \ tests/test_cmd_account.c \ tests/test_cmd_rooms.c \ tests/test_cmd_sub.c \ + tests/test_cmd_alias.c \ tests/test_cmd_statuses.c \ tests/test_history.c \ tests/test_jid.c \ diff --git a/src/command/command.c b/src/command/command.c index 76f237cb..87161c4f 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -547,7 +547,7 @@ static struct cmd_t command_defs[] = NULL } } }, { "/alias", - cmd_alias, parse_args, 1, 3, &cons_alias_setting, + cmd_alias, parse_args_with_freetext, 1, 3, &cons_alias_setting, { "/alias add|remove|list [name value]", "Add your own command aliases.", { "/alias add|remove|list [name value]", "-----------------------------------", diff --git a/src/command/commands.c b/src/command/commands.c index 712d39d8..c4390966 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -1821,8 +1821,47 @@ cmd_nick(gchar **args, struct cmd_help_t help) gboolean cmd_alias(gchar **args, struct cmd_help_t help) { - cons_show("Alias command TODO"); - return TRUE; + char *subcmd = args[0]; + + if (strcmp(subcmd, "add") == 0) { + char *alias = args[1]; + if (alias == NULL) { + cons_show("Usage: %s", help.usage); + return TRUE; + } else { + char *value = args[2]; + if (value == NULL) { + cons_show("Usage: %s", help.usage); + return TRUE; + } else { + prefs_add_alias(alias, value); + cons_show("Command alias added /%s -> %s", alias, value); + return TRUE; + } + } + } else if (strcmp(subcmd, "remove") == 0) { + char *alias = args[1]; + if (alias == NULL) { + cons_show("Usage: %s", help.usage); + return TRUE; + } else { + gboolean removed = prefs_remove_alias(alias); + if (!removed) { + cons_show("No such command alias /%s", alias); + } else { + cons_show("Command alias removed -> /%s", alias); + } + return TRUE; + } + } else if (strcmp(subcmd, "list") == 0) { + GList *aliases = prefs_get_aliases(); + cons_show_aliases(aliases); + prefs_free_aliases(aliases); + return TRUE; + } else { + cons_show("Usage: %s", help.usage); + return TRUE; + } } gboolean diff --git a/src/config/preferences.c b/src/config/preferences.c index 3d5c9325..88e267f4 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -44,6 +44,7 @@ #define PREF_GROUP_NOTIFICATIONS "notifications" #define PREF_GROUP_PRESENCE "presence" #define PREF_GROUP_CONNECTION "connection" +#define PREF_GROUP_ALIAS "alias" static gchar *prefs_loc; static GKeyFile *prefs; @@ -259,6 +260,82 @@ prefs_set_autoaway_time(gint value) _save_prefs(); } +void +prefs_add_alias(const char * const name, const char * const value) +{ + g_key_file_set_string(prefs, PREF_GROUP_ALIAS, name, value); + _save_prefs(); +} + +char * +prefs_get_alias(const char * const name) +{ + return g_key_file_get_string(prefs, PREF_GROUP_ALIAS, name, NULL); + +} + +gboolean +prefs_remove_alias(const char * const name) +{ + if (!g_key_file_has_key(prefs, PREF_GROUP_ALIAS, name, NULL)) { + return FALSE; + } else { + g_key_file_remove_key(prefs, PREF_GROUP_ALIAS, name, NULL); + _save_prefs(); + return TRUE; + } +} + +static gint +_alias_cmp(gconstpointer *p1, gconstpointer *p2) +{ + ProfAlias *alias1 = (ProfAlias*)p1; + ProfAlias *alias2 = (ProfAlias*)p2; + + return strcmp(alias1->name, alias2->name); +} + +GList * +prefs_get_aliases(void) +{ + if (!g_key_file_has_group(prefs, PREF_GROUP_ALIAS)) { + return NULL; + } else { + GList *result = NULL; + gsize len; + gchar **keys = g_key_file_get_keys(prefs, PREF_GROUP_ALIAS, &len, NULL); + int i; + for (i = 0; i < len; i++) { + char *name = keys[i]; + char *value = g_key_file_get_string(prefs, PREF_GROUP_ALIAS, name, NULL); + + ProfAlias *alias = malloc(sizeof(struct prof_alias_t)); + alias->name = strdup(name); + alias->value = strdup(value); + + result = g_list_insert_sorted(result, alias, (GCompareFunc)_alias_cmp); + } + + g_strfreev(keys); + + return result; + } +} + +void +_free_alias(ProfAlias *alias) +{ + FREE_SET_NULL(alias->name); + FREE_SET_NULL(alias->value); + FREE_SET_NULL(alias); +} + +void +prefs_free_aliases(GList *aliases) +{ + g_list_free_full(aliases, (GDestroyNotify)_free_alias); +} + static void _save_prefs(void) { @@ -299,25 +376,25 @@ _get_group(preference_t pref) case PREF_STATUSES_CHAT: case PREF_STATUSES_MUC: case PREF_OTR_WARN: - return "ui"; + return PREF_GROUP_UI; case PREF_STATES: case PREF_OUTTYPE: - return "chatstates"; + return PREF_GROUP_CHATSTATES; case PREF_NOTIFY_TYPING: case PREF_NOTIFY_MESSAGE: case PREF_NOTIFY_INVITE: case PREF_NOTIFY_SUB: - return "notifications"; + return PREF_GROUP_NOTIFICATIONS; case PREF_CHLOG: case PREF_GRLOG: case PREF_OTR_LOG: - return "logging"; + return PREF_GROUP_LOGGING; case PREF_AUTOAWAY_CHECK: case PREF_AUTOAWAY_MODE: case PREF_AUTOAWAY_MESSAGE: - return "presence"; + return PREF_GROUP_PRESENCE; case PREF_CONNECT_ACCOUNT: - return "connection"; + return PREF_GROUP_CONNECTION; default: return NULL; } diff --git a/src/config/preferences.h b/src/config/preferences.h index cc9d63e1..22a175d4 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -65,6 +65,11 @@ typedef enum { PREF_OTR_WARN } preference_t; +typedef struct prof_alias_t { + gchar *name; + gchar *value; +} ProfAlias; + void prefs_load(void); void prefs_close(void); @@ -92,6 +97,12 @@ void prefs_set_autoaway_time(gint value); void prefs_add_login(const char *jid); +void prefs_add_alias(const char * const name, const char * const value); +gboolean prefs_remove_alias(const char * const name); +char* prefs_get_alias(const char * const name); +GList* prefs_get_aliases(void); +void prefs_free_aliases(GList *aliases); + gboolean prefs_get_boolean(preference_t pref); void prefs_set_boolean(preference_t pref, gboolean value); char * prefs_get_string(preference_t pref); diff --git a/src/ui/console.c b/src/ui/console.c index a79f438e..0a8b3be2 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -903,6 +903,21 @@ _cons_show_account(ProfAccount *account) } static void +_cons_show_aliases(GList *aliases) +{ + GList *curr = aliases; + if (curr != NULL) { + cons_show("Command aliases:"); + } + while (curr != NULL) { + ProfAlias *alias = curr->data; + cons_show(" /%s -> %s", alias->name, alias->value); + curr = g_list_next(curr); + } + cons_show(""); +} + +static void _cons_alias_setting(void) { cons_show("Alias setting TODO"); @@ -1645,4 +1660,5 @@ console_init_module(void) cons_alert = _cons_alert; cons_show_contact_online = _cons_show_contact_online; cons_show_contact_offline = _cons_show_contact_offline; + cons_show_aliases = _cons_show_aliases; } diff --git a/src/ui/ui.h b/src/ui/ui.h index 00d284f3..cdd25ced 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -183,6 +183,7 @@ void (*cons_show_status)(const char * const barejid); void (*cons_show_info)(PContact pcontact); void (*cons_show_caps)(const char * const contact, Resource *resource); void (*cons_show_themes)(GSList *themes); +void (*cons_show_aliases)(GList *aliases); void (*cons_show_login_success)(ProfAccount *account); void (*cons_show_software_version)(const char * const jid, const char * const presence, const char * const name, diff --git a/tests/test_cmd_alias.c b/tests/test_cmd_alias.c new file mode 100644 index 00000000..bdb16ede --- /dev/null +++ b/tests/test_cmd_alias.c @@ -0,0 +1,150 @@ +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> +#include <stdlib.h> +#include <string.h> +#include <glib.h> + +#include "xmpp/xmpp.h" +#include "xmpp/mock_xmpp.h" + +#include "ui/ui.h" +#include "ui/mock_ui.h" + +#include "config/preferences.h" + +#include "command/commands.h" + +void cmd_alias_add_shows_usage_when_no_args(void **state) +{ + mock_cons_show(); + CommandHelp *help = malloc(sizeof(CommandHelp)); + help->usage = "some usage"; + gchar *args[] = { "add", NULL }; + + expect_cons_show("Usage: some usage"); + + gboolean result = cmd_alias(args, *help); + assert_true(result); + + free(help); +} + +void cmd_alias_add_shows_usage_when_no_value(void **state) +{ + mock_cons_show(); + CommandHelp *help = malloc(sizeof(CommandHelp)); + help->usage = "some usage"; + gchar *args[] = { "add", "alias", NULL }; + + expect_cons_show("Usage: some usage"); + + gboolean result = cmd_alias(args, *help); + assert_true(result); + + free(help); +} + +void cmd_alias_remove_shows_usage_when_no_args(void **state) +{ + mock_cons_show(); + CommandHelp *help = malloc(sizeof(CommandHelp)); + help->usage = "some usage"; + gchar *args[] = { "remove", NULL }; + + expect_cons_show("Usage: some usage"); + + gboolean result = cmd_alias(args, *help); + assert_true(result); + + free(help); +} + +void cmd_alias_show_usage_when_invalid_subcmd(void **state) +{ + mock_cons_show(); + CommandHelp *help = malloc(sizeof(CommandHelp)); + help->usage = "some usage"; + gchar *args[] = { "blah", NULL }; + + expect_cons_show("Usage: some usage"); + + gboolean result = cmd_alias(args, *help); + assert_true(result); + + free(help); +} + +void cmd_alias_add_adds_alias(void **state) +{ + mock_cons_show(); + CommandHelp *help = malloc(sizeof(CommandHelp)); + gchar *args[] = { "add", "hc", "/help commands", NULL }; + + expect_cons_show("Command alias added /hc -> /help commands"); + + gboolean result = cmd_alias(args, *help); + + char *returned_val = prefs_get_alias("hc"); + + assert_true(result); + assert_string_equal("/help commands", returned_val); + + free(help); +} + +void cmd_alias_remove_removes_alias(void **state) +{ + mock_cons_show(); + CommandHelp *help = malloc(sizeof(CommandHelp)); + gchar *args[] = { "remove", "hn", NULL }; + + prefs_add_alias("hn", "/help navigation"); + + expect_cons_show("Command alias removed -> /hn"); + + gboolean result = cmd_alias(args, *help); + + char *returned_val = prefs_get_alias("hn"); + + assert_true(result); + assert_null(returned_val); + + free(help); +} + +void cmd_alias_remove_shows_message_when_no_alias(void **state) +{ + mock_cons_show(); + CommandHelp *help = malloc(sizeof(CommandHelp)); + gchar *args[] = { "remove", "hn", NULL }; + + expect_cons_show("No such command alias /hn"); + + gboolean result = cmd_alias(args, *help); + assert_true(result); + + free(help); +} + +void cmd_alias_list_shows_all_aliases(void **state) +{ + mock_cons_show_aliases(); + CommandHelp *help = malloc(sizeof(CommandHelp)); + gchar *args[] = { "list", NULL }; + + prefs_add_alias("vy", "/vercheck on"); + prefs_add_alias("q", "/quit"); + prefs_add_alias("hn", "/help navigation"); + prefs_add_alias("hc", "/help commands"); + prefs_add_alias("vn", "/vercheck off"); + + // write a custom checker to check the correct list is passed + expect_cons_show_aliases(); + + gboolean result = cmd_alias(args, *help); + assert_true(result); + + free(help); +} diff --git a/tests/test_cmd_alias.h b/tests/test_cmd_alias.h new file mode 100644 index 00000000..1f2df5cd --- /dev/null +++ b/tests/test_cmd_alias.h @@ -0,0 +1,8 @@ +void cmd_alias_add_shows_usage_when_no_args(void **state); +void cmd_alias_add_shows_usage_when_no_value(void **state); +void cmd_alias_remove_shows_usage_when_no_args(void **state); +void cmd_alias_show_usage_when_invalid_subcmd(void **state); +void cmd_alias_add_adds_alias(void **state); +void cmd_alias_remove_removes_alias(void **state); +void cmd_alias_remove_shows_message_when_no_alias(void **state); +void cmd_alias_list_shows_all_aliases(void **state); diff --git a/tests/testsuite.c b/tests/testsuite.c index 94a06a87..af42fe7c 100644 --- a/tests/testsuite.c +++ b/tests/testsuite.c @@ -21,6 +21,7 @@ #include "test_roster_list.h" #include "test_preferences.h" #include "test_server_events.h" +#include "test_cmd_alias.h" #define PROF_RUN_TESTS(name) fprintf(stderr, "\n-> Running %s\n", #name); \ fflush(stderr); \ @@ -390,6 +391,26 @@ int main(int argc, char* argv[]) { // delete_config_file), }; + const UnitTest cmd_alias_tests[] = { + unit_test(cmd_alias_add_shows_usage_when_no_args), + unit_test(cmd_alias_add_shows_usage_when_no_value), + unit_test(cmd_alias_remove_shows_usage_when_no_args), + unit_test(cmd_alias_show_usage_when_invalid_subcmd), + unit_test_setup_teardown(cmd_alias_add_adds_alias, + create_config_file, + delete_config_file), + unit_test_setup_teardown(cmd_alias_remove_removes_alias, + create_config_file, + delete_config_file), + unit_test_setup_teardown(cmd_alias_remove_shows_message_when_no_alias, + create_config_file, + delete_config_file), + unit_test_setup_teardown(cmd_alias_list_shows_all_aliases, + create_config_file, + delete_config_file), + }; + + int bak, new; fflush(stdout); bak = dup(1); @@ -413,6 +434,7 @@ int main(int argc, char* argv[]) { PROF_RUN_TESTS(cmd_statuses_tests); PROF_RUN_TESTS(preferences_tests); PROF_RUN_TESTS(server_events_tests); + PROF_RUN_TESTS(cmd_alias_tests); fflush(stdout); dup2(bak, 1); diff --git a/tests/ui/mock_ui.c b/tests/ui/mock_ui.c index cd6c62ff..e03b77c5 100644 --- a/tests/ui/mock_ui.c +++ b/tests/ui/mock_ui.c @@ -69,6 +69,12 @@ void _mock_cons_show_account(ProfAccount *account) } static +void _mock_cons_show_aliases(GList *aliases) +{ + check_expected(aliases); +} + +static void _mock_cons_show_account_list(gchar **accounts) { check_expected(accounts); @@ -123,6 +129,12 @@ mock_cons_show_account(void) } void +mock_cons_show_aliases(void) +{ + cons_show_aliases = _mock_cons_show_aliases; +} + +void mock_cons_show_account_list(void) { cons_show_account_list = _mock_cons_show_account_list; @@ -190,6 +202,13 @@ expect_cons_show_contact_online(PContact contact, Resource *resource, GDateTime } void +expect_cons_show_aliases() +{ + // write a custom checker for the list + expect_any(_mock_cons_show_aliases, aliases); +} + +void mock_ui_ask_password_returns(char *password) { will_return(_mock_ui_ask_password, strdup(password)); diff --git a/tests/ui/mock_ui.h b/tests/ui/mock_ui.h index 6f6d34d7..b0a5a80d 100644 --- a/tests/ui/mock_ui.h +++ b/tests/ui/mock_ui.h @@ -21,6 +21,9 @@ void expect_cons_show_error(char *output); void mock_cons_show_account(void); void expect_cons_show_account(ProfAccount *account); +void mock_cons_show_aliases(void); +void expect_cons_show_aliases(void); + void mock_cons_show_account_list(void); void expect_cons_show_account_list(gchar **accounts); |