From eb6236fa04d55c4fd87c07c9c753483b5fecc2a0 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sun, 30 Jun 2013 17:19:43 +0300 Subject: [PATCH 1/8] fixed memory leaks in command.c --- src/command/command.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/command/command.c b/src/command/command.c index 50f7b08f..16511fec 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -2690,7 +2690,7 @@ _cmd_join(gchar **args, struct cmd_help_t help) } else { g_string_append(room_str, args[0]); g_string_append(room_str, "@conference."); - g_string_append(room_str, strdup(my_jid->domainpart)); + g_string_append(room_str, my_jid->domainpart); room = room_str->str; } @@ -2711,6 +2711,7 @@ _cmd_join(gchar **args, struct cmd_help_t help) ui_room_join(room_jid); muc_remove_invite(room); + jid_destroy(room_arg); jid_destroy(room_jid); jid_destroy(my_jid); g_string_free(room_str, TRUE); @@ -2788,7 +2789,7 @@ _cmd_rooms(gchar **args, struct cmd_help_t help) if (args[0] == NULL) { Jid *jid = jid_create(jabber_get_fulljid()); GString *conference_node = g_string_new("conference."); - g_string_append(conference_node, strdup(jid->domainpart)); + g_string_append(conference_node, jid->domainpart); jid_destroy(jid); iq_room_list_request(conference_node->str); g_string_free(conference_node, TRUE); @@ -2814,7 +2815,7 @@ _cmd_disco(gchar **args, struct cmd_help_t help) jid = g_string_append(jid, args[1]); } else { Jid *jidp = jid_create(jabber_get_fulljid()); - jid = g_string_append(jid, strdup(jidp->domainpart)); + jid = g_string_append(jid, jidp->domainpart); jid_destroy(jidp); } From 1f7e7e84471f65a3a7c13b8ac2dab888a952ea5f Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Sun, 30 Jun 2013 14:05:20 -0400 Subject: [PATCH 2/8] Fix a small typo (`Invalud' -> `Invalid') --- src/command/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command/command.c b/src/command/command.c index 50f7b08f..109447f1 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -1463,7 +1463,7 @@ _cmd_account(gchar **args, struct cmd_help_t help) cons_show(""); } else if (strcmp(property, "status") == 0) { if (!valid_resource_presence_string(value) && (strcmp(value, "last") != 0)) { - cons_show("Invalud status: %s", value); + cons_show("Invalid status: %s", value); } else { accounts_set_login_presence(account_name, value); cons_show("Updated login status for account %s: %s", account_name, value); From e933572ab9d79f389e99e028643c19f4604251b0 Mon Sep 17 00:00:00 2001 From: James Booth Date: Sun, 30 Jun 2013 22:59:06 +0100 Subject: [PATCH 3/8] Tidied help --- src/command/command.c | 64 +++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/src/command/command.c b/src/command/command.c index 2d38026f..4af0da96 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -163,7 +163,7 @@ static struct cmd_t command_defs[] = "Example : /help presence", "Example : /help who", "", - "For more details help, see the user guide at http://www.profanity.im/userguide.html.", + "For more detailed help, see the user guide at http://www.profanity.im/userguide.html.", NULL } } }, { "/about", @@ -197,11 +197,11 @@ static struct cmd_t command_defs[] = { "/msg", _cmd_msg, parse_args_with_freetext, 1, 2, NULL, - { "/msg jid|nick [message]", "Start chat with user.", - { "/msg jid|nick [message]", - "-----------------------", - "Open a chat window with for the user JID (Jabber ID) and send the message if one is supplied.", - "When in a chat room, supply the nickname to start private chat with the room member.", + { "/msg contact|nick [message]", "Start chat with user.", + { "/msg contact|nick [message]", + "---------------------------", + "Open a chat window for the contact and send the message if one is supplied.", + "When in a chat room, supply a nickname to start private chat with a room member.", "Use quotes if the nickname includes spaces.", "", "Example : /msg myfriend@server.com Hey, here's a message!", @@ -232,32 +232,32 @@ static struct cmd_t command_defs[] = { "/group", _cmd_group, parse_args_with_freetext, 0, 3, NULL, - { "/group show|add|remove [group] [contact]", "Manage roster groups.", - { "/group show|add|remove [group] [contact]", - "-------------------------------------", + { "/group [show|add|remove] [group] [contact]", "Manage roster groups.", + { "/group [show|add|remove] [group] [contact]", + "------------------------------------------", "View, add to, and remove from roster groups.", "Passing no argument will list all roster groups.", "The 'show' command takes 'group' as an argument, and lists all roster items in that group.", - "The 'add' command takes 'group' and 'contact' arguments, and add the contact to the group.", - "The 'remove' command takes 'group' and 'contact' arguments and removed the contact from the group,", + "The 'add' command takes 'group' and 'contact' arguments, and adds the contact to the group.", + "The 'remove' command takes 'group' and 'contact' arguments and removes the contact from the group,", "", "Example : /group", "Example : /group show friends", "Example : /group add friends newfriend@server.org", - "Example : /group add family brother (using contacts nickname)", + "Example : /group add family Brother (using contacts nickname)", "Example : /group remove colleagues boss@work.com", NULL } } }, { "/info", _cmd_info, parse_args, 0, 1, NULL, - { "/info [jid|nick]", "Show basic information about a contact, or room member.", - { "/info [jid|nick]", - "----------------", + { "/info [contact|nick]", "Show basic information about a contact, or room member.", + { "/info [contact|nick]", + "--------------------", "Show information including current subscription status and summary information for each connected resource.", "If in a chat window the parameter is not required, the current recipient will be used.", "", - "Example : /info mybuddy@chat.server.org (contact)", - "Example : /info kai (room member)", + "Example : /info mybuddy@chat.server.org", + "Example : /info kai", NULL } } }, { "/caps", @@ -284,7 +284,7 @@ static struct cmd_t command_defs[] = "If in the console window or a regular chat window, a full JID is required.", "If in a chat room, the nickname is required.", "If in private chat, no parameter is required.", - "If the contacts software does not support software version requests, nothing will be displayed.", + "If the contact's software does not support software version requests, nothing will be displayed.", "", "Example : /software mybuddy@chat.server.org/laptop (contact's laptop resource)", "Example : /software mybuddy@chat.server.org/phone (contact's phone resource)", @@ -293,14 +293,14 @@ static struct cmd_t command_defs[] = { "/status", _cmd_status, parse_args, 0, 1, NULL, - { "/status [jid|nick]", "Find out your contacts presence information.", - { "/status [jid|nick]", - "------------------", + { "/status [contact|nick]", "Find out a contacts presence information.", + { "/status [contact|nick]", + "----------------------", "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.", "", - "Example : /status buddy@server.com (contact)", - "Example : /status jon (room member)", + "Example : /status buddy@server.com", + "Example : /status jon", NULL } } }, { "/join", @@ -311,7 +311,7 @@ static struct cmd_t command_defs[] = "Join a chat room at the conference server.", "If nick is specified you will join with this nickname.", "Otherwise the 'localpart' of your JID (before the @) will be used.", - "If no server is supplied, it will default to 'conference.'", + "If no server is supplied, a default of 'conference.' will be used.", "If the room doesn't exist, and the server allows it, a new one will be created.", "", "Example : /join jdev@conference.jabber.org", @@ -329,11 +329,10 @@ static struct cmd_t command_defs[] = { "/invite", _cmd_invite, parse_args_with_freetext, 1, 2, NULL, - { "/invite jid [message]", "Invite contact to chat room.", - { "/invite jid [message]", - "--------------------------", + { "/invite contact [message]", "Invite contact to chat room.", + { "/invite contact [message]", + "-------------------------", "Send a direct invite to the specified contact to the current chat room.", - "The jid must be a contact in your roster.", "If a message is supplied it will be send as the reason for the invite.", NULL } } }, @@ -404,7 +403,7 @@ static struct cmd_t command_defs[] = { "/wins [tidy|prune]", "------------------", "Passing no argument will list all currently active windows and information about their usage.", - "tidy : Shuffle windows so there are no gaps between used windows.", + "tidy : Shuffle windows so there are no gaps.", "prune : Close all windows with no unread messages, and then tidy as above.", NULL } } }, @@ -438,7 +437,7 @@ static struct cmd_t command_defs[] = "---------", "Send the url as a tiny url.", "", - "Example : /tiny http://www.google.com", + "Example : /tiny http://www.profanity.im", NULL } } }, { "/duck", @@ -522,7 +521,6 @@ static struct cmd_t command_defs[] = " : on|off", "invite : Notifications for chat room invites.", " : on|off", - "", "sub : Notifications for subscription requests.", " : on|off", "", @@ -644,7 +642,7 @@ static struct cmd_t command_defs[] = { "/history on|off", "Chat history in message windows.", { "/history on|off", "---------------", - "Switch chat history on or off, requires /chlog will automatically be enabled when this setting in on.", + "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.", NULL } } }, @@ -663,7 +661,7 @@ static struct cmd_t command_defs[] = { "/reconnect seconds", "------------------", "Set the reconnect attempt interval in seconds for when the connection is lost.", - "A value of 0 will switch of reconnect attempts.", + "A value of 0 will switch off reconnect attempts.", NULL } } }, { "/autoping", From 817857e4c0d986226b7c213debca9de4f32e979a Mon Sep 17 00:00:00 2001 From: James Booth Date: Wed, 3 Jul 2013 21:23:18 +0100 Subject: [PATCH 4/8] Fixed naming clash for roster help --- src/command/command.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/command/command.c b/src/command/command.c index 4af0da96..63d003f4 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -870,7 +870,7 @@ cmd_init(void) autocomplete_add(help_ac, strdup("chatting")); autocomplete_add(help_ac, strdup("groupchat")); autocomplete_add(help_ac, strdup("presence")); - autocomplete_add(help_ac, strdup("roster")); + autocomplete_add(help_ac, strdup("contacts")); autocomplete_add(help_ac, strdup("service")); autocomplete_add(help_ac, strdup("settings")); autocomplete_add(help_ac, strdup("other")); @@ -1739,7 +1739,7 @@ _cmd_help(gchar **args, struct cmd_help_t help) "/xa" }; _cmd_show_filtered_help("Presence commands", filter, ARRAY_SIZE(filter)); - } else if (strcmp(args[0], "roster") == 0) { + } else if (strcmp(args[0], "contacts") == 0) { gchar *filter[] = { "/group", "/roster", "/sub", "/who" }; _cmd_show_filtered_help("Roster commands", filter, ARRAY_SIZE(filter)); From 581c1e8b951d7b9841cec56d5ebf9d3c138e6ce9 Mon Sep 17 00:00:00 2001 From: James Booth Date: Wed, 3 Jul 2013 23:44:51 +0100 Subject: [PATCH 5/8] Coloured contact and subscription in /roster and /group output --- src/config/theme.c | 14 ++++++ src/config/theme.h | 2 + src/contact.c | 14 ++++++ src/contact.h | 1 + src/ui/console.c | 117 ++++++++++++++++++++++++--------------------- src/xmpp/roster.c | 18 +++---- 6 files changed, 103 insertions(+), 63 deletions(-) diff --git a/src/config/theme.c b/src/config/theme.c index 5ca19969..1c0d176a 100644 --- a/src/config/theme.c +++ b/src/config/theme.c @@ -72,6 +72,8 @@ static struct colours_t { NCURSES_COLOR_T inputtext; NCURSES_COLOR_T timetext; NCURSES_COLOR_T splashtext; + NCURSES_COLOR_T subscribed; + NCURSES_COLOR_T unsubscribed; NCURSES_COLOR_T online; NCURSES_COLOR_T away; NCURSES_COLOR_T xa; @@ -220,6 +222,10 @@ theme_init_colours(void) // states init_pair(60, colour_prefs.typing, colour_prefs.bkgnd); init_pair(61, colour_prefs.gone, colour_prefs.bkgnd); + + // subscription status + init_pair(70, colour_prefs.subscribed, colour_prefs.bkgnd); + init_pair(71, colour_prefs.unsubscribed, colour_prefs.bkgnd); } static NCURSES_COLOR_T @@ -306,6 +312,14 @@ _load_colours(void) _set_colour(timetext_val, &colour_prefs.timetext, COLOR_WHITE); g_free(timetext_val); + gchar *subscribed_val = g_key_file_get_string(theme, "colours", "subscribed", NULL); + _set_colour(subscribed_val, &colour_prefs.subscribed, COLOR_GREEN); + g_free(subscribed_val); + + gchar *unsubscribed_val = g_key_file_get_string(theme, "colours", "unsubscribed", NULL); + _set_colour(unsubscribed_val, &colour_prefs.unsubscribed, COLOR_RED); + g_free(unsubscribed_val); + gchar *online_val = g_key_file_get_string(theme, "colours", "online", NULL); _set_colour(online_val, &colour_prefs.online, COLOR_GREEN); g_free(online_val); diff --git a/src/config/theme.h b/src/config/theme.h index d87b69f2..8878d7b2 100644 --- a/src/config/theme.h +++ b/src/config/theme.h @@ -55,6 +55,8 @@ #define COLOUR_XA COLOR_PAIR(55) #define COLOUR_TYPING COLOR_PAIR(60) #define COLOUR_GONE COLOR_PAIR(61) +#define COLOUR_SUBSCRIBED COLOR_PAIR(70) +#define COLOUR_UNSUBSCRIBED COLOR_PAIR(71) void theme_init(const char * const theme_name); void theme_init_colours(void); diff --git a/src/contact.c b/src/contact.c index bab3d89c..44cbd4b4 100644 --- a/src/contact.c +++ b/src/contact.c @@ -252,6 +252,20 @@ p_contact_subscription(const PContact contact) return contact->subscription; } +gboolean +p_contact_subscribed(const PContact contact) +{ + if (contact->subscription == NULL) { + return FALSE; + } else if (strcmp(contact->subscription, "to") == 0) { + return TRUE; + } else if (strcmp(contact->subscription, "both") == 0) { + return TRUE; + } else { + return FALSE; + } +} + Resource * p_contact_get_resource(const PContact contact, const char * const resource) { diff --git a/src/contact.h b/src/contact.h index cfd8b4d4..141587a0 100644 --- a/src/contact.h +++ b/src/contact.h @@ -53,5 +53,6 @@ Resource * p_contact_get_resource(const PContact contact, const char * const res void p_contact_set_groups(const PContact contact, GSList *groups); GSList * p_contact_groups(const PContact contact); gboolean p_contact_in_group(const PContact contact, const char * const group); +gboolean p_contact_subscribed(const PContact contact); #endif diff --git a/src/ui/console.c b/src/ui/console.c index 67f3fa28..ee5ad221 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -43,6 +43,7 @@ static ProfWin* console; static void _cons_splash_logo(void); +void _show_roster_contacts(GSList *list, gboolean show_groups); ProfWin * cons_create(void) @@ -1307,17 +1308,9 @@ cons_navigation_help(void) } void -cons_show_roster_group(const char * const group, GSList *list) +_show_roster_contacts(GSList *list, gboolean show_groups) { GSList *curr = list; - cons_show(""); - - if (curr != NULL) { - cons_show("%s:", group); - } else { - cons_show("No group named %s exists.", group); - } - while(curr) { PContact contact = curr->data; @@ -1328,10 +1321,24 @@ cons_show_roster_group(const char * const group, GSList *list) title = g_string_append(title, strdup(p_contact_name(contact))); title = g_string_append(title, ")"); } - cons_show(title->str); + + const char *presence = p_contact_presence(contact); + win_print_time(console, '-'); + if (p_contact_subscribed(contact)) { + win_presence_colour_on(console, presence); + wprintw(console->win, "%s\n", title->str); + win_presence_colour_off(console, presence); + } else { + win_presence_colour_on(console, "offline"); + wprintw(console->win, "%s\n", title->str); + win_presence_colour_off(console, "offline"); + } + g_string_free(title, TRUE); - GString *sub = g_string_new(" Subscription : "); + win_print_time(console, '-'); + wprintw(console->win, " Subscription : "); + GString *sub = g_string_new(""); sub = g_string_append(sub, p_contact_subscription(contact)); if (p_contact_pending_out(contact)) { sub = g_string_append(sub, ", request sent"); @@ -1339,12 +1346,54 @@ cons_show_roster_group(const char * const group, GSList *list) if (presence_sub_request_exists(p_contact_barejid(contact))) { sub = g_string_append(sub, ", request received"); } - cons_show(sub->str); + if (p_contact_subscribed(contact)) { + wattron(console->win, COLOUR_SUBSCRIBED); + } else { + wattron(console->win, COLOUR_UNSUBSCRIBED); + } + wprintw(console->win, "%s\n", sub->str); + if (p_contact_subscribed(contact)) { + wattroff(console->win, COLOUR_SUBSCRIBED); + } else { + wattroff(console->win, COLOUR_UNSUBSCRIBED); + } + g_string_free(sub, TRUE); + if (show_groups) { + GSList *groups = p_contact_groups(contact); + if (groups != NULL) { + GString *groups_str = g_string_new(" Groups : "); + while (groups != NULL) { + g_string_append(groups_str, strdup(groups->data)); + if (g_slist_next(groups) != NULL) { + g_string_append(groups_str, ", "); + } + groups = g_slist_next(groups); + } + + cons_show(groups_str->str); + g_string_free(groups_str, TRUE); + } + } + curr = g_slist_next(curr); } +} + +void +cons_show_roster_group(const char * const group, GSList *list) +{ + cons_show(""); + + if (list != NULL) { + cons_show("%s:", group); + } else { + cons_show("No group named %s exists.", group); + } + + _show_roster_contacts(list, FALSE); ui_console_dirty(); cons_alert(); } @@ -1352,52 +1401,10 @@ cons_show_roster_group(const char * const group, GSList *list) void cons_show_roster(GSList *list) { - GSList *curr = list; cons_show(""); cons_show("Roster:"); - while(curr) { - - PContact contact = curr->data; - GString *title = g_string_new(" "); - title = g_string_append(title, p_contact_barejid(contact)); - if (p_contact_name(contact) != NULL) { - title = g_string_append(title, " ("); - title = g_string_append(title, strdup(p_contact_name(contact))); - title = g_string_append(title, ")"); - } - cons_show(title->str); - g_string_free(title, TRUE); - - GString *sub = g_string_new(" Subscription : "); - sub = g_string_append(sub, p_contact_subscription(contact)); - if (p_contact_pending_out(contact)) { - sub = g_string_append(sub, ", request sent"); - } - if (presence_sub_request_exists(p_contact_barejid(contact))) { - sub = g_string_append(sub, ", request received"); - } - cons_show(sub->str); - g_string_free(sub, TRUE); - - GSList *groups = p_contact_groups(contact); - if (groups != NULL) { - GString *groups_str = g_string_new(" Groups : "); - while (groups != NULL) { - g_string_append(groups_str, strdup(groups->data)); - if (g_slist_next(groups) != NULL) { - g_string_append(groups_str, ", "); - } - groups = g_slist_next(groups); - } - - cons_show(groups_str->str); - g_string_free(groups_str, TRUE); - } - - curr = g_slist_next(curr); - } - + _show_roster_contacts(list, TRUE); ui_console_dirty(); cons_alert(); } diff --git a/src/xmpp/roster.c b/src/xmpp/roster.c index f96a3f84..ed72d502 100644 --- a/src/xmpp/roster.c +++ b/src/xmpp/roster.c @@ -562,14 +562,16 @@ _roster_handle_push(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, // remove each fulljid PContact contact = roster_get_contact(barejid); - GList *resources = p_contact_get_available_resources(contact); - while (resources != NULL) { - GString *fulljid = g_string_new(strdup(barejid)); - g_string_append(fulljid, "/"); - g_string_append(fulljid, strdup(resources->data)); - autocomplete_remove(fulljid_ac, fulljid->str); - g_string_free(fulljid, TRUE); - resources = g_list_next(resources); + if (contact != NULL) { + GList *resources = p_contact_get_available_resources(contact); + while (resources != NULL) { + GString *fulljid = g_string_new(strdup(barejid)); + g_string_append(fulljid, "/"); + g_string_append(fulljid, strdup(resources->data)); + autocomplete_remove(fulljid_ac, fulljid->str); + g_string_free(fulljid, TRUE); + resources = g_list_next(resources); + } } // remove the contact From e99a0e117a51436932d90aee5d5c1c12c5cf7681 Mon Sep 17 00:00:00 2001 From: James Booth Date: Tue, 9 Jul 2013 22:34:55 +0100 Subject: [PATCH 6/8] Fix autocompletion of quoted strings - WIP Needs some refactoring Need to use unicode functions in: parser.c autocomplete.c --- src/command/parser.c | 18 +++++-- src/tools/autocomplete.c | 109 ++++++++++++++++++++++++++++++++------- 2 files changed, 104 insertions(+), 23 deletions(-) diff --git a/src/command/parser.c b/src/command/parser.c index af01ddcc..d7dfebab 100644 --- a/src/command/parser.c +++ b/src/command/parser.c @@ -201,8 +201,14 @@ parse_args_with_freetext(const char * const inp, int min, int max) in_quotes = TRUE; i++; } - token_start = ©[i]; - token_size++; + if (copy[i] == '"') { + token_start = ©[i+1]; + } else { + token_start = ©[i]; + } + if (copy[i] != '"') { + token_size++; + } } } else { if (in_quotes) { @@ -213,7 +219,9 @@ parse_args_with_freetext(const char * const inp, int min, int max) in_token = FALSE; in_quotes = FALSE; } else { - token_size++; + if (copy[i] != '"') { + token_size++; + } } } else { if ((!in_freetext && copy[i] == ' ') || copy[i] == '\0') { @@ -222,7 +230,9 @@ parse_args_with_freetext(const char * const inp, int min, int max) token_size = 0; in_token = FALSE; } else { - token_size++; + if (copy[i] != '"') { + token_size++; + } } } } diff --git a/src/tools/autocomplete.c b/src/tools/autocomplete.c index e3829f7f..086dfabe 100644 --- a/src/tools/autocomplete.c +++ b/src/tools/autocomplete.c @@ -26,6 +26,8 @@ #include "autocomplete.h" +#include "ui/ui.h" + struct autocomplete_t { GSList *items; GSList *last_found; @@ -260,6 +262,84 @@ autocomplete_param_with_ac(char *input, int *size, char *command, return auto_msg; } +int +_count_tokens(char *string) +{ + int num_tokens = 0; + + cons_debug("String: %s", string); + + // if no quotes, use glib + if (g_strrstr(string, "\"") == NULL) { + cons_debug("NO QUOTES"); + gchar **tokens = g_strsplit(string, " ", 0); + num_tokens = g_strv_length(tokens); + g_strfreev(tokens); + + // else count tokens including quoted + } else { + cons_debug("QUOTES"); + int length = strlen(string); + int i = 0; + gboolean in_quotes = FALSE; + + // include first token + num_tokens++; + + for (i = 0; i < length; i++) { + if (string[i] == ' ') { + if (!in_quotes) { + num_tokens++; + } + } else if (string[i] == '"') { + if (in_quotes) { + in_quotes = FALSE; + } else { + in_quotes = TRUE; + } + } + } + } + + return num_tokens; +} + +char * +_get_start(char *string, int tokens) +{ + char *result_str = NULL; + int num_tokens = 0; + int length = strlen(string); + int i = 0; + gboolean in_quotes = FALSE; + GString *result = g_string_new(""); + + // include first token + num_tokens++; + + for (i = 0; i < length; i++) { + if (num_tokens < tokens) { + g_string_append_c(result, string[i]); + } + if (string[i] == ' ') { + if (!in_quotes) { + num_tokens++; + } + } else if (string[i] == '"') { + if (in_quotes) { + in_quotes = FALSE; + } else { + in_quotes = TRUE; + } + } + } + + result_str = result->str; + g_string_free(result, FALSE); + + return result_str; +} + char * autocomplete_param_no_with_func(char *input, int *size, char *command, int arg_number, autocomplete_func func) @@ -267,44 +347,35 @@ autocomplete_param_no_with_func(char *input, int *size, char *command, char *result = NULL; if (strncmp(input, command, strlen(command)) == 0 && (*size > strlen(command))) { int i = 0; - int quote_count = 0; char *found = NULL; GString *result_str = NULL; - // copy and null terminate input, count quotes + // copy and null terminate input gchar inp_cpy[*size]; for (i = 0; i < *size; i++) { - if (input[i] == '"') { - quote_count++; - } inp_cpy[i] = input[i]; } inp_cpy[i] = '\0'; g_strstrip(inp_cpy); - // count tokens - gchar **tokens = g_strsplit(inp_cpy, " ", 0); - int num_tokens = g_strv_length(tokens); + // count tokens properly + int num_tokens = _count_tokens(inp_cpy); + cons_debug("tokens: %d", num_tokens); - // if num tokens, or 2 quotes then candidate for autocompletion of last param - if (((num_tokens > arg_number - 1) && quote_count == 0) || quote_count == 2) { + // if correct number of tokens, then candidate for autocompletion of last param + if (num_tokens == arg_number) { - gchar *comp_str = NULL; + gchar *start_str = _get_start(inp_cpy, arg_number); + cons_debug("STARTSTR: %s", start_str); - // find start of autocompletion string - if (num_tokens > 3 && quote_count == 0) { - comp_str = g_strrstr(inp_cpy, tokens[arg_number - 1]); - } else { - comp_str = g_strrstr(inp_cpy, "\""); - comp_str = comp_str + 2; - } + gchar *comp_str = g_strdup(&inp_cpy[strlen(start_str)]); // autocomplete param if (comp_str != NULL) { found = func(comp_str); if (found != NULL) { result_str = g_string_new(""); - g_string_append(result_str, g_strndup(inp_cpy, strlen(inp_cpy) - strlen(comp_str))); + g_string_append(result_str, start_str); g_string_append(result_str, found); result = result_str->str; g_string_free(result_str, FALSE); From 907beb55f6dba952b6b07579c919fad251b7a0c0 Mon Sep 17 00:00:00 2001 From: James Booth Date: Tue, 9 Jul 2013 22:42:20 +0100 Subject: [PATCH 7/8] Removed debug --- src/tools/autocomplete.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/tools/autocomplete.c b/src/tools/autocomplete.c index 086dfabe..849aaf1d 100644 --- a/src/tools/autocomplete.c +++ b/src/tools/autocomplete.c @@ -26,8 +26,6 @@ #include "autocomplete.h" -#include "ui/ui.h" - struct autocomplete_t { GSList *items; GSList *last_found; @@ -267,18 +265,14 @@ _count_tokens(char *string) { int num_tokens = 0; - cons_debug("String: %s", string); - // if no quotes, use glib if (g_strrstr(string, "\"") == NULL) { - cons_debug("NO QUOTES"); gchar **tokens = g_strsplit(string, " ", 0); num_tokens = g_strv_length(tokens); g_strfreev(tokens); // else count tokens including quoted } else { - cons_debug("QUOTES"); int length = strlen(string); int i = 0; gboolean in_quotes = FALSE; @@ -360,14 +354,10 @@ autocomplete_param_no_with_func(char *input, int *size, char *command, // count tokens properly int num_tokens = _count_tokens(inp_cpy); - cons_debug("tokens: %d", num_tokens); // if correct number of tokens, then candidate for autocompletion of last param if (num_tokens == arg_number) { - gchar *start_str = _get_start(inp_cpy, arg_number); - cons_debug("STARTSTR: %s", start_str); - gchar *comp_str = g_strdup(&inp_cpy[strlen(start_str)]); // autocomplete param From 1d05a7047314fa3c669358114dc6ce36bbc08386 Mon Sep 17 00:00:00 2001 From: James Booth Date: Sat, 13 Jul 2013 22:59:42 +0100 Subject: [PATCH 8/8] Down arrow adds current line to history and shows empty line --- src/tools/history.c | 4 ++++ src/ui/inputwin.c | 4 ++++ tests/test_history.c | 6 +++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/tools/history.c b/src/tools/history.c index 5ac41969..b80a9555 100644 --- a/src/tools/history.c +++ b/src/tools/history.c @@ -146,6 +146,10 @@ history_next(History history, char *item) return NULL; } + if (g_list_next(history->session.sess_curr) == NULL) { + return NULL; + } + char *copied = ""; if (item != NULL) { copied = strdup(item); diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c index 3f3d2ab5..feb4a0ba 100644 --- a/src/ui/inputwin.c +++ b/src/ui/inputwin.c @@ -490,6 +490,10 @@ _handle_edit(int result, const wint_t ch, char *input, int *size) next = cmd_history_next(input, size); if (next) { inp_replace_input(input, next, size); + } else if (*size != 0) { + input[*size] = '\0'; + cmd_history_append(input); + inp_replace_input(input, "", size); } return 1; diff --git a/tests/test_history.c b/tests/test_history.c index 91e5aa99..6af96946 100644 --- a/tests/test_history.c +++ b/tests/test_history.c @@ -93,7 +93,7 @@ void prev_with_val_then_next_returns_val(void) assert_string_equals("Oioi", item2); } -void prev_with_val_then_next_twice_returns_val(void) +void prev_with_val_then_next_twice_returns_null(void) { History history = history_new(10); history_append(history, "Hello"); @@ -102,7 +102,7 @@ void prev_with_val_then_next_twice_returns_val(void) char *item2 = history_next(history, item1); char *item3 = history_next(history, item2); - assert_string_equals("Oioi", item3); + assert_is_null(item3); } void navigate_then_append_new(void) @@ -225,7 +225,7 @@ void register_history_tests(void) TEST(previous_goes_to_correct_element); TEST(prev_then_next_returns_empty); TEST(prev_with_val_then_next_returns_val); - TEST(prev_with_val_then_next_twice_returns_val); + TEST(prev_with_val_then_next_twice_returns_null); TEST(navigate_then_append_new); TEST(edit_item_mid_history); TEST(edit_previous_and_append);