about summary refs log tree commit diff stats
path: root/src/command
diff options
context:
space:
mode:
Diffstat (limited to 'src/command')
-rw-r--r--src/command/cmd_ac.c206
-rw-r--r--src/command/cmd_ac.h2
-rw-r--r--src/command/cmd_defs.c69
-rw-r--r--src/command/cmd_defs.h2
-rw-r--r--src/command/cmd_funcs.c386
-rw-r--r--src/command/cmd_funcs.h4
6 files changed, 577 insertions, 92 deletions
diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c
index 9bdd7f73..f9d5a22a 100644
--- a/src/command/cmd_ac.c
+++ b/src/command/cmd_ac.c
@@ -1,7 +1,7 @@
 /*
  * cmd_ac.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
@@ -98,6 +98,8 @@ static char* _sendfile_autocomplete(ProfWin *window, const char *const input, gb
 static char* _blocked_autocomplete(ProfWin *window, const char *const input, gboolean previous);
 static char* _tray_autocomplete(ProfWin *window, const char *const input, gboolean previous);
 static char* _presence_autocomplete(ProfWin *window, const char *const input, gboolean previous);
+static char* _rooms_autocomplete(ProfWin *window, const char *const input, gboolean previous);
+static char* _statusbar_autocomplete(ProfWin *window, const char *const input, gboolean previous);
 
 static char* _script_autocomplete_func(const char *const prefix, gboolean previous);
 
@@ -143,6 +145,7 @@ 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_show_ac;
 static Autocomplete roster_room_position_ac;
 static Autocomplete roster_room_by_ac;
 static Autocomplete roster_room_order_ac;
@@ -160,6 +163,9 @@ static Autocomplete alias_ac;
 static Autocomplete aliases_ac;
 static Autocomplete join_property_ac;
 static Autocomplete room_ac;
+static Autocomplete rooms_all_ac;
+static Autocomplete rooms_list_ac;
+static Autocomplete rooms_cache_ac;
 static Autocomplete affiliation_ac;
 static Autocomplete role_ac;
 static Autocomplete privilege_cmd_ac;
@@ -194,6 +200,11 @@ static Autocomplete tray_ac;
 static Autocomplete presence_ac;
 static Autocomplete presence_setting_ac;
 static Autocomplete winpos_ac;
+static Autocomplete statusbar_ac;
+static Autocomplete statusbar_self_ac;
+static Autocomplete statusbar_chat_ac;
+static Autocomplete statusbar_room_ac;
+static Autocomplete statusbar_show_ac;
 
 void
 cmd_ac_init(void)
@@ -381,8 +392,6 @@ cmd_ac_init(void)
     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();
@@ -469,6 +478,11 @@ cmd_ac_init(void)
     autocomplete_add(roster_room_ac, "order");
     autocomplete_add(roster_room_ac, "unread");
     autocomplete_add(roster_room_ac, "private");
+    autocomplete_add(roster_room_ac, "show");
+    autocomplete_add(roster_room_ac, "hide");
+
+    roster_room_show_ac = autocomplete_new();
+    autocomplete_add(roster_room_show_ac, "server");
 
     roster_room_by_ac = autocomplete_new();
     autocomplete_add(roster_room_by_ac, "service");
@@ -585,6 +599,20 @@ cmd_ac_init(void)
     autocomplete_add(room_ac, "destroy");
     autocomplete_add(room_ac, "config");
 
+    rooms_all_ac = autocomplete_new();
+    autocomplete_add(rooms_all_ac, "service");
+    autocomplete_add(rooms_all_ac, "filter");
+    autocomplete_add(rooms_all_ac, "cache");
+
+    rooms_list_ac = autocomplete_new();
+    autocomplete_add(rooms_list_ac, "service");
+    autocomplete_add(rooms_list_ac, "filter");
+
+    rooms_cache_ac = autocomplete_new();
+    autocomplete_add(rooms_cache_ac, "on");
+    autocomplete_add(rooms_cache_ac, "off");
+    autocomplete_add(rooms_cache_ac, "clear");
+
     affiliation_ac = autocomplete_new();
     autocomplete_add(affiliation_ac, "owner");
     autocomplete_add(affiliation_ac, "admin");
@@ -750,6 +778,35 @@ cmd_ac_init(void)
     winpos_ac = autocomplete_new();
     autocomplete_add(winpos_ac, "up");
     autocomplete_add(winpos_ac, "down");
+
+    statusbar_ac = autocomplete_new();
+    autocomplete_add(statusbar_ac, "up");
+    autocomplete_add(statusbar_ac, "down");
+    autocomplete_add(statusbar_ac, "show");
+    autocomplete_add(statusbar_ac, "hide");
+    autocomplete_add(statusbar_ac, "maxtabs");
+    autocomplete_add(statusbar_ac, "tablen");
+    autocomplete_add(statusbar_ac, "self");
+    autocomplete_add(statusbar_ac, "chat");
+    autocomplete_add(statusbar_ac, "room");
+
+    statusbar_self_ac = autocomplete_new();
+    autocomplete_add(statusbar_self_ac, "user");
+    autocomplete_add(statusbar_self_ac, "barejid");
+    autocomplete_add(statusbar_self_ac, "fulljid");
+    autocomplete_add(statusbar_self_ac, "off");
+
+    statusbar_chat_ac = autocomplete_new();
+    autocomplete_add(statusbar_chat_ac, "user");
+    autocomplete_add(statusbar_chat_ac, "jid");
+
+    statusbar_room_ac = autocomplete_new();
+    autocomplete_add(statusbar_room_ac, "room");
+    autocomplete_add(statusbar_room_ac, "jid");
+
+    statusbar_show_ac = autocomplete_new();
+    autocomplete_add(statusbar_show_ac, "name");
+    autocomplete_add(statusbar_show_ac, "number");
 }
 
 void
@@ -916,6 +973,7 @@ cmd_ac_reset(ProfWin *window)
     }
 
     muc_invites_reset_ac();
+    muc_confserver_reset_ac();
     accounts_reset_all_search();
     accounts_reset_enabled_search();
     tlscerts_reset_ac();
@@ -979,6 +1037,7 @@ cmd_ac_reset(ProfWin *window)
     autocomplete_reset(roster_count_ac);
     autocomplete_reset(roster_order_ac);
     autocomplete_reset(roster_room_ac);
+    autocomplete_reset(roster_room_show_ac);
     autocomplete_reset(roster_room_by_ac);
     autocomplete_reset(roster_unread_ac);
     autocomplete_reset(roster_room_position_ac);
@@ -998,6 +1057,9 @@ cmd_ac_reset(ProfWin *window)
     autocomplete_reset(aliases_ac);
     autocomplete_reset(join_property_ac);
     autocomplete_reset(room_ac);
+    autocomplete_reset(rooms_all_ac);
+    autocomplete_reset(rooms_list_ac);
+    autocomplete_reset(rooms_cache_ac);
     autocomplete_reset(affiliation_ac);
     autocomplete_reset(role_ac);
     autocomplete_reset(privilege_cmd_ac);
@@ -1026,6 +1088,11 @@ cmd_ac_reset(ProfWin *window)
     autocomplete_reset(presence_ac);
     autocomplete_reset(presence_setting_ac);
     autocomplete_reset(winpos_ac);
+    autocomplete_reset(statusbar_ac);
+    autocomplete_reset(statusbar_self_ac);
+    autocomplete_reset(statusbar_chat_ac);
+    autocomplete_reset(statusbar_room_ac);
+    autocomplete_reset(statusbar_show_ac);
 
     autocomplete_reset(script_ac);
     if (script_show_ac) {
@@ -1098,6 +1165,7 @@ cmd_ac_uninit(void)
     autocomplete_free(roster_count_ac);
     autocomplete_free(roster_order_ac);
     autocomplete_free(roster_room_ac);
+    autocomplete_free(roster_room_show_ac);
     autocomplete_free(roster_room_by_ac);
     autocomplete_free(roster_unread_ac);
     autocomplete_free(roster_room_position_ac);
@@ -1116,6 +1184,9 @@ cmd_ac_uninit(void)
     autocomplete_free(aliases_ac);
     autocomplete_free(join_property_ac);
     autocomplete_free(room_ac);
+    autocomplete_free(rooms_all_ac);
+    autocomplete_free(rooms_list_ac);
+    autocomplete_free(rooms_cache_ac);
     autocomplete_free(affiliation_ac);
     autocomplete_free(role_ac);
     autocomplete_free(privilege_cmd_ac);
@@ -1149,6 +1220,11 @@ cmd_ac_uninit(void)
     autocomplete_free(presence_ac);
     autocomplete_free(presence_setting_ac);
     autocomplete_free(winpos_ac);
+    autocomplete_free(statusbar_ac);
+    autocomplete_free(statusbar_self_ac);
+    autocomplete_free(statusbar_chat_ac);
+    autocomplete_free(statusbar_room_ac);
+    autocomplete_free(statusbar_show_ac);
 }
 
 char*
@@ -1268,7 +1344,7 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input, gboolean previ
 
     // autocomplete boolean settings
     gchar *boolean_choices[] = { "/beep", "/intype", "/states", "/outtype", "/flash", "/splash", "/chlog", "/grlog",
-        "/history", "/vercheck", "/privileges", "/wrap", "/winstidy", "/carbons", "/encwarn",
+        "/history", "/vercheck", "/privileges", "/wrap", "/carbons", "/encwarn",
         "/lastactivity" };
 
     for (i = 0; i < ARRAY_SIZE(boolean_choices); i++) {
@@ -1336,8 +1412,8 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input, gboolean previ
         }
     }
 
-    gchar *cmds[] = { "/prefs", "/disco", "/room", "/autoping", "/titlebar", "/mainwin", "/statusbar", "/inputwin" };
-    Autocomplete completers[] = { prefs_ac, disco_ac, room_ac, autoping_ac, winpos_ac, winpos_ac, winpos_ac, winpos_ac };
+    gchar *cmds[] = { "/prefs", "/disco", "/room", "/autoping", "/titlebar", "/mainwin", "/inputwin" };
+    Autocomplete completers[] = { prefs_ac, disco_ac, room_ac, autoping_ac, winpos_ac, winpos_ac, winpos_ac };
 
     for (i = 0; i < ARRAY_SIZE(cmds); i++) {
         result = autocomplete_param_with_ac(input, cmds[i], completers[i], TRUE, previous);
@@ -1387,6 +1463,8 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input, gboolean previ
     g_hash_table_insert(ac_funcs, "/blocked",       _blocked_autocomplete);
     g_hash_table_insert(ac_funcs, "/tray",          _tray_autocomplete);
     g_hash_table_insert(ac_funcs, "/presence",      _presence_autocomplete);
+    g_hash_table_insert(ac_funcs, "/rooms",         _rooms_autocomplete);
+    g_hash_table_insert(ac_funcs, "/statusbar",     _statusbar_autocomplete);
 
     int len = strlen(input);
     char parsed[len+1];
@@ -1550,6 +1628,14 @@ _roster_autocomplete(ProfWin *window, const char *const input, gboolean previous
     if (result) {
         return result;
     }
+    result = autocomplete_param_with_ac(input, "/roster room show", roster_room_show_ac, TRUE, previous);
+    if (result) {
+        return result;
+    }
+    result = autocomplete_param_with_ac(input, "/roster room hide", roster_room_show_ac, TRUE, previous);
+    if (result) {
+        return result;
+    }
     result = autocomplete_param_with_func(input, "/roster count zero", prefs_autocomplete_boolean_choice, previous);
     if (result) {
         return result;
@@ -2590,11 +2676,6 @@ _wins_autocomplete(ProfWin *window, const char *const input, gboolean previous)
 {
     char *result = NULL;
 
-    result = autocomplete_param_with_func(input, "/wins autotidy", prefs_autocomplete_boolean_choice, previous);
-    if (result) {
-        return result;
-    }
-
     result = autocomplete_param_with_ac(input, "/wins", wins_ac, TRUE, previous);
     if (result) {
         return result;
@@ -3074,3 +3155,106 @@ _presence_autocomplete(ProfWin *window, const char *const input, gboolean previo
     return NULL;
 }
 
+static char*
+_rooms_autocomplete(ProfWin *window, const char *const input, gboolean previous)
+{
+    char *found = NULL;
+    gboolean result = FALSE;
+
+    gchar **args = parse_args(input, 0, 4, &result);
+
+    if (result) {
+        gboolean space_at_end = g_str_has_suffix(input, " ");
+        int num_args = g_strv_length(args);
+        if (num_args <= 1) {
+            found = autocomplete_param_with_ac(input, "/rooms", rooms_all_ac, TRUE, previous);
+            if (found) {
+                g_strfreev(args);
+                return found;
+            }
+        }
+        if ((num_args == 1 && g_strcmp0(args[0], "service") == 0 && space_at_end) ||
+                (num_args == 2 && g_strcmp0(args[0], "service") == 0 && !space_at_end)) {
+            found = autocomplete_param_with_func(input, "/rooms service", muc_confserver_find, previous);
+            if (found) {
+                g_strfreev(args);
+                return found;
+            }
+        }
+        if ((num_args == 1 && g_strcmp0(args[0], "cache") == 0 && space_at_end) ||
+                (num_args == 2 && g_strcmp0(args[0], "cache") == 0 && !space_at_end)) {
+            found = autocomplete_param_with_ac(input, "/rooms cache", rooms_cache_ac, TRUE, previous);
+            if (found) {
+                g_strfreev(args);
+                return found;
+            }
+        }
+        if ((num_args == 2 && space_at_end) || (num_args == 3 && !space_at_end)) {
+            GString *beginning = g_string_new("/rooms");
+            g_string_append_printf(beginning, " %s %s", args[0], args[1]);
+            found = autocomplete_param_with_ac(input, beginning->str, rooms_list_ac, TRUE, previous);
+            g_string_free(beginning, TRUE);
+            if (found) {
+                g_strfreev(args);
+                return found;
+            }
+        }
+        if ((num_args == 3 && g_strcmp0(args[2], "service") == 0 && space_at_end) ||
+                (num_args == 4 && g_strcmp0(args[2], "service") == 0 && !space_at_end)) {
+            GString *beginning = g_string_new("/rooms");
+            g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]);
+            found = autocomplete_param_with_func(input, beginning->str, muc_confserver_find, previous);
+            g_string_free(beginning, TRUE);
+            if (found) {
+                g_strfreev(args);
+                return found;
+            }
+        }
+        if ((num_args >= 2) && g_strcmp0(args[0], "cache") == 0) {
+            g_strfreev(args);
+            return NULL;
+        }
+    }
+
+    g_strfreev(args);
+
+    return NULL;
+}
+
+static char*
+_statusbar_autocomplete(ProfWin *window, const char *const input, gboolean previous)
+{
+    char *found = NULL;
+
+    found = autocomplete_param_with_ac(input, "/statusbar", statusbar_ac, TRUE, previous);
+    if (found) {
+        return found;
+    }
+
+    found = autocomplete_param_with_ac(input, "/statusbar show", statusbar_show_ac, TRUE, previous);
+    if (found) {
+        return found;
+    }
+
+    found = autocomplete_param_with_ac(input, "/statusbar hide", statusbar_show_ac, TRUE, previous);
+    if (found) {
+        return found;
+    }
+
+    found = autocomplete_param_with_ac(input, "/statusbar self", statusbar_self_ac, TRUE, previous);
+    if (found) {
+        return found;
+    }
+
+    found = autocomplete_param_with_ac(input, "/statusbar chat", statusbar_chat_ac, TRUE, previous);
+    if (found) {
+        return found;
+    }
+
+    found = autocomplete_param_with_ac(input, "/statusbar room", statusbar_room_ac, TRUE, previous);
+    if (found) {
+        return found;
+    }
+
+    return NULL;
+}
diff --git a/src/command/cmd_ac.h b/src/command/cmd_ac.h
index d56d0e30..d7b47eb5 100644
--- a/src/command/cmd_ac.h
+++ b/src/command/cmd_ac.h
@@ -1,7 +1,7 @@
 /*
  * cmd_ac.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c
index c760d47c..418155c4 100644
--- a/src/command/cmd_defs.c
+++ b/src/command/cmd_defs.c
@@ -1,7 +1,7 @@
 /*
  * cmd_defs.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
@@ -287,6 +287,8 @@ static struct cmd_t command_defs[] =
             "/roster room by service|none",
             "/roster room order name|unread",
             "/roster room unread before|after|off",
+            "/roster room show server",
+            "/roster room hide server",
             "/roster private room|group|off",
             "/roster private char <char>|none",
             "/roster header char <char>|none",
@@ -352,6 +354,8 @@ static struct cmd_t command_defs[] =
             { "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." },
+            { "room show server",           "Show the conference server with room JIDs." },
+            { "room hide server",           "Do not show the conference server with room JIDs." },
             { "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." },
@@ -784,20 +788,31 @@ static struct cmd_t command_defs[] =
     },
 
     { "/rooms",
-        parse_args, 0, 1, NULL,
+        parse_args, 0, 4, NULL,
         CMD_NOSUBFUNCS
         CMD_MAINFUNC(cmd_rooms)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
-            "/rooms [<service>]")
+            "/rooms",
+            "/rooms filter <text>",
+            "/rooms service <service>",
+            "/rooms service <service> filter <text>",
+            "/rooms cache on|off|clear")
         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.")
+            "If no argument is supplied, the account preference 'muc.service' is used, 'conference.<domain-part>' by default. "
+            "The filter argument only shows rooms that contain the provided text, case insensitive.")
         CMD_ARGS(
-            { "<service>", "The conference service to query." })
+            { "service <service>",  "The conference service to query." },
+            { "filter <text>",      "The text to filter results by."},
+            { "cache on|off",       "Enable or disable caching of rooms list response, enabled by default."},
+            { "cache clear",        "Clear the rooms response cache if enabled."})
         CMD_EXAMPLES(
-            "/rooms conference.jabber.org")
+            "/rooms",
+            "/rooms filter development",
+            "/rooms service conference.jabber.org",
+            "/rooms service conference.jabber.org filter \"News Room\"")
     },
 
     { "/bookmark",
@@ -947,18 +962,14 @@ static struct cmd_t command_defs[] =
         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 })
+            { "swap",       cmd_wins_swap })
         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(
@@ -966,9 +977,7 @@ static struct cmd_t command_defs[] =
             "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." },
+            { "prune",                  "Close all windows with no unread messages." },
             { "swap <source> <target>", "Swap windows, target may be an empty position." })
         CMD_NOEXAMPLES
     },
@@ -1343,20 +1352,40 @@ static struct cmd_t command_defs[] =
     },
 
     { "/statusbar",
-        parse_args, 1, 1, &cons_winpos_setting,
+        parse_args, 1, 2, &cons_statusbar_setting,
         CMD_NOSUBFUNCS
         CMD_MAINFUNC(cmd_statusbar)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
+            "/statusbar show name|number",
+            "/statusbar hide name|number",
+            "/statusbar maxtabs <value>",
+            "/statusbar tablen <value>",
+            "/statusbar self user|barejid|fulljid|off",
+            "/statusbar chat user|jid",
+            "/statusbar room room|jid",
             "/statusbar up",
             "/statusbar down")
         CMD_DESC(
-            "Move the status bar.")
-        CMD_ARGS(
-            { "up", "Move the status bar up the screen." },
-            { "down", "Move the status bar down the screen." })
-        CMD_NOEXAMPLES
+            "Manage statusbar display preferences.")
+        CMD_ARGS(
+            { "maxtabs <value>",            "Set the maximum number of tabs to display, <value> must be between 0 and 10" },
+            { "tablen <value>",             "Set the maximum number of characters to show as the tab name, 0 sets to unlimited." },
+            { "show|hide name",             "Show or hide names in tabs." },
+            { "show|hide number",           "Show or hide numbers in tabs." },
+            { "self user|barejid|fulljid",  "Show account user name, barejid, fulljid as status bar title." },
+            { "self off",                   "Disable showing self as status bar title." },
+            { "chat user|jid",              "Show users name, or the fulljid if no nick is present for chat tabs." },
+            { "room room|jid",              "Show room name, or the fulljid for room tabs." },
+            { "up",                         "Move the status bar up the screen." },
+            { "down",                       "Move the status bar down the screen." })
+        CMD_EXAMPLES(
+            "/statusbar maxtabs 8",
+            "/statusbar tablen 5",
+            "/statusbar self user",
+            "/statusbar chat jid",
+            "/statusbar hide name")
     },
 
     { "/inputwin",
diff --git a/src/command/cmd_defs.h b/src/command/cmd_defs.h
index e0cadaf2..d318e7ed 100644
--- a/src/command/cmd_defs.h
+++ b/src/command/cmd_defs.h
@@ -1,7 +1,7 @@
 /*
  * cmd_defs.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c
index 850be61c..c8aa22b4 100644
--- a/src/command/cmd_funcs.c
+++ b/src/command/cmd_funcs.c
@@ -1,7 +1,7 @@
 /*
  * cmd_funcs.c
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
@@ -1253,17 +1253,6 @@ cmd_wins_unread(ProfWin *window, const char *const command, gchar **args)
 }
 
 gboolean
-cmd_wins_tidy(ProfWin *window, const char *const command, gchar **args)
-{
-    if (wins_tidy()) {
-        cons_show("Windows tidied.");
-    } else {
-        cons_show("No tidy needed.");
-    }
-    return TRUE;
-}
-
-gboolean
 cmd_wins_prune(ProfWin *window, const char *const command, gchar **args)
 {
     ui_prune_wins();
@@ -1280,38 +1269,34 @@ cmd_wins_swap(ProfWin *window, const char *const command, gchar **args)
 
     int source_win = atoi(args[1]);
     int target_win = atoi(args[2]);
+
     if ((source_win == 1) || (target_win == 1)) {
         cons_show("Cannot move console window.");
-    } else if (source_win == 10 || target_win == 10) {
+        return TRUE;
+    }
+
+    if (source_win == 10 || target_win == 10) {
         cons_show("Window 10 does not exist");
-    } else if (source_win != target_win) {
-        gboolean swapped = wins_swap(source_win, target_win);
-        if (swapped) {
-            cons_show("Swapped windows %d <-> %d", source_win, target_win);
-        } else {
-            cons_show("Window %d does not exist", source_win);
-        }
-    } else {
+        return TRUE;
+    }
+
+    if (source_win == target_win) {
         cons_show("Same source and target window supplied.");
+        return TRUE;
     }
 
-    return TRUE;
-}
+    if (wins_get_by_num(source_win) == NULL) {
+        cons_show("Window %d does not exist", source_win);
+        return TRUE;
+    }
 
-gboolean
-cmd_wins_autotidy(ProfWin *window, const char *const command, gchar **args)
-{
-    if (g_strcmp0(args[1], "on") == 0) {
-        cons_show("Window autotidy enabled");
-        prefs_set_boolean(PREF_WINS_AUTO_TIDY, TRUE);
-        wins_tidy();
-    } else if (g_strcmp0(args[1], "off") == 0) {
-        cons_show("Window autotidy disabled");
-        prefs_set_boolean(PREF_WINS_AUTO_TIDY, FALSE);
-    } else {
-        cons_bad_cmd_usage(command);
+    if (wins_get_by_num(target_win) == NULL) {
+        cons_show("Window %d does not exist", target_win);
+        return TRUE;
     }
 
+    wins_swap(source_win, target_win);
+    cons_show("Swapped windows %d <-> %d", source_win, target_win);
     return TRUE;
 }
 
@@ -1407,11 +1392,7 @@ cmd_close(ProfWin *window, const char *const command, gchar **args)
         // close the window
         ui_close_win(index);
         cons_show("Closed window %d", index);
-
-        // Tidy up the window list.
-        if (prefs_get_boolean(PREF_WINS_AUTO_TIDY)) {
-            wins_tidy();
-        }
+        wins_tidy();
 
         rosterwin_roster();
         return TRUE;
@@ -1442,11 +1423,7 @@ cmd_close(ProfWin *window, const char *const command, gchar **args)
         // close the window
         ui_close_win(index);
         cons_show("Closed window %s", args[0]);
-
-        // Tidy up the window list.
-        if (prefs_get_boolean(PREF_WINS_AUTO_TIDY)) {
-            wins_tidy();
-        }
+        wins_tidy();
 
         rosterwin_roster();
         return TRUE;
@@ -2095,7 +2072,7 @@ cmd_who(ProfWin *window, const char *const command, gchar **args)
     }
 
     if (window->type != WIN_CONSOLE && window->type != WIN_MUC) {
-        status_bar_new(1);
+        status_bar_new(1, WIN_CONSOLE, "console");
     }
 
     return TRUE;
@@ -2869,6 +2846,30 @@ cmd_roster(ProfWin *window, const char *const command, gchar **args)
                 cons_bad_cmd_usage(command);
                 return TRUE;
             }
+        } else if (g_strcmp0(args[1], "show") == 0) {
+            if (g_strcmp0(args[2], "server") == 0) {
+                cons_show("Roster room server enabled.");
+                prefs_set_boolean(PREF_ROSTER_ROOMS_SERVER, TRUE);
+                if (conn_status == JABBER_CONNECTED) {
+                    rosterwin_roster();
+                }
+                return TRUE;
+            } else {
+                cons_bad_cmd_usage(command);
+                return TRUE;
+            }
+        } else if (g_strcmp0(args[1], "hide") == 0) {
+            if (g_strcmp0(args[2], "server") == 0) {
+                cons_show("Roster room server disabled.");
+                prefs_set_boolean(PREF_ROSTER_ROOMS_SERVER, FALSE);
+                if (conn_status == JABBER_CONNECTED) {
+                    rosterwin_roster();
+                }
+                return TRUE;
+            } else {
+                cons_bad_cmd_usage(command);
+                return TRUE;
+            }
         } else {
             cons_bad_cmd_usage(command);
             return TRUE;
@@ -3918,6 +3919,7 @@ cmd_form(ProfWin *window, const char *const command, gchar **args)
         }
         ui_focus_win(new_current);
         wins_close_by_num(num);
+        wins_tidy();
     }
 
     return TRUE;
@@ -4369,18 +4371,102 @@ cmd_rooms(ProfWin *window, const char *const command, gchar **args)
         return TRUE;
     }
 
-    if (args[0]) {
-        iq_room_list_request(args[0]);
-        return TRUE;
+    gchar *service = NULL;
+    gchar *filter = NULL;
+    if (args[0] != NULL) {
+        if (g_strcmp0(args[0], "service") == 0) {
+            if (args[1] == NULL) {
+                cons_bad_cmd_usage(command);
+                cons_show("");
+                return TRUE;
+            }
+            service = g_strdup(args[1]);
+        } else if (g_strcmp0(args[0], "filter") == 0) {
+            if (args[1] == NULL) {
+                cons_bad_cmd_usage(command);
+                cons_show("");
+                return TRUE;
+            }
+            filter = g_strdup(args[1]);
+        } else if (g_strcmp0(args[0], "cache") == 0) {
+            if (g_strv_length(args) != 2) {
+                cons_bad_cmd_usage(command);
+                cons_show("");
+                return TRUE;
+            } else if (g_strcmp0(args[1], "on") == 0) {
+                prefs_set_boolean(PREF_ROOM_LIST_CACHE, TRUE);
+                cons_show("Rooms list cache enabled.");
+                return TRUE;
+            } else if (g_strcmp0(args[1], "off") == 0) {
+                prefs_set_boolean(PREF_ROOM_LIST_CACHE, FALSE);
+                cons_show("Rooms list cache disabled.");
+                return TRUE;
+            } else if (g_strcmp0(args[1], "clear") == 0) {
+                iq_rooms_cache_clear();
+                cons_show("Rooms list cache cleared.");
+                return TRUE;
+            } else {
+                cons_bad_cmd_usage(command);
+                cons_show("");
+                return TRUE;
+            }
+        } else {
+            cons_bad_cmd_usage(command);
+            cons_show("");
+            return TRUE;
+        }
+    }
+    if (g_strv_length(args) >=3 ) {
+        if (g_strcmp0(args[2], "service") == 0) {
+            if (args[3] == NULL) {
+                cons_bad_cmd_usage(command);
+                cons_show("");
+                g_free(service);
+                g_free(filter);
+                return TRUE;
+            }
+            g_free(service);
+            service = g_strdup(args[3]);
+        } else if (g_strcmp0(args[2], "filter") == 0) {
+            if (args[3] == NULL) {
+                cons_bad_cmd_usage(command);
+                cons_show("");
+                g_free(service);
+                g_free(filter);
+                return TRUE;
+            }
+            g_free(filter);
+            filter = g_strdup(args[3]);
+        } else {
+            cons_bad_cmd_usage(command);
+            cons_show("");
+            return TRUE;
+        }
     }
 
-    ProfAccount *account = accounts_get_account(session_get_account_name());
-    if (account->muc_service) {
-        iq_room_list_request(account->muc_service);
+    if (service == NULL) {
+        ProfAccount *account = accounts_get_account(session_get_account_name());
+        if (account->muc_service) {
+            service = g_strdup(account->muc_service);
+            account_free(account);
+        } else {
+            cons_show("Account MUC service property not found.");
+            account_free(account);
+            g_free(service);
+            g_free(filter);
+            return TRUE;
+        }
+    }
+
+    cons_show("");
+    if (filter) {
+        cons_show("Room list request sent: %s, filter: '%s'", service, filter);
     } else {
-        cons_show("Account MUC service property not found.");
+        cons_show("Room list request sent: %s", service);
     }
-    account_free(account);
+    iq_room_list_request(service, filter);
+
+    g_free(service);
 
     return TRUE;
 }
@@ -4392,11 +4478,15 @@ cmd_bookmark(ProfWin *window, const char *const command, gchar **args)
 
     if (conn_status != JABBER_CONNECTED) {
         cons_show("You are not currently connected.");
+        cons_alert();
         return TRUE;
     }
 
+    int num_args = g_strv_length(args);
     gchar *cmd = args[0];
-    if (window->type == WIN_MUC && (cmd == NULL || g_strcmp0(cmd, "add") == 0)) {
+    if (window->type == WIN_MUC
+            && num_args < 2
+            && (cmd == NULL || g_strcmp0(cmd, "add") == 0)) {
         // default to current nickname, password, and autojoin "on"
         ProfMucWin *mucwin = (ProfMucWin*)window;
         assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
@@ -4411,7 +4501,9 @@ cmd_bookmark(ProfWin *window, const char *const command, gchar **args)
         return TRUE;
     }
 
-    if (window->type == WIN_MUC && g_strcmp0(cmd, "remove") == 0) {
+    if (window->type == WIN_MUC
+            && num_args < 2
+            && g_strcmp0(cmd, "remove") == 0) {
         ProfMucWin *mucwin = (ProfMucWin*)window;
         assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
         gboolean removed = bookmark_remove(mucwin->roomjid);
@@ -4425,6 +4517,7 @@ cmd_bookmark(ProfWin *window, const char *const command, gchar **args)
 
     if (cmd == NULL) {
         cons_bad_cmd_usage(command);
+        cons_alert();
         return TRUE;
     }
 
@@ -4439,6 +4532,7 @@ cmd_bookmark(ProfWin *window, const char *const command, gchar **args)
             cons_bad_cmd_usage(command);
             cons_show("");
         }
+        cons_alert();
         return TRUE;
     }
 
@@ -4453,11 +4547,13 @@ cmd_bookmark(ProfWin *window, const char *const command, gchar **args)
     if (jid == NULL) {
         cons_bad_cmd_usage(command);
         cons_show("");
+        cons_alert();
         return TRUE;
     }
     if (strchr(jid, '@') == NULL) {
         cons_show("Invalid room, must be of the form room@domain.tld");
         cons_show("");
+        cons_alert();
         return TRUE;
     }
 
@@ -4468,6 +4564,7 @@ cmd_bookmark(ProfWin *window, const char *const command, gchar **args)
         } else {
             cons_show("No bookmark exists for %s.", jid);
         }
+        cons_alert();
         return TRUE;
     }
 
@@ -4476,6 +4573,7 @@ cmd_bookmark(ProfWin *window, const char *const command, gchar **args)
         if (!joined) {
             cons_show("No bookmark exists for %s.", jid);
         }
+        cons_alert();
         return TRUE;
     }
 
@@ -4486,6 +4584,7 @@ cmd_bookmark(ProfWin *window, const char *const command, gchar **args)
     if (!parsed) {
         cons_bad_cmd_usage(command);
         cons_show("");
+        cons_alert();
         return TRUE;
     }
 
@@ -4495,6 +4594,7 @@ cmd_bookmark(ProfWin *window, const char *const command, gchar **args)
         cons_bad_cmd_usage(command);
         cons_show("");
         options_destroy(options);
+        cons_alert();
         return TRUE;
     }
 
@@ -4509,6 +4609,7 @@ cmd_bookmark(ProfWin *window, const char *const command, gchar **args)
             cons_show("Bookmark already exists, use /bookmark update to edit.");
         }
         options_destroy(options);
+        cons_alert();
         return TRUE;
     }
 
@@ -4520,11 +4621,13 @@ cmd_bookmark(ProfWin *window, const char *const command, gchar **args)
             cons_show("No bookmark exists for %s.", jid);
         }
         options_destroy(options);
+        cons_alert();
         return TRUE;
     }
 
     cons_bad_cmd_usage(command);
     options_destroy(options);
+    cons_alert();
 
     return TRUE;
 }
@@ -5667,6 +5770,177 @@ cmd_mainwin(ProfWin *window, const char *const command, gchar **args)
 gboolean
 cmd_statusbar(ProfWin *window, const char *const command, gchar **args)
 {
+    if (g_strcmp0(args[0], "show") == 0) {
+        if (g_strcmp0(args[1], "name") == 0) {
+            prefs_set_boolean(PREF_STATUSBAR_SHOW_NAME, TRUE);
+            cons_show("Enabled showing tab names.");
+            ui_resize();
+            return TRUE;
+        }
+        if (g_strcmp0(args[1], "number") == 0) {
+            prefs_set_boolean(PREF_STATUSBAR_SHOW_NUMBER, TRUE);
+            cons_show("Enabled showing tab numbers.");
+            ui_resize();
+            return TRUE;
+        }
+        cons_bad_cmd_usage(command);
+        return TRUE;
+    }
+
+    if (g_strcmp0(args[0], "hide") == 0) {
+        if (g_strcmp0(args[1], "name") == 0) {
+            if (prefs_get_boolean(PREF_STATUSBAR_SHOW_NUMBER) == FALSE) {
+                cons_show("Cannot disable both names and numbers in statusbar.");
+                cons_show("Use '/statusbar maxtabs 0' to hide tabs.");
+                return TRUE;
+            }
+            prefs_set_boolean(PREF_STATUSBAR_SHOW_NAME, FALSE);
+            cons_show("Disabled showing tab names.");
+            ui_resize();
+            return TRUE;
+        }
+        if (g_strcmp0(args[1], "number") == 0) {
+            if (prefs_get_boolean(PREF_STATUSBAR_SHOW_NAME) == FALSE) {
+                cons_show("Cannot disable both names and numbers in statusbar.");
+                cons_show("Use '/statusbar maxtabs 0' to hide tabs.");
+                return TRUE;
+            }
+            prefs_set_boolean(PREF_STATUSBAR_SHOW_NUMBER, FALSE);
+            cons_show("Disabled showing tab numbers.");
+            ui_resize();
+            return TRUE;
+        }
+        cons_bad_cmd_usage(command);
+        return TRUE;
+    }
+
+    if (g_strcmp0(args[0], "maxtabs") == 0) {
+        if (args[1] == NULL) {
+            cons_bad_cmd_usage(command);
+            return TRUE;
+        }
+
+        char *value = args[1];
+        int intval = 0;
+        char *err_msg = NULL;
+        gboolean res = strtoi_range(value, &intval, 0, INT_MAX, &err_msg);
+        if (res) {
+            if (intval < 0 || intval > 10) {
+                cons_bad_cmd_usage(command);
+                return TRUE;
+            }
+
+            prefs_set_statusbartabs(intval);
+            if (intval == 0) {
+                cons_show("Status bar tabs disabled.");
+            } else {
+                cons_show("Status bar tabs set to %d.", intval);
+            }
+            ui_resize();
+            return TRUE;
+        } else {
+            cons_show(err_msg);
+            cons_bad_cmd_usage(command);
+            free(err_msg);
+            return TRUE;
+        }
+    }
+
+    if (g_strcmp0(args[0], "tablen") == 0) {
+        if (args[1] == NULL) {
+            cons_bad_cmd_usage(command);
+            return TRUE;
+        }
+
+        char *value = args[1];
+        int intval = 0;
+        char *err_msg = NULL;
+        gboolean res = strtoi_range(value, &intval, 0, INT_MAX, &err_msg);
+        if (res) {
+            if (intval < 0) {
+                cons_bad_cmd_usage(command);
+                return TRUE;
+            }
+
+            prefs_set_statusbartablen(intval);
+            if (intval == 0) {
+                cons_show("Maximum tab length disabled.");
+            } else {
+                cons_show("Maximum tab length set to %d.", intval);
+            }
+            ui_resize();
+            return TRUE;
+        } else {
+            cons_show(err_msg);
+            cons_bad_cmd_usage(command);
+            free(err_msg);
+            return TRUE;
+        }
+    }
+
+    if (g_strcmp0(args[0], "self") == 0) {
+        if (g_strcmp0(args[1], "barejid") == 0) {
+            prefs_set_string(PREF_STATUSBAR_SELF, "barejid");
+            cons_show("Using barejid for statusbar title.");
+            ui_resize();
+            return TRUE;
+        }
+        if (g_strcmp0(args[1], "fulljid") == 0) {
+            prefs_set_string(PREF_STATUSBAR_SELF, "fulljid");
+            cons_show("Using fulljid for statusbar title.");
+            ui_resize();
+            return TRUE;
+        }
+        if (g_strcmp0(args[1], "user") == 0) {
+            prefs_set_string(PREF_STATUSBAR_SELF, "user");
+            cons_show("Using user for statusbar title.");
+            ui_resize();
+            return TRUE;
+        }
+        if (g_strcmp0(args[1], "off") == 0) {
+            prefs_set_string(PREF_STATUSBAR_SELF, "off");
+            cons_show("Disabling statusbar title.");
+            ui_resize();
+            return TRUE;
+        }
+        cons_bad_cmd_usage(command);
+        return TRUE;
+    }
+
+    if (g_strcmp0(args[0], "chat") == 0) {
+        if (g_strcmp0(args[1], "jid") == 0) {
+            prefs_set_string(PREF_STATUSBAR_CHAT, "jid");
+            cons_show("Using jid for chat tabs.");
+            ui_resize();
+            return TRUE;
+        }
+        if (g_strcmp0(args[1], "user") == 0) {
+            prefs_set_string(PREF_STATUSBAR_CHAT, "user");
+            cons_show("Using user for chat tabs.");
+            ui_resize();
+            return TRUE;
+        }
+        cons_bad_cmd_usage(command);
+        return TRUE;
+    }
+
+    if (g_strcmp0(args[0], "room") == 0) {
+        if (g_strcmp0(args[1], "jid") == 0) {
+            prefs_set_string(PREF_STATUSBAR_ROOM, "jid");
+            cons_show("Using jid for room tabs.");
+            ui_resize();
+            return TRUE;
+        }
+        if (g_strcmp0(args[1], "room") == 0) {
+            prefs_set_string(PREF_STATUSBAR_ROOM, "room");
+            cons_show("Using room name for room tabs.");
+            ui_resize();
+            return TRUE;
+        }
+        cons_bad_cmd_usage(command);
+        return TRUE;
+    }
+
     if (g_strcmp0(args[0], "up") == 0) {
         gboolean result = prefs_statusbar_pos_up();
         if (result) {
diff --git a/src/command/cmd_funcs.h b/src/command/cmd_funcs.h
index 2f0e0bac..0bbf338e 100644
--- a/src/command/cmd_funcs.h
+++ b/src/command/cmd_funcs.h
@@ -1,7 +1,7 @@
 /*
  * cmd_funcs.h
  *
- * Copyright (C) 2012 - 2017 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com>
  *
  * This file is part of Profanity.
  *
@@ -205,10 +205,8 @@ 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);