diff options
author | Manish Goregaokar <manishsmail@gmail.com> | 2018-01-19 18:34:30 +0530 |
---|---|---|
committer | Manish Goregaokar <manishsmail@gmail.com> | 2018-01-20 10:25:06 +0530 |
commit | 12d08f79bbec3582fe079ec5a5d0f91002f62037 (patch) | |
tree | cb26a75ae9532567d38dee726e6b9e59ce41a26e /src/fe-common/core | |
parent | 243ae4be84d422322f20be1b715dc0b00ef9c32d (diff) | |
download | irssi-12d08f79bbec3582fe079ec5a5d0f91002f62037.zip |
Insert colons after completing nicks preceded by a list of other autocompleted nicks
When pinging two people, typing `nick1<tab> nick2<tab> message` for
autocompletion will get you `nick1: nick2 message`, which is kinda
confusing.
We only insert the colon after the first autocompleted nick,
because if a nick is used in the middle of the sentence it's mentioning
the person but not targeting the message at them.
However, this breaks down when we try to ping a list of people. There
should be a colon in front of each separating the names from the
message. only having a colon at the end of the nick list works too,
but it seems like the IRC convention is to just use multiple colons.
This patch makes it so that autocompleting a nick after a list of
existing autocompleted nicks at the beginning of the message
will include a colon.
Diffstat (limited to 'src/fe-common/core')
-rw-r--r-- | src/fe-common/core/chat-completion.c | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/src/fe-common/core/chat-completion.c b/src/fe-common/core/chat-completion.c index 97cd0565..7ecdd4a2 100644 --- a/src/fe-common/core/chat-completion.c +++ b/src/fe-common/core/chat-completion.c @@ -639,6 +639,59 @@ static void complete_window_nicks(GList **list, WINDOW_REC *window, } } +/* Checks if a line is only nicks from autocompletion. + This lets us insert colons only at the beginning of a list + of nicks */ +static int only_nicks(const char *linestart) +{ + int i = 1; + char prev; + + // at the beginning of the line + if (*linestart == '\0') { + return TRUE; + } + + /* completion_char being a whole string introduces loads of edge cases + and can't be handled generally. Skip this case; we handled the + "beginning of line" case already */ + if (completion_char[1] != '\0') + return FALSE; + + /* This would make the completion char get inserted everywhere otherwise */ + if (*completion_char == ' ') + return FALSE; + + /* First ensure that the line is of the format "foo: bar: baz" + we check this by ensuring each space is preceded by a colon or + another space */ + while (linestart[i] != '\0') { + if (linestart[i] == ' ') { + prev = linestart[i - 1]; + if (prev != *completion_char && prev != ' ') + return FALSE; + } + i += 1; + } + + /* There's an edge case here, if we're completing something + like `foo: bar ba<tab>`, then the `linestart` line will end + at "bar", and we'll miss the space. Ensure that the end + of the line is a colon followed by an optional series of spaces */ + i -= 1; + while (i >= 0) { + if (linestart[i] == ' ') { + i--; + continue; + } else if (linestart[i] == *completion_char) { + return TRUE; + } else { + break; + } + } + return FALSE; +} + static void sig_complete_word(GList **list, WINDOW_REC *window, const char *word, const char *linestart, int *want_space) @@ -691,7 +744,7 @@ static void sig_complete_word(GList **list, WINDOW_REC *window, } else if (channel != NULL) { /* nick completion .. we could also be completing a nick after /MSG from nicks in channel */ - const char *suffix = *linestart != '\0' ? NULL : completion_char; + const char *suffix = only_nicks(linestart) ? completion_char : NULL; complete_window_nicks(list, window, word, suffix); } else if (window->level & MSGLEVEL_MSGS) { /* msgs window, complete /MSG nicks */ |