Improved nick completion: completes with last speakers first (task #5896), fixed nick completion (bugs #19590 and #19589)

This commit is contained in:
Sebastien Helleu 2007-04-14 13:14:05 +00:00
parent a89ca83306
commit f30fb21175
38 changed files with 8304 additions and 7766 deletions

View File

@ -1,10 +1,15 @@
WeeChat - Wee Enhanced Environment for Chat
===========================================
ChangeLog - 2007-04-04
ChangeLog - 2007-04-14
Version 0.2.5 (under dev!):
* improved nick completion: added option look_nick_completion_smart,
enabled by default (task #5896)
* fixed nick completion in command arguments (bug #19590)
* fixed possible crash with nick completion when a nick leaves channel
(bug #19589)
* added color for input text not found in buffer history
* fixed USER message when connecting to IRC server (patch #5835)

1075
po/cs.po

File diff suppressed because it is too large Load Diff

1075
po/de.po

File diff suppressed because it is too large Load Diff

1075
po/es.po

File diff suppressed because it is too large Load Diff

1078
po/fr.po

File diff suppressed because it is too large Load Diff

1075
po/hu.po

File diff suppressed because it is too large Load Diff

1075
po/ru.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -251,7 +251,8 @@ command_index_build ()
while (weechat_commands[i].command_name)
{
(void) weelist_add (&index_commands, &last_index_command,
weechat_commands[i].command_name);
weechat_commands[i].command_name,
WEELIST_POS_SORT);
i++;
}
i = 0;
@ -259,7 +260,8 @@ command_index_build ()
{
if (irc_commands[i].cmd_function_args || irc_commands[i].cmd_function_1arg)
(void) weelist_add (&index_commands, &last_index_command,
irc_commands[i].command_name);
irc_commands[i].command_name,
WEELIST_POS_SORT);
i++;
}
}
@ -945,7 +947,8 @@ weechat_cmd_alias (t_irc_server *server, t_irc_channel *channel,
}
if (!alias_new (arguments, pos))
return -1;
if (weelist_add (&index_commands, &last_index_command, arguments))
if (weelist_add (&index_commands, &last_index_command, arguments,
WEELIST_POS_SORT))
{
irc_display_prefix (NULL, NULL, PREFIX_INFO);
gui_printf (NULL, _("Alias \"%s\" => \"%s\" created\n"),

View File

@ -95,12 +95,14 @@ completion_free (t_completion *completion)
free (completion->args);
completion->args = NULL;
while (completion->completion_list)
weelist_remove (&completion->completion_list,
&completion->last_completion,
completion->completion_list);
weelist_remove_all (&completion->completion_list,
&completion->last_completion);
completion->completion_list = NULL;
completion->last_completion = NULL;
if (completion->word_found)
free (completion->word_found);
completion->word_found = NULL;
}
/*
@ -203,20 +205,95 @@ completion_get_command_infos (t_completion *completion,
return;
}
/*
* completion_is_only_alphanum: return 1 if there is only alpha/num chars
* in a string
*/
int
completion_is_only_alphanum (char *string)
{
while (string[0])
{
if (strchr (cfg_look_nick_completion_ignore, string[0]))
return 0;
string++;
}
return 1;
}
/*
* completion_strdup_alphanum: duplicate alpha/num chars in a string
*/
char *
completion_strdup_alphanum (char *string)
{
char *result, *pos;
result = (char *)malloc (strlen (string) + 1);
pos = result;
while (string[0])
{
if (!strchr (cfg_look_nick_completion_ignore, string[0]))
{
pos[0] = string[0];
pos++;
}
string++;
}
pos[0] = '\0';
return result;
}
/*
* completion_nickncmp: locale and case independent string comparison
* with max length for nicks (alpha or digits only)
*/
int
completion_nickncmp (char *base_word, char *nick, int max)
{
char *base_word2, *nick2;
int return_cmp;
if (!cfg_look_nick_completion_ignore
|| !cfg_look_nick_completion_ignore[0]
|| !base_word || !nick || !base_word[0] || !nick[0]
|| (!completion_is_only_alphanum (base_word)))
return ascii_strncasecmp (base_word, nick, max);
base_word2 = completion_strdup_alphanum (base_word);
nick2 = completion_strdup_alphanum (nick);
return_cmp = ascii_strncasecmp (base_word2, nick2, strlen (base_word2));
free (base_word2);
free (nick2);
return return_cmp;
}
/*
* completion_list_add: add a word to completion word list
* if nick_completion != 0, then add as a nick
* if nick_completion < 0, then add at beginning of list
*/
void
completion_list_add (t_completion *completion, char *word)
completion_list_add (t_completion *completion, char *word, int nick_completion)
{
if (!completion->base_word || !completion->base_word[0]
|| (ascii_strncasecmp (completion->base_word, word,
strlen (completion->base_word)) == 0))
|| ((nick_completion != 0) && (completion_nickncmp (completion->base_word, word,
strlen (completion->base_word)) == 0))
|| ((nick_completion == 0) && (ascii_strncasecmp (completion->base_word, word,
strlen (completion->base_word)) == 0)))
{
weelist_add (&completion->completion_list,
&completion->last_completion,
word);
word,
(nick_completion < 0) ?
WEELIST_POS_BEGINNING : WEELIST_POS_SORT);
}
}
@ -231,7 +308,7 @@ completion_list_add_alias (t_completion *completion)
for (ptr_alias = weechat_alias; ptr_alias; ptr_alias = ptr_alias->next_alias)
{
completion_list_add (completion, ptr_alias->alias_name);
completion_list_add (completion, ptr_alias->alias_name, 0);
}
}
@ -246,7 +323,7 @@ completion_list_add_alias_cmd (t_completion *completion)
for (ptr_list = index_commands; ptr_list; ptr_list = ptr_list->next_weelist)
{
completion_list_add (completion, ptr_list->data);
completion_list_add (completion, ptr_list->data, 0);
}
}
@ -259,7 +336,7 @@ completion_list_add_channel (t_completion *completion)
{
if (completion->channel)
completion_list_add (completion,
((t_irc_channel *)(completion->channel))->name);
((t_irc_channel *)(completion->channel))->name, 0);
}
/*
@ -276,7 +353,7 @@ completion_list_add_server_channels (t_completion *completion)
for (ptr_channel = ((t_irc_server *)(completion->server))->channels;
ptr_channel; ptr_channel = ptr_channel->next_channel)
{
completion_list_add (completion, ptr_channel->name);
completion_list_add (completion, ptr_channel->name, 0);
}
}
}
@ -361,7 +438,7 @@ completion_list_add_filename (t_completion *completion)
entry->d_name,
S_ISDIR(statbuf.st_mode) ? DIR_SEPARATOR : "");
completion_list_add (completion, buffer);
completion_list_add (completion, buffer, 0);
}
}
}
@ -392,7 +469,7 @@ completion_list_add_plugin_cmd (t_completion *completion)
ptr_handler; ptr_handler = ptr_handler->next_handler)
{
if (ptr_handler->type == PLUGIN_HANDLER_COMMAND)
completion_list_add (completion, ptr_handler->command);
completion_list_add (completion, ptr_handler->command, 0);
}
}
#else
@ -413,7 +490,7 @@ completion_list_add_irc_cmd_sent (t_completion *completion)
for (i = 0; irc_commands[i].command_name; i++)
{
if (irc_commands[i].cmd_function_args || irc_commands[i].cmd_function_1arg)
completion_list_add (completion, irc_commands[i].command_name);
completion_list_add (completion, irc_commands[i].command_name, 0);
}
}
@ -429,7 +506,7 @@ completion_list_add_irc_cmd_recv (t_completion *completion)
for (i = 0; irc_commands[i].command_name; i++)
{
if (irc_commands[i].recv_function)
completion_list_add(completion, irc_commands[i].command_name);
completion_list_add(completion, irc_commands[i].command_name, 0);
}
}
@ -444,7 +521,7 @@ completion_list_add_key_cmd (t_completion *completion)
for (i = 0; gui_key_functions[i].function_name; i++)
{
completion_list_add (completion, gui_key_functions[i].function_name);
completion_list_add (completion, gui_key_functions[i].function_name, 0);
}
}
@ -457,7 +534,8 @@ completion_list_add_self_nick (t_completion *completion)
{
if (completion->server)
{
completion_list_add (completion, ((t_irc_server *)(completion->server))->nick);
completion_list_add (completion,
((t_irc_server *)(completion->server))->nick, 0);
}
}
@ -469,22 +547,34 @@ void
completion_list_add_channel_nicks (t_completion *completion)
{
t_irc_nick *ptr_nick;
t_weelist *ptr_weelist;
if (completion->channel)
{
if (((t_irc_channel *)(completion->channel))->type == CHANNEL_TYPE_CHANNEL)
{
/* add channel nicks */
for (ptr_nick = ((t_irc_channel *)(completion->channel))->nicks;
ptr_nick; ptr_nick = ptr_nick->next_nick)
{
completion_list_add (completion, ptr_nick->nick);
completion_list_add (completion, ptr_nick->nick, 1);
}
/* add nicks speaking recently on this channel */
if (cfg_look_nick_completion_smart)
{
for (ptr_weelist = ((t_irc_channel *)(completion->channel))->nicks_speaking;
ptr_weelist; ptr_weelist = ptr_weelist->next_weelist)
{
if (nick_search ((t_irc_channel *)(completion->channel), ptr_weelist->data))
completion_list_add (completion, ptr_weelist->data, -1);
}
}
}
if ((((t_irc_channel *)(completion->channel))->type == CHANNEL_TYPE_PRIVATE)
|| (((t_irc_channel *)(completion->channel))->type == CHANNEL_TYPE_DCC_CHAT))
{
completion_list_add (completion,
((t_irc_channel *)(completion->channel))->name);
((t_irc_channel *)(completion->channel))->name, 1);
}
completion->arg_is_nick = 1;
}
@ -508,7 +598,7 @@ completion_list_add_channel_nicks_hosts (t_completion *completion)
for (ptr_nick = ((t_irc_channel *)(completion->channel))->nicks;
ptr_nick; ptr_nick = ptr_nick->next_nick)
{
completion_list_add (completion, ptr_nick->nick);
completion_list_add (completion, ptr_nick->nick, 1);
if (ptr_nick->host)
{
length = strlen (ptr_nick->nick) + 1 +
@ -518,7 +608,7 @@ completion_list_add_channel_nicks_hosts (t_completion *completion)
{
snprintf (buf, length, "%s!%s",
ptr_nick->nick, ptr_nick->host);
completion_list_add (completion, buf);
completion_list_add (completion, buf, 1);
free (buf);
}
}
@ -528,7 +618,7 @@ completion_list_add_channel_nicks_hosts (t_completion *completion)
|| (((t_irc_channel *)(completion->channel))->type == CHANNEL_TYPE_PRIVATE))
{
completion_list_add (completion,
((t_irc_channel *)(completion->channel))->name);
((t_irc_channel *)(completion->channel))->name, 1);
}
completion->arg_is_nick = 1;
}
@ -553,7 +643,7 @@ completion_list_add_option (t_completion *completion)
for (j = 0; weechat_options[i][j].option_name; j++)
{
completion_list_add (completion,
weechat_options[i][j].option_name);
weechat_options[i][j].option_name, 0);
}
}
}
@ -565,7 +655,7 @@ completion_list_add_option (t_completion *completion)
snprintf (option_name, sizeof (option_name), "%s.%s",
ptr_server->name,
weechat_options[CONFIG_SECTION_SERVER][i].option_name);
completion_list_add (completion, option_name);
completion_list_add (completion, option_name, 0);
}
}
}
@ -583,7 +673,7 @@ completion_list_add_plugin_option (t_completion *completion)
for (ptr_option = plugin_options; ptr_option;
ptr_option = ptr_option->next_option)
{
completion_list_add (completion, ptr_option->name);
completion_list_add (completion, ptr_option->name, 0);
}
#else
/* make C compiler happy */
@ -599,7 +689,7 @@ void
completion_list_add_part (t_completion *completion)
{
if (cfg_irc_default_msg_part && cfg_irc_default_msg_part[0])
completion_list_add (completion, cfg_irc_default_msg_part);
completion_list_add (completion, cfg_irc_default_msg_part, 0);
}
/*
@ -615,7 +705,7 @@ completion_list_add_plugin (t_completion *completion)
for (ptr_plugin = weechat_plugins; ptr_plugin;
ptr_plugin = ptr_plugin->next_plugin)
{
completion_list_add (completion, ptr_plugin->name);
completion_list_add (completion, ptr_plugin->name, 0);
}
#else
/* make C compiler happy */
@ -631,7 +721,7 @@ void
completion_list_add_quit (t_completion *completion)
{
if (cfg_irc_default_msg_quit && cfg_irc_default_msg_quit[0])
completion_list_add (completion, cfg_irc_default_msg_quit);
completion_list_add (completion, cfg_irc_default_msg_quit, 0);
}
/*
@ -643,7 +733,7 @@ completion_list_add_server (t_completion *completion)
{
if (completion->server)
completion_list_add (completion,
((t_irc_server *)(completion->server))->name);
((t_irc_server *)(completion->server))->name, 0);
}
/*
@ -658,7 +748,7 @@ completion_list_add_servers (t_completion *completion)
for (ptr_server = irc_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
completion_list_add (completion, ptr_server->name);
completion_list_add (completion, ptr_server->name, 0);
}
}
@ -681,7 +771,7 @@ completion_list_add_topic (t_completion *completion)
string = (char *)gui_color_decode ((unsigned char *)((t_irc_channel *)(completion->channel))->topic, 0);
completion_list_add (completion,
(string) ?
string : ((t_irc_channel *)(completion->channel))->topic);
string : ((t_irc_channel *)(completion->channel))->topic, 0);
if (string)
free (string);
}
@ -713,26 +803,26 @@ completion_list_add_option_value (t_completion *completion)
{
case OPTION_TYPE_BOOLEAN:
if (option_value && (*((int *)(option_value))))
completion_list_add (completion, "on");
completion_list_add (completion, "on", 0);
else
completion_list_add (completion, "off");
completion_list_add (completion, "off", 0);
break;
case OPTION_TYPE_INT:
snprintf (option_string, sizeof (option_string) - 1,
"%d", (option_value) ? *((int *)(option_value)) : option->default_int);
completion_list_add (completion, option_string);
completion_list_add (completion, option_string, 0);
break;
case OPTION_TYPE_INT_WITH_STRING:
completion_list_add (completion,
(option_value) ?
option->array_values[*((int *)(option_value))] :
option->array_values[option->default_int]);
option->array_values[option->default_int], 0);
break;
case OPTION_TYPE_COLOR:
completion_list_add (completion,
(option_value) ?
gui_color_get_name (*((int *)(option_value))) :
option->default_string);
option->default_string, 0);
break;
case OPTION_TYPE_STRING:
snprintf (option_string, sizeof (option_string) - 1,
@ -740,7 +830,7 @@ completion_list_add_option_value (t_completion *completion)
((option_value) && (*((char **)(option_value)))) ?
*((char **)(option_value)) :
option->default_string);
completion_list_add (completion, option_string);
completion_list_add (completion, option_string, 0);
break;
}
}
@ -768,7 +858,7 @@ completion_list_add_plugin_option_value (t_completion *completion)
ptr_option = plugin_config_search_internal (completion->args);
if (ptr_option)
completion_list_add (completion, ptr_option->value);
completion_list_add (completion, ptr_option->value, 0);
if (pos)
pos[0] = ' ';
@ -790,7 +880,7 @@ completion_list_add_weechat_cmd (t_completion *completion)
for (i = 0; weechat_commands[i].command_name; i++)
{
completion_list_add (completion, weechat_commands[i].command_name);
completion_list_add (completion, weechat_commands[i].command_name, 0);
}
}
@ -819,7 +909,8 @@ completion_build_list_template (t_completion *completion, char *template)
word[word_offset] = '\0';
weelist_add (&completion->completion_list,
&completion->last_completion,
word);
word,
WEELIST_POS_SORT);
}
word_offset = 0;
break;
@ -1105,7 +1196,9 @@ completion_command (t_completion *completion)
{
if ((!completion->word_found) || word_found_seen)
{
completion->word_found = ptr_weelist->data;
if (completion->word_found)
free (completion->word_found);
completion->word_found = strdup (ptr_weelist->data);
if (completion->direction < 0)
ptr_weelist2 = ptr_weelist->prev_weelist;
@ -1144,80 +1237,12 @@ completion_command (t_completion *completion)
}
if (completion->word_found)
{
free (completion->word_found);
completion->word_found = NULL;
completion_command (completion);
}
}
/*
* completion_is_only_alphanum: return 1 if there is only alpha/num chars
* in a string
*/
int
completion_is_only_alphanum (char *string)
{
while (string[0])
{
if (strchr (cfg_look_nick_completion_ignore, string[0]))
return 0;
string++;
}
return 1;
}
/*
* completion_strdup_alphanum: duplicate alpha/num chars in a string
*/
char *
completion_strdup_alphanum (char *string)
{
char *result, *pos;
result = (char *)malloc (strlen (string) + 1);
pos = result;
while (string[0])
{
if (!strchr (cfg_look_nick_completion_ignore, string[0]))
{
pos[0] = string[0];
pos++;
}
string++;
}
pos[0] = '\0';
return result;
}
/*
* completion_nickncmp: locale and case independent string comparison
* with max length for nicks (alpha or digits only)
*/
int
completion_nickncmp (char *base_word, char *nick, int max)
{
char *base_word2, *nick2;
int return_cmp;
if (!cfg_look_nick_completion_ignore
|| !cfg_look_nick_completion_ignore[0]
|| !base_word || !nick || !base_word[0] || !nick[0]
|| (!completion_is_only_alphanum (base_word)))
return ascii_strncasecmp (base_word, nick, max);
base_word2 = completion_strdup_alphanum (base_word);
nick2 = completion_strdup_alphanum (nick);
return_cmp = ascii_strncasecmp (base_word2, nick2, strlen (base_word2));
free (base_word2);
free (nick2);
return return_cmp;
}
/*
* completion_command_arg: complete a command argument
*/
@ -1243,7 +1268,9 @@ completion_command_arg (t_completion *completion, int nick_completion)
{
if ((!completion->word_found) || word_found_seen)
{
completion->word_found = ptr_weelist->data;
if (completion->word_found)
free (completion->word_found);
completion->word_found = strdup (ptr_weelist->data);
if (completion->direction < 0)
ptr_weelist2 = ptr_weelist->prev_weelist;
@ -1284,6 +1311,7 @@ completion_command_arg (t_completion *completion, int nick_completion)
}
if (completion->word_found)
{
free (completion->word_found);
completion->word_found = NULL;
completion_command_arg (completion, nick_completion);
}
@ -1297,7 +1325,8 @@ void
completion_nick (t_completion *completion)
{
int length, word_found_seen, other_completion;
t_irc_nick *ptr_nick, *ptr_nick2;
t_irc_nick *ptr_nick;
t_weelist *ptr_weelist, *ptr_weelist2;
if (!completion->channel)
return;
@ -1311,31 +1340,73 @@ completion_nick (t_completion *completion)
{
weelist_add (&completion->completion_list,
&completion->last_completion,
((t_irc_channel *)(completion->channel))->name);
((t_irc_channel *)(completion->channel))->name,
WEELIST_POS_SORT);
weelist_add (&completion->completion_list,
&completion->last_completion,
((t_irc_server *)(completion->server))->nick);
((t_irc_server *)(completion->server))->nick,
WEELIST_POS_SORT);
}
completion_command_arg (completion, 1);
return;
}
/* rebuild nick list for completion, with nicks speaking at beginning of list */
if ((((t_irc_channel *)(completion->channel))->nick_completion_reset)
|| (!(completion->completion_list)))
{
/* empty completion list */
if (completion->completion_list)
{
weelist_remove_all (&(completion->completion_list),
&(completion->last_completion));
completion->completion_list = NULL;
completion->last_completion = NULL;
}
/* add channel nicks */
for (ptr_nick = ((t_irc_channel *)(completion->channel))->nicks;
ptr_nick; ptr_nick = ptr_nick->next_nick)
{
weelist_add (&(completion->completion_list),
&(completion->last_completion),
ptr_nick->nick,
WEELIST_POS_SORT);
}
/* add nicks speaking recently on this channel */
if (cfg_look_nick_completion_smart)
{
for (ptr_weelist = ((t_irc_channel *)(completion->channel))->nicks_speaking;
ptr_weelist; ptr_weelist = ptr_weelist->next_weelist)
{
if (nick_search ((t_irc_channel *)(completion->channel), ptr_weelist->data))
weelist_add (&(completion->completion_list),
&(completion->last_completion),
ptr_weelist->data,
WEELIST_POS_BEGINNING);
}
}
((t_irc_channel *)(completion->channel))->nick_completion_reset = 0;
}
length = strlen (completion->base_word);
word_found_seen = 0;
other_completion = 0;
if (completion->direction < 0)
ptr_nick = ((t_irc_channel *)(completion->channel))->last_nick;
else
ptr_nick = ((t_irc_channel *)(completion->channel))->nicks;
while (ptr_nick)
if (completion->direction < 0)
ptr_weelist = completion->last_completion;
else
ptr_weelist = completion->completion_list;
while (ptr_weelist)
{
if (completion_nickncmp (completion->base_word, ptr_nick->nick, length) == 0)
if (completion_nickncmp (completion->base_word, ptr_weelist->data, length) == 0)
{
if ((!completion->word_found) || word_found_seen)
{
completion->word_found = ptr_nick->nick;
if (completion->word_found)
free (completion->word_found);
completion->word_found = strdup (ptr_weelist->data);
if (cfg_look_nick_complete_first)
{
completion->position = -1;
@ -1343,21 +1414,21 @@ completion_nick (t_completion *completion)
}
if (completion->direction < 0)
ptr_nick2 = ptr_nick->prev_nick;
ptr_weelist2 = ptr_weelist->prev_weelist;
else
ptr_nick2 = ptr_nick->next_nick;
ptr_weelist2 = ptr_weelist->next_weelist;
while (ptr_nick2)
while (ptr_weelist2)
{
if (completion_nickncmp (completion->base_word,
ptr_nick2->nick,
ptr_weelist2->data,
length) == 0)
other_completion++;
if (completion->direction < 0)
ptr_nick2 = ptr_nick2->prev_nick;
ptr_weelist2 = ptr_weelist2->prev_weelist;
else
ptr_nick2 = ptr_nick2->next_nick;
ptr_weelist2 = ptr_weelist2->next_weelist;
}
if (other_completion == 0)
@ -1372,16 +1443,17 @@ completion_nick (t_completion *completion)
other_completion++;
}
if (completion->word_found &&
(ascii_strcasecmp (ptr_nick->nick, completion->word_found) == 0))
(ascii_strcasecmp (ptr_weelist->data, completion->word_found) == 0))
word_found_seen = 1;
if (completion->direction < 0)
ptr_nick = ptr_nick->prev_nick;
ptr_weelist = ptr_weelist->prev_weelist;
else
ptr_nick = ptr_nick->next_nick;
ptr_weelist = ptr_weelist->next_weelist;
}
if (completion->word_found)
{
free (completion->word_found);
completion->word_found = NULL;
completion_nick (completion);
}
@ -1435,12 +1507,15 @@ completion_search (t_completion *completion, int direction,
/* if new completion => look for base word */
if (pos != completion->position)
{
if (completion->word_found)
free (completion->word_found);
completion->word_found = NULL;
completion_find_context (completion, buffer, size, pos);
}
/* completion */
old_word_found = completion->word_found;
old_word_found = (completion->word_found) ?
strdup (completion->word_found) : NULL;
switch (completion->context)
{
case COMPLETION_NULL:
@ -1487,6 +1562,8 @@ completion_search (t_completion *completion, int direction,
}
}
}
if (old_word_found)
free (old_word_found);
}
/*

View File

@ -97,6 +97,7 @@ int cfg_look_align_size;
int cfg_look_align_size_max;
char *cfg_look_nick_completor;
char *cfg_look_nick_completion_ignore;
int cfg_look_nick_completion_smart;
int cfg_look_nick_complete_first;
int cfg_look_infobar;
char *cfg_look_infobar_timestamp;
@ -222,6 +223,10 @@ t_config_option weechat_options_look[] =
N_("chars ignored for nick completion"),
OPTION_TYPE_STRING, 0, 0, 0,
"[]-^", NULL, NULL, &cfg_look_nick_completion_ignore, config_change_noop },
{ "look_nick_completion_smart", N_("smart completion for nicks"),
N_("smart completion for nicks (completes with last speakers first)"),
OPTION_TYPE_BOOLEAN, BOOL_FALSE, BOOL_TRUE, BOOL_TRUE,
NULL, NULL, &cfg_look_nick_completion_smart, NULL, config_change_noop },
{ "look_nick_complete_first", N_("complete only with first nick found"),
N_("complete only with first nick found"),
OPTION_TYPE_BOOLEAN, BOOL_FALSE, BOOL_TRUE, BOOL_FALSE,
@ -2024,7 +2029,8 @@ config_read ()
{
/* create new alias */
if (alias_new (line, pos))
weelist_add (&index_commands, &last_index_command, line);
weelist_add (&index_commands, &last_index_command,
line, WEELIST_POS_SORT);
}
else if (section == CONFIG_SECTION_IGNORE)
{

View File

@ -114,6 +114,7 @@ extern int cfg_look_align_size;
extern int cfg_look_align_size_max;
extern char *cfg_look_nick_completor;
extern char *cfg_look_nick_completion_ignore;
extern int cfg_look_nick_completion_smart;
extern int cfg_look_nick_complete_first;
extern int cfg_look_infobar;
extern char *cfg_look_infobar_timestamp;

View File

@ -33,6 +33,26 @@
#include "util.h"
/*
* weelist_get_size: get list size (number of elements)
*/
int
weelist_get_size (t_weelist *weelist)
{
t_weelist *ptr_weelist;
int count;
count = 0;
for (ptr_weelist = weelist; ptr_weelist; ptr_weelist = ptr_weelist->next_weelist)
{
count++;
}
return count;
}
/*
* weelist_search: search date in a list
*/
@ -74,14 +94,36 @@ weelist_find_pos (t_weelist *weelist, char *data)
*/
void
weelist_insert (t_weelist **weelist, t_weelist **last_weelist, t_weelist *element)
weelist_insert (t_weelist **weelist, t_weelist **last_weelist, t_weelist *element,
int position)
{
t_weelist *pos_weelist;
pos_weelist = weelist_find_pos (*weelist, element->data);
if (*weelist)
{
/* remove element if already in list */
pos_weelist = weelist_search (*weelist, element->data);
if (pos_weelist)
weelist_remove (weelist, last_weelist, pos_weelist);
}
if (*weelist)
{
/* search position for new element, according to pos asked */
pos_weelist = NULL;
switch (position)
{
case WEELIST_POS_SORT:
pos_weelist = weelist_find_pos (*weelist, element->data);
break;
case WEELIST_POS_BEGINNING:
pos_weelist = *weelist;
break;
case WEELIST_POS_END:
pos_weelist = NULL;
break;
}
if (pos_weelist)
{
/* insert data into the list (before position found) */
@ -116,7 +158,8 @@ weelist_insert (t_weelist **weelist, t_weelist **last_weelist, t_weelist *elemen
*/
t_weelist *
weelist_add (t_weelist **weelist, t_weelist **last_weelist, char *data)
weelist_add (t_weelist **weelist, t_weelist **last_weelist, char *data,
int position)
{
t_weelist *new_weelist;
@ -126,7 +169,7 @@ weelist_add (t_weelist **weelist, t_weelist **last_weelist, char *data)
if ((new_weelist = ((t_weelist *) malloc (sizeof (t_weelist)))))
{
new_weelist->data = strdup (data);
weelist_insert (weelist, last_weelist, new_weelist);
weelist_insert (weelist, last_weelist, new_weelist, position);
return new_weelist;
}
/* failed to allocate new element */
@ -134,7 +177,7 @@ weelist_add (t_weelist **weelist, t_weelist **last_weelist, char *data)
}
/*
* weelist_remove: free an element in a list
* weelist_remove: remove an element from a list
*/
void
@ -142,7 +185,7 @@ weelist_remove (t_weelist **weelist, t_weelist **last_weelist, t_weelist *elemen
{
t_weelist *new_weelist;
if (!element)
if (!element || !(*weelist))
return;
/* remove element from list */
@ -166,6 +209,19 @@ weelist_remove (t_weelist **weelist, t_weelist **last_weelist, t_weelist *elemen
*weelist = new_weelist;
}
/*
* weelist_remove_all: remove all elements from a list
*/
void
weelist_remove_all (t_weelist **weelist, t_weelist **last_weelist)
{
while (*weelist)
{
weelist_remove (weelist, last_weelist, *weelist);
}
}
/*
* weelist_print_log: print weelist in log (usually for crash dump)
*/

View File

@ -21,6 +21,10 @@
#ifndef __WEECHAT_LIST_H
#define __WEECHAT_LIST_H 1
#define WEELIST_POS_SORT 0
#define WEELIST_POS_BEGINNING 1
#define WEELIST_POS_END 2
typedef struct t_weelist t_weelist;
struct t_weelist
@ -30,9 +34,11 @@ struct t_weelist
t_weelist *next_weelist;
};
extern int weelist_get_size (t_weelist *);
extern t_weelist *weelist_search (t_weelist *, char *);
extern t_weelist *weelist_add (t_weelist **, t_weelist **, char *);
extern t_weelist *weelist_add (t_weelist **, t_weelist **, char *, int);
extern void weelist_remove (t_weelist **, t_weelist **, t_weelist *);
extern void weelist_remove_all (t_weelist **, t_weelist **);
extern void weelist_print_log (t_weelist *, char *);
#endif /* weelist.h */

View File

@ -70,9 +70,12 @@ channel_new (t_irc_server *server, int channel_type, char *channel_name)
new_channel->cycle = 0;
new_channel->close = 0;
new_channel->display_creation_date = 0;
new_channel->nick_completion_reset = 0;
new_channel->nicks = NULL;
new_channel->last_nick = NULL;
new_channel->buffer = NULL;
new_channel->nicks_speaking = NULL;
new_channel->last_nick_speaking = NULL;
/* add new channel to queue */
new_channel->prev_channel = server->last_channel;
@ -136,6 +139,9 @@ channel_free (t_irc_server *server, t_irc_channel *channel)
nick_free_all (channel);
if (channel->away_message)
free (channel->away_message);
if (channel->nicks_speaking)
weelist_remove_all (&(channel->nicks_speaking),
&(channel->last_nick_speaking));
free (channel);
server->channels = new_channels;
}
@ -404,6 +410,31 @@ channel_set_notify_level (t_irc_server *server, t_irc_channel *channel, int noti
config_option_list_set (&(server->notify_levels), channel->name, level_string);
}
/*
* channel_add_nick_speaking: add a nick speaking on a channel
*/
void
channel_add_nick_speaking (t_irc_channel *channel, char *nick)
{
int size, to_remove, i;
weelist_add (&(channel->nicks_speaking), &(channel->last_nick_speaking),
nick, WEELIST_POS_END);
size = weelist_get_size (channel->nicks_speaking);
if (size > CHANNEL_NICKS_SPEAKING_LIMIT)
{
to_remove = size - CHANNEL_NICKS_SPEAKING_LIMIT;
for (i = 0; i < to_remove; i++)
{
weelist_remove (&(channel->nicks_speaking),
&(channel->last_nick_speaking),
channel->nicks_speaking);
}
}
}
/*
* channel_print_log: print channel infos in log (usually for crash dump)
*/
@ -426,6 +457,14 @@ channel_print_log (t_irc_channel *channel)
weechat_log_printf (" nicks. . . . . . . . : 0x%X\n", channel->nicks);
weechat_log_printf (" last_nick. . . . . . : 0x%X\n", channel->last_nick);
weechat_log_printf (" buffer . . . . . . . : 0x%X\n", channel->buffer);
weechat_log_printf (" nicks_speaking . . . : 0x%X\n", channel->nicks_speaking);
weechat_log_printf (" last_nick_speaking . : 0x%X\n", channel->last_nick_speaking);
weechat_log_printf (" prev_channel . . . . : 0x%X\n", channel->prev_channel);
weechat_log_printf (" next_channel . . . . : 0x%X\n", channel->next_channel);
if (channel->nicks_speaking)
{
weechat_log_printf ("\n");
weelist_print_log (channel->nicks_speaking,
"channel nick speaking element");
}
}

View File

@ -232,6 +232,8 @@ nick_new (t_irc_server *server, t_irc_channel *channel, char *nick_name,
nick_insert_sorted (channel, new_nick);
channel->nicks_count++;
channel->nick_completion_reset = 1;
/* all is ok, return address of new nick */
return new_nick;
@ -296,6 +298,8 @@ nick_free (t_irc_channel *channel, t_irc_nick *nick)
free (nick->host);
free (nick);
channel->nicks = new_nicks;
channel->nick_completion_reset = 1;
}
/*

View File

@ -1392,6 +1392,7 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *nick, char *argume
gui_printf (ptr_channel->buffer, " %s%s\n",
GUI_COLOR(COLOR_WIN_CHAT), pos);
}
channel_add_nick_speaking (ptr_channel, nick);
}
return 0;
}
@ -1520,6 +1521,7 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *nick, char *argume
gui_printf_type (ptr_channel->buffer, MSG_TYPE_MSG,
"%s\n", pos);
}
channel_add_nick_speaking (ptr_channel, nick);
}
}
else

View File

@ -90,15 +90,16 @@ struct t_irc_nick
t_irc_nick *next_nick; /* link to next nick on the channel */
};
/* channel types */
#define CHANNEL_PREFIX "#&+!"
/* channel types */
#define CHANNEL_TYPE_UNKNOWN -1
#define CHANNEL_TYPE_CHANNEL 0
#define CHANNEL_TYPE_PRIVATE 1
#define CHANNEL_TYPE_DCC_CHAT 2
#define CHANNEL_NICKS_SPEAKING_LIMIT 32
typedef struct t_irc_channel t_irc_channel;
struct t_irc_channel
@ -116,8 +117,12 @@ struct t_irc_channel
int cycle; /* currently cycling (/part then /join) */
int close; /* close request (/buffer close) */
int display_creation_date; /* 1 if creation date should be displayed */
int nick_completion_reset; /* 1 if nick completion should be rebuilt */
/* there was some join/part on channel */
t_irc_nick *nicks; /* nicks on the channel */
t_irc_nick *last_nick; /* last nick on the channel */
t_weelist *nicks_speaking; /* nicks speaking (for smart completion) */
t_weelist *last_nick_speaking; /* last nick speaking */
t_gui_buffer *buffer; /* GUI buffer allocated for channel */
t_irc_channel *prev_channel; /* link to previous channel */
t_irc_channel *next_channel; /* link to next channel */
@ -415,6 +420,7 @@ extern void channel_set_away (t_irc_channel *, char *, int);
extern int channel_create_dcc (t_irc_dcc *);
extern int channel_get_notify_level (t_irc_server *, t_irc_channel *);
extern void channel_set_notify_level (t_irc_server *, t_irc_channel *, int);
extern void channel_add_nick_speaking (t_irc_channel *, char *);
extern void channel_print_log (t_irc_channel *);
/* nick functions (irc-nick.c) */

View File

@ -322,7 +322,8 @@ plugin_cmd_handler_add (t_weechat_plugin *plugin, char *command,
/* add command to WeeChat commands list */
if (!weelist_search (index_commands, command))
weelist_add (&index_commands, &last_index_command, command);
weelist_add (&index_commands, &last_index_command, command,
WEELIST_POS_SORT);
}
else
{

View File

@ -1,10 +1,15 @@
WeeChat - Wee Enhanced Environment for Chat
===========================================
ChangeLog - 2007-04-04
ChangeLog - 2007-04-14
Version 0.2.5 (under dev!):
* improved nick completion: added option look_nick_completion_smart,
enabled by default (task #5896)
* fixed nick completion in command arguments (bug #19590)
* fixed possible crash with nick completion when a nick leaves channel
(bug #19589)
* added color for input text not found in buffer history
* fixed USER message when connecting to IRC server (patch #5835)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -251,7 +251,8 @@ command_index_build ()
while (weechat_commands[i].command_name)
{
(void) weelist_add (&index_commands, &last_index_command,
weechat_commands[i].command_name);
weechat_commands[i].command_name,
WEELIST_POS_SORT);
i++;
}
i = 0;
@ -259,7 +260,8 @@ command_index_build ()
{
if (irc_commands[i].cmd_function_args || irc_commands[i].cmd_function_1arg)
(void) weelist_add (&index_commands, &last_index_command,
irc_commands[i].command_name);
irc_commands[i].command_name,
WEELIST_POS_SORT);
i++;
}
}
@ -945,7 +947,8 @@ weechat_cmd_alias (t_irc_server *server, t_irc_channel *channel,
}
if (!alias_new (arguments, pos))
return -1;
if (weelist_add (&index_commands, &last_index_command, arguments))
if (weelist_add (&index_commands, &last_index_command, arguments,
WEELIST_POS_SORT))
{
irc_display_prefix (NULL, NULL, PREFIX_INFO);
gui_printf (NULL, _("Alias \"%s\" => \"%s\" created\n"),

View File

@ -95,12 +95,14 @@ completion_free (t_completion *completion)
free (completion->args);
completion->args = NULL;
while (completion->completion_list)
weelist_remove (&completion->completion_list,
&completion->last_completion,
completion->completion_list);
weelist_remove_all (&completion->completion_list,
&completion->last_completion);
completion->completion_list = NULL;
completion->last_completion = NULL;
if (completion->word_found)
free (completion->word_found);
completion->word_found = NULL;
}
/*
@ -203,20 +205,95 @@ completion_get_command_infos (t_completion *completion,
return;
}
/*
* completion_is_only_alphanum: return 1 if there is only alpha/num chars
* in a string
*/
int
completion_is_only_alphanum (char *string)
{
while (string[0])
{
if (strchr (cfg_look_nick_completion_ignore, string[0]))
return 0;
string++;
}
return 1;
}
/*
* completion_strdup_alphanum: duplicate alpha/num chars in a string
*/
char *
completion_strdup_alphanum (char *string)
{
char *result, *pos;
result = (char *)malloc (strlen (string) + 1);
pos = result;
while (string[0])
{
if (!strchr (cfg_look_nick_completion_ignore, string[0]))
{
pos[0] = string[0];
pos++;
}
string++;
}
pos[0] = '\0';
return result;
}
/*
* completion_nickncmp: locale and case independent string comparison
* with max length for nicks (alpha or digits only)
*/
int
completion_nickncmp (char *base_word, char *nick, int max)
{
char *base_word2, *nick2;
int return_cmp;
if (!cfg_look_nick_completion_ignore
|| !cfg_look_nick_completion_ignore[0]
|| !base_word || !nick || !base_word[0] || !nick[0]
|| (!completion_is_only_alphanum (base_word)))
return ascii_strncasecmp (base_word, nick, max);
base_word2 = completion_strdup_alphanum (base_word);
nick2 = completion_strdup_alphanum (nick);
return_cmp = ascii_strncasecmp (base_word2, nick2, strlen (base_word2));
free (base_word2);
free (nick2);
return return_cmp;
}
/*
* completion_list_add: add a word to completion word list
* if nick_completion != 0, then add as a nick
* if nick_completion < 0, then add at beginning of list
*/
void
completion_list_add (t_completion *completion, char *word)
completion_list_add (t_completion *completion, char *word, int nick_completion)
{
if (!completion->base_word || !completion->base_word[0]
|| (ascii_strncasecmp (completion->base_word, word,
strlen (completion->base_word)) == 0))
|| ((nick_completion != 0) && (completion_nickncmp (completion->base_word, word,
strlen (completion->base_word)) == 0))
|| ((nick_completion == 0) && (ascii_strncasecmp (completion->base_word, word,
strlen (completion->base_word)) == 0)))
{
weelist_add (&completion->completion_list,
&completion->last_completion,
word);
word,
(nick_completion < 0) ?
WEELIST_POS_BEGINNING : WEELIST_POS_SORT);
}
}
@ -231,7 +308,7 @@ completion_list_add_alias (t_completion *completion)
for (ptr_alias = weechat_alias; ptr_alias; ptr_alias = ptr_alias->next_alias)
{
completion_list_add (completion, ptr_alias->alias_name);
completion_list_add (completion, ptr_alias->alias_name, 0);
}
}
@ -246,7 +323,7 @@ completion_list_add_alias_cmd (t_completion *completion)
for (ptr_list = index_commands; ptr_list; ptr_list = ptr_list->next_weelist)
{
completion_list_add (completion, ptr_list->data);
completion_list_add (completion, ptr_list->data, 0);
}
}
@ -259,7 +336,7 @@ completion_list_add_channel (t_completion *completion)
{
if (completion->channel)
completion_list_add (completion,
((t_irc_channel *)(completion->channel))->name);
((t_irc_channel *)(completion->channel))->name, 0);
}
/*
@ -276,7 +353,7 @@ completion_list_add_server_channels (t_completion *completion)
for (ptr_channel = ((t_irc_server *)(completion->server))->channels;
ptr_channel; ptr_channel = ptr_channel->next_channel)
{
completion_list_add (completion, ptr_channel->name);
completion_list_add (completion, ptr_channel->name, 0);
}
}
}
@ -361,7 +438,7 @@ completion_list_add_filename (t_completion *completion)
entry->d_name,
S_ISDIR(statbuf.st_mode) ? DIR_SEPARATOR : "");
completion_list_add (completion, buffer);
completion_list_add (completion, buffer, 0);
}
}
}
@ -392,7 +469,7 @@ completion_list_add_plugin_cmd (t_completion *completion)
ptr_handler; ptr_handler = ptr_handler->next_handler)
{
if (ptr_handler->type == PLUGIN_HANDLER_COMMAND)
completion_list_add (completion, ptr_handler->command);
completion_list_add (completion, ptr_handler->command, 0);
}
}
#else
@ -413,7 +490,7 @@ completion_list_add_irc_cmd_sent (t_completion *completion)
for (i = 0; irc_commands[i].command_name; i++)
{
if (irc_commands[i].cmd_function_args || irc_commands[i].cmd_function_1arg)
completion_list_add (completion, irc_commands[i].command_name);
completion_list_add (completion, irc_commands[i].command_name, 0);
}
}
@ -429,7 +506,7 @@ completion_list_add_irc_cmd_recv (t_completion *completion)
for (i = 0; irc_commands[i].command_name; i++)
{
if (irc_commands[i].recv_function)
completion_list_add(completion, irc_commands[i].command_name);
completion_list_add(completion, irc_commands[i].command_name, 0);
}
}
@ -444,7 +521,7 @@ completion_list_add_key_cmd (t_completion *completion)
for (i = 0; gui_key_functions[i].function_name; i++)
{
completion_list_add (completion, gui_key_functions[i].function_name);
completion_list_add (completion, gui_key_functions[i].function_name, 0);
}
}
@ -457,7 +534,8 @@ completion_list_add_self_nick (t_completion *completion)
{
if (completion->server)
{
completion_list_add (completion, ((t_irc_server *)(completion->server))->nick);
completion_list_add (completion,
((t_irc_server *)(completion->server))->nick, 0);
}
}
@ -469,22 +547,34 @@ void
completion_list_add_channel_nicks (t_completion *completion)
{
t_irc_nick *ptr_nick;
t_weelist *ptr_weelist;
if (completion->channel)
{
if (((t_irc_channel *)(completion->channel))->type == CHANNEL_TYPE_CHANNEL)
{
/* add channel nicks */
for (ptr_nick = ((t_irc_channel *)(completion->channel))->nicks;
ptr_nick; ptr_nick = ptr_nick->next_nick)
{
completion_list_add (completion, ptr_nick->nick);
completion_list_add (completion, ptr_nick->nick, 1);
}
/* add nicks speaking recently on this channel */
if (cfg_look_nick_completion_smart)
{
for (ptr_weelist = ((t_irc_channel *)(completion->channel))->nicks_speaking;
ptr_weelist; ptr_weelist = ptr_weelist->next_weelist)
{
if (nick_search ((t_irc_channel *)(completion->channel), ptr_weelist->data))
completion_list_add (completion, ptr_weelist->data, -1);
}
}
}
if ((((t_irc_channel *)(completion->channel))->type == CHANNEL_TYPE_PRIVATE)
|| (((t_irc_channel *)(completion->channel))->type == CHANNEL_TYPE_DCC_CHAT))
{
completion_list_add (completion,
((t_irc_channel *)(completion->channel))->name);
((t_irc_channel *)(completion->channel))->name, 1);
}
completion->arg_is_nick = 1;
}
@ -508,7 +598,7 @@ completion_list_add_channel_nicks_hosts (t_completion *completion)
for (ptr_nick = ((t_irc_channel *)(completion->channel))->nicks;
ptr_nick; ptr_nick = ptr_nick->next_nick)
{
completion_list_add (completion, ptr_nick->nick);
completion_list_add (completion, ptr_nick->nick, 1);
if (ptr_nick->host)
{
length = strlen (ptr_nick->nick) + 1 +
@ -518,7 +608,7 @@ completion_list_add_channel_nicks_hosts (t_completion *completion)
{
snprintf (buf, length, "%s!%s",
ptr_nick->nick, ptr_nick->host);
completion_list_add (completion, buf);
completion_list_add (completion, buf, 1);
free (buf);
}
}
@ -528,7 +618,7 @@ completion_list_add_channel_nicks_hosts (t_completion *completion)
|| (((t_irc_channel *)(completion->channel))->type == CHANNEL_TYPE_PRIVATE))
{
completion_list_add (completion,
((t_irc_channel *)(completion->channel))->name);
((t_irc_channel *)(completion->channel))->name, 1);
}
completion->arg_is_nick = 1;
}
@ -553,7 +643,7 @@ completion_list_add_option (t_completion *completion)
for (j = 0; weechat_options[i][j].option_name; j++)
{
completion_list_add (completion,
weechat_options[i][j].option_name);
weechat_options[i][j].option_name, 0);
}
}
}
@ -565,7 +655,7 @@ completion_list_add_option (t_completion *completion)
snprintf (option_name, sizeof (option_name), "%s.%s",
ptr_server->name,
weechat_options[CONFIG_SECTION_SERVER][i].option_name);
completion_list_add (completion, option_name);
completion_list_add (completion, option_name, 0);
}
}
}
@ -583,7 +673,7 @@ completion_list_add_plugin_option (t_completion *completion)
for (ptr_option = plugin_options; ptr_option;
ptr_option = ptr_option->next_option)
{
completion_list_add (completion, ptr_option->name);
completion_list_add (completion, ptr_option->name, 0);
}
#else
/* make C compiler happy */
@ -599,7 +689,7 @@ void
completion_list_add_part (t_completion *completion)
{
if (cfg_irc_default_msg_part && cfg_irc_default_msg_part[0])
completion_list_add (completion, cfg_irc_default_msg_part);
completion_list_add (completion, cfg_irc_default_msg_part, 0);
}
/*
@ -615,7 +705,7 @@ completion_list_add_plugin (t_completion *completion)
for (ptr_plugin = weechat_plugins; ptr_plugin;
ptr_plugin = ptr_plugin->next_plugin)
{
completion_list_add (completion, ptr_plugin->name);
completion_list_add (completion, ptr_plugin->name, 0);
}
#else
/* make C compiler happy */
@ -631,7 +721,7 @@ void
completion_list_add_quit (t_completion *completion)
{
if (cfg_irc_default_msg_quit && cfg_irc_default_msg_quit[0])
completion_list_add (completion, cfg_irc_default_msg_quit);
completion_list_add (completion, cfg_irc_default_msg_quit, 0);
}
/*
@ -643,7 +733,7 @@ completion_list_add_server (t_completion *completion)
{
if (completion->server)
completion_list_add (completion,
((t_irc_server *)(completion->server))->name);
((t_irc_server *)(completion->server))->name, 0);
}
/*
@ -658,7 +748,7 @@ completion_list_add_servers (t_completion *completion)
for (ptr_server = irc_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
completion_list_add (completion, ptr_server->name);
completion_list_add (completion, ptr_server->name, 0);
}
}
@ -681,7 +771,7 @@ completion_list_add_topic (t_completion *completion)
string = (char *)gui_color_decode ((unsigned char *)((t_irc_channel *)(completion->channel))->topic, 0);
completion_list_add (completion,
(string) ?
string : ((t_irc_channel *)(completion->channel))->topic);
string : ((t_irc_channel *)(completion->channel))->topic, 0);
if (string)
free (string);
}
@ -713,26 +803,26 @@ completion_list_add_option_value (t_completion *completion)
{
case OPTION_TYPE_BOOLEAN:
if (option_value && (*((int *)(option_value))))
completion_list_add (completion, "on");
completion_list_add (completion, "on", 0);
else
completion_list_add (completion, "off");
completion_list_add (completion, "off", 0);
break;
case OPTION_TYPE_INT:
snprintf (option_string, sizeof (option_string) - 1,
"%d", (option_value) ? *((int *)(option_value)) : option->default_int);
completion_list_add (completion, option_string);
completion_list_add (completion, option_string, 0);
break;
case OPTION_TYPE_INT_WITH_STRING:
completion_list_add (completion,
(option_value) ?
option->array_values[*((int *)(option_value))] :
option->array_values[option->default_int]);
option->array_values[option->default_int], 0);
break;
case OPTION_TYPE_COLOR:
completion_list_add (completion,
(option_value) ?
gui_color_get_name (*((int *)(option_value))) :
option->default_string);
option->default_string, 0);
break;
case OPTION_TYPE_STRING:
snprintf (option_string, sizeof (option_string) - 1,
@ -740,7 +830,7 @@ completion_list_add_option_value (t_completion *completion)
((option_value) && (*((char **)(option_value)))) ?
*((char **)(option_value)) :
option->default_string);
completion_list_add (completion, option_string);
completion_list_add (completion, option_string, 0);
break;
}
}
@ -768,7 +858,7 @@ completion_list_add_plugin_option_value (t_completion *completion)
ptr_option = plugin_config_search_internal (completion->args);
if (ptr_option)
completion_list_add (completion, ptr_option->value);
completion_list_add (completion, ptr_option->value, 0);
if (pos)
pos[0] = ' ';
@ -790,7 +880,7 @@ completion_list_add_weechat_cmd (t_completion *completion)
for (i = 0; weechat_commands[i].command_name; i++)
{
completion_list_add (completion, weechat_commands[i].command_name);
completion_list_add (completion, weechat_commands[i].command_name, 0);
}
}
@ -819,7 +909,8 @@ completion_build_list_template (t_completion *completion, char *template)
word[word_offset] = '\0';
weelist_add (&completion->completion_list,
&completion->last_completion,
word);
word,
WEELIST_POS_SORT);
}
word_offset = 0;
break;
@ -1105,7 +1196,9 @@ completion_command (t_completion *completion)
{
if ((!completion->word_found) || word_found_seen)
{
completion->word_found = ptr_weelist->data;
if (completion->word_found)
free (completion->word_found);
completion->word_found = strdup (ptr_weelist->data);
if (completion->direction < 0)
ptr_weelist2 = ptr_weelist->prev_weelist;
@ -1144,80 +1237,12 @@ completion_command (t_completion *completion)
}
if (completion->word_found)
{
free (completion->word_found);
completion->word_found = NULL;
completion_command (completion);
}
}
/*
* completion_is_only_alphanum: return 1 if there is only alpha/num chars
* in a string
*/
int
completion_is_only_alphanum (char *string)
{
while (string[0])
{
if (strchr (cfg_look_nick_completion_ignore, string[0]))
return 0;
string++;
}
return 1;
}
/*
* completion_strdup_alphanum: duplicate alpha/num chars in a string
*/
char *
completion_strdup_alphanum (char *string)
{
char *result, *pos;
result = (char *)malloc (strlen (string) + 1);
pos = result;
while (string[0])
{
if (!strchr (cfg_look_nick_completion_ignore, string[0]))
{
pos[0] = string[0];
pos++;
}
string++;
}
pos[0] = '\0';
return result;
}
/*
* completion_nickncmp: locale and case independent string comparison
* with max length for nicks (alpha or digits only)
*/
int
completion_nickncmp (char *base_word, char *nick, int max)
{
char *base_word2, *nick2;
int return_cmp;
if (!cfg_look_nick_completion_ignore
|| !cfg_look_nick_completion_ignore[0]
|| !base_word || !nick || !base_word[0] || !nick[0]
|| (!completion_is_only_alphanum (base_word)))
return ascii_strncasecmp (base_word, nick, max);
base_word2 = completion_strdup_alphanum (base_word);
nick2 = completion_strdup_alphanum (nick);
return_cmp = ascii_strncasecmp (base_word2, nick2, strlen (base_word2));
free (base_word2);
free (nick2);
return return_cmp;
}
/*
* completion_command_arg: complete a command argument
*/
@ -1243,7 +1268,9 @@ completion_command_arg (t_completion *completion, int nick_completion)
{
if ((!completion->word_found) || word_found_seen)
{
completion->word_found = ptr_weelist->data;
if (completion->word_found)
free (completion->word_found);
completion->word_found = strdup (ptr_weelist->data);
if (completion->direction < 0)
ptr_weelist2 = ptr_weelist->prev_weelist;
@ -1284,6 +1311,7 @@ completion_command_arg (t_completion *completion, int nick_completion)
}
if (completion->word_found)
{
free (completion->word_found);
completion->word_found = NULL;
completion_command_arg (completion, nick_completion);
}
@ -1297,7 +1325,8 @@ void
completion_nick (t_completion *completion)
{
int length, word_found_seen, other_completion;
t_irc_nick *ptr_nick, *ptr_nick2;
t_irc_nick *ptr_nick;
t_weelist *ptr_weelist, *ptr_weelist2;
if (!completion->channel)
return;
@ -1311,31 +1340,73 @@ completion_nick (t_completion *completion)
{
weelist_add (&completion->completion_list,
&completion->last_completion,
((t_irc_channel *)(completion->channel))->name);
((t_irc_channel *)(completion->channel))->name,
WEELIST_POS_SORT);
weelist_add (&completion->completion_list,
&completion->last_completion,
((t_irc_server *)(completion->server))->nick);
((t_irc_server *)(completion->server))->nick,
WEELIST_POS_SORT);
}
completion_command_arg (completion, 1);
return;
}
/* rebuild nick list for completion, with nicks speaking at beginning of list */
if ((((t_irc_channel *)(completion->channel))->nick_completion_reset)
|| (!(completion->completion_list)))
{
/* empty completion list */
if (completion->completion_list)
{
weelist_remove_all (&(completion->completion_list),
&(completion->last_completion));
completion->completion_list = NULL;
completion->last_completion = NULL;
}
/* add channel nicks */
for (ptr_nick = ((t_irc_channel *)(completion->channel))->nicks;
ptr_nick; ptr_nick = ptr_nick->next_nick)
{
weelist_add (&(completion->completion_list),
&(completion->last_completion),
ptr_nick->nick,
WEELIST_POS_SORT);
}
/* add nicks speaking recently on this channel */
if (cfg_look_nick_completion_smart)
{
for (ptr_weelist = ((t_irc_channel *)(completion->channel))->nicks_speaking;
ptr_weelist; ptr_weelist = ptr_weelist->next_weelist)
{
if (nick_search ((t_irc_channel *)(completion->channel), ptr_weelist->data))
weelist_add (&(completion->completion_list),
&(completion->last_completion),
ptr_weelist->data,
WEELIST_POS_BEGINNING);
}
}
((t_irc_channel *)(completion->channel))->nick_completion_reset = 0;
}
length = strlen (completion->base_word);
word_found_seen = 0;
other_completion = 0;
if (completion->direction < 0)
ptr_nick = ((t_irc_channel *)(completion->channel))->last_nick;
else
ptr_nick = ((t_irc_channel *)(completion->channel))->nicks;
while (ptr_nick)
if (completion->direction < 0)
ptr_weelist = completion->last_completion;
else
ptr_weelist = completion->completion_list;
while (ptr_weelist)
{
if (completion_nickncmp (completion->base_word, ptr_nick->nick, length) == 0)
if (completion_nickncmp (completion->base_word, ptr_weelist->data, length) == 0)
{
if ((!completion->word_found) || word_found_seen)
{
completion->word_found = ptr_nick->nick;
if (completion->word_found)
free (completion->word_found);
completion->word_found = strdup (ptr_weelist->data);
if (cfg_look_nick_complete_first)
{
completion->position = -1;
@ -1343,21 +1414,21 @@ completion_nick (t_completion *completion)
}
if (completion->direction < 0)
ptr_nick2 = ptr_nick->prev_nick;
ptr_weelist2 = ptr_weelist->prev_weelist;
else
ptr_nick2 = ptr_nick->next_nick;
ptr_weelist2 = ptr_weelist->next_weelist;
while (ptr_nick2)
while (ptr_weelist2)
{
if (completion_nickncmp (completion->base_word,
ptr_nick2->nick,
ptr_weelist2->data,
length) == 0)
other_completion++;
if (completion->direction < 0)
ptr_nick2 = ptr_nick2->prev_nick;
ptr_weelist2 = ptr_weelist2->prev_weelist;
else
ptr_nick2 = ptr_nick2->next_nick;
ptr_weelist2 = ptr_weelist2->next_weelist;
}
if (other_completion == 0)
@ -1372,16 +1443,17 @@ completion_nick (t_completion *completion)
other_completion++;
}
if (completion->word_found &&
(ascii_strcasecmp (ptr_nick->nick, completion->word_found) == 0))
(ascii_strcasecmp (ptr_weelist->data, completion->word_found) == 0))
word_found_seen = 1;
if (completion->direction < 0)
ptr_nick = ptr_nick->prev_nick;
ptr_weelist = ptr_weelist->prev_weelist;
else
ptr_nick = ptr_nick->next_nick;
ptr_weelist = ptr_weelist->next_weelist;
}
if (completion->word_found)
{
free (completion->word_found);
completion->word_found = NULL;
completion_nick (completion);
}
@ -1435,12 +1507,15 @@ completion_search (t_completion *completion, int direction,
/* if new completion => look for base word */
if (pos != completion->position)
{
if (completion->word_found)
free (completion->word_found);
completion->word_found = NULL;
completion_find_context (completion, buffer, size, pos);
}
/* completion */
old_word_found = completion->word_found;
old_word_found = (completion->word_found) ?
strdup (completion->word_found) : NULL;
switch (completion->context)
{
case COMPLETION_NULL:
@ -1487,6 +1562,8 @@ completion_search (t_completion *completion, int direction,
}
}
}
if (old_word_found)
free (old_word_found);
}
/*

View File

@ -97,6 +97,7 @@ int cfg_look_align_size;
int cfg_look_align_size_max;
char *cfg_look_nick_completor;
char *cfg_look_nick_completion_ignore;
int cfg_look_nick_completion_smart;
int cfg_look_nick_complete_first;
int cfg_look_infobar;
char *cfg_look_infobar_timestamp;
@ -222,6 +223,10 @@ t_config_option weechat_options_look[] =
N_("chars ignored for nick completion"),
OPTION_TYPE_STRING, 0, 0, 0,
"[]-^", NULL, NULL, &cfg_look_nick_completion_ignore, config_change_noop },
{ "look_nick_completion_smart", N_("smart completion for nicks"),
N_("smart completion for nicks (completes with last speakers first)"),
OPTION_TYPE_BOOLEAN, BOOL_FALSE, BOOL_TRUE, BOOL_TRUE,
NULL, NULL, &cfg_look_nick_completion_smart, NULL, config_change_noop },
{ "look_nick_complete_first", N_("complete only with first nick found"),
N_("complete only with first nick found"),
OPTION_TYPE_BOOLEAN, BOOL_FALSE, BOOL_TRUE, BOOL_FALSE,
@ -2024,7 +2029,8 @@ config_read ()
{
/* create new alias */
if (alias_new (line, pos))
weelist_add (&index_commands, &last_index_command, line);
weelist_add (&index_commands, &last_index_command,
line, WEELIST_POS_SORT);
}
else if (section == CONFIG_SECTION_IGNORE)
{

View File

@ -114,6 +114,7 @@ extern int cfg_look_align_size;
extern int cfg_look_align_size_max;
extern char *cfg_look_nick_completor;
extern char *cfg_look_nick_completion_ignore;
extern int cfg_look_nick_completion_smart;
extern int cfg_look_nick_complete_first;
extern int cfg_look_infobar;
extern char *cfg_look_infobar_timestamp;

View File

@ -33,6 +33,26 @@
#include "util.h"
/*
* weelist_get_size: get list size (number of elements)
*/
int
weelist_get_size (t_weelist *weelist)
{
t_weelist *ptr_weelist;
int count;
count = 0;
for (ptr_weelist = weelist; ptr_weelist; ptr_weelist = ptr_weelist->next_weelist)
{
count++;
}
return count;
}
/*
* weelist_search: search date in a list
*/
@ -74,14 +94,36 @@ weelist_find_pos (t_weelist *weelist, char *data)
*/
void
weelist_insert (t_weelist **weelist, t_weelist **last_weelist, t_weelist *element)
weelist_insert (t_weelist **weelist, t_weelist **last_weelist, t_weelist *element,
int position)
{
t_weelist *pos_weelist;
pos_weelist = weelist_find_pos (*weelist, element->data);
if (*weelist)
{
/* remove element if already in list */
pos_weelist = weelist_search (*weelist, element->data);
if (pos_weelist)
weelist_remove (weelist, last_weelist, pos_weelist);
}
if (*weelist)
{
/* search position for new element, according to pos asked */
pos_weelist = NULL;
switch (position)
{
case WEELIST_POS_SORT:
pos_weelist = weelist_find_pos (*weelist, element->data);
break;
case WEELIST_POS_BEGINNING:
pos_weelist = *weelist;
break;
case WEELIST_POS_END:
pos_weelist = NULL;
break;
}
if (pos_weelist)
{
/* insert data into the list (before position found) */
@ -116,7 +158,8 @@ weelist_insert (t_weelist **weelist, t_weelist **last_weelist, t_weelist *elemen
*/
t_weelist *
weelist_add (t_weelist **weelist, t_weelist **last_weelist, char *data)
weelist_add (t_weelist **weelist, t_weelist **last_weelist, char *data,
int position)
{
t_weelist *new_weelist;
@ -126,7 +169,7 @@ weelist_add (t_weelist **weelist, t_weelist **last_weelist, char *data)
if ((new_weelist = ((t_weelist *) malloc (sizeof (t_weelist)))))
{
new_weelist->data = strdup (data);
weelist_insert (weelist, last_weelist, new_weelist);
weelist_insert (weelist, last_weelist, new_weelist, position);
return new_weelist;
}
/* failed to allocate new element */
@ -134,7 +177,7 @@ weelist_add (t_weelist **weelist, t_weelist **last_weelist, char *data)
}
/*
* weelist_remove: free an element in a list
* weelist_remove: remove an element from a list
*/
void
@ -142,7 +185,7 @@ weelist_remove (t_weelist **weelist, t_weelist **last_weelist, t_weelist *elemen
{
t_weelist *new_weelist;
if (!element)
if (!element || !(*weelist))
return;
/* remove element from list */
@ -166,6 +209,19 @@ weelist_remove (t_weelist **weelist, t_weelist **last_weelist, t_weelist *elemen
*weelist = new_weelist;
}
/*
* weelist_remove_all: remove all elements from a list
*/
void
weelist_remove_all (t_weelist **weelist, t_weelist **last_weelist)
{
while (*weelist)
{
weelist_remove (weelist, last_weelist, *weelist);
}
}
/*
* weelist_print_log: print weelist in log (usually for crash dump)
*/

View File

@ -21,6 +21,10 @@
#ifndef __WEECHAT_LIST_H
#define __WEECHAT_LIST_H 1
#define WEELIST_POS_SORT 0
#define WEELIST_POS_BEGINNING 1
#define WEELIST_POS_END 2
typedef struct t_weelist t_weelist;
struct t_weelist
@ -30,9 +34,11 @@ struct t_weelist
t_weelist *next_weelist;
};
extern int weelist_get_size (t_weelist *);
extern t_weelist *weelist_search (t_weelist *, char *);
extern t_weelist *weelist_add (t_weelist **, t_weelist **, char *);
extern t_weelist *weelist_add (t_weelist **, t_weelist **, char *, int);
extern void weelist_remove (t_weelist **, t_weelist **, t_weelist *);
extern void weelist_remove_all (t_weelist **, t_weelist **);
extern void weelist_print_log (t_weelist *, char *);
#endif /* weelist.h */

View File

@ -70,9 +70,12 @@ channel_new (t_irc_server *server, int channel_type, char *channel_name)
new_channel->cycle = 0;
new_channel->close = 0;
new_channel->display_creation_date = 0;
new_channel->nick_completion_reset = 0;
new_channel->nicks = NULL;
new_channel->last_nick = NULL;
new_channel->buffer = NULL;
new_channel->nicks_speaking = NULL;
new_channel->last_nick_speaking = NULL;
/* add new channel to queue */
new_channel->prev_channel = server->last_channel;
@ -136,6 +139,9 @@ channel_free (t_irc_server *server, t_irc_channel *channel)
nick_free_all (channel);
if (channel->away_message)
free (channel->away_message);
if (channel->nicks_speaking)
weelist_remove_all (&(channel->nicks_speaking),
&(channel->last_nick_speaking));
free (channel);
server->channels = new_channels;
}
@ -404,6 +410,31 @@ channel_set_notify_level (t_irc_server *server, t_irc_channel *channel, int noti
config_option_list_set (&(server->notify_levels), channel->name, level_string);
}
/*
* channel_add_nick_speaking: add a nick speaking on a channel
*/
void
channel_add_nick_speaking (t_irc_channel *channel, char *nick)
{
int size, to_remove, i;
weelist_add (&(channel->nicks_speaking), &(channel->last_nick_speaking),
nick, WEELIST_POS_END);
size = weelist_get_size (channel->nicks_speaking);
if (size > CHANNEL_NICKS_SPEAKING_LIMIT)
{
to_remove = size - CHANNEL_NICKS_SPEAKING_LIMIT;
for (i = 0; i < to_remove; i++)
{
weelist_remove (&(channel->nicks_speaking),
&(channel->last_nick_speaking),
channel->nicks_speaking);
}
}
}
/*
* channel_print_log: print channel infos in log (usually for crash dump)
*/
@ -426,6 +457,14 @@ channel_print_log (t_irc_channel *channel)
weechat_log_printf (" nicks. . . . . . . . : 0x%X\n", channel->nicks);
weechat_log_printf (" last_nick. . . . . . : 0x%X\n", channel->last_nick);
weechat_log_printf (" buffer . . . . . . . : 0x%X\n", channel->buffer);
weechat_log_printf (" nicks_speaking . . . : 0x%X\n", channel->nicks_speaking);
weechat_log_printf (" last_nick_speaking . : 0x%X\n", channel->last_nick_speaking);
weechat_log_printf (" prev_channel . . . . : 0x%X\n", channel->prev_channel);
weechat_log_printf (" next_channel . . . . : 0x%X\n", channel->next_channel);
if (channel->nicks_speaking)
{
weechat_log_printf ("\n");
weelist_print_log (channel->nicks_speaking,
"channel nick speaking element");
}
}

View File

@ -232,6 +232,8 @@ nick_new (t_irc_server *server, t_irc_channel *channel, char *nick_name,
nick_insert_sorted (channel, new_nick);
channel->nicks_count++;
channel->nick_completion_reset = 1;
/* all is ok, return address of new nick */
return new_nick;
@ -296,6 +298,8 @@ nick_free (t_irc_channel *channel, t_irc_nick *nick)
free (nick->host);
free (nick);
channel->nicks = new_nicks;
channel->nick_completion_reset = 1;
}
/*

View File

@ -1392,6 +1392,7 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *nick, char *argume
gui_printf (ptr_channel->buffer, " %s%s\n",
GUI_COLOR(COLOR_WIN_CHAT), pos);
}
channel_add_nick_speaking (ptr_channel, nick);
}
return 0;
}
@ -1520,6 +1521,7 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *nick, char *argume
gui_printf_type (ptr_channel->buffer, MSG_TYPE_MSG,
"%s\n", pos);
}
channel_add_nick_speaking (ptr_channel, nick);
}
}
else

View File

@ -90,15 +90,16 @@ struct t_irc_nick
t_irc_nick *next_nick; /* link to next nick on the channel */
};
/* channel types */
#define CHANNEL_PREFIX "#&+!"
/* channel types */
#define CHANNEL_TYPE_UNKNOWN -1
#define CHANNEL_TYPE_CHANNEL 0
#define CHANNEL_TYPE_PRIVATE 1
#define CHANNEL_TYPE_DCC_CHAT 2
#define CHANNEL_NICKS_SPEAKING_LIMIT 32
typedef struct t_irc_channel t_irc_channel;
struct t_irc_channel
@ -116,8 +117,12 @@ struct t_irc_channel
int cycle; /* currently cycling (/part then /join) */
int close; /* close request (/buffer close) */
int display_creation_date; /* 1 if creation date should be displayed */
int nick_completion_reset; /* 1 if nick completion should be rebuilt */
/* there was some join/part on channel */
t_irc_nick *nicks; /* nicks on the channel */
t_irc_nick *last_nick; /* last nick on the channel */
t_weelist *nicks_speaking; /* nicks speaking (for smart completion) */
t_weelist *last_nick_speaking; /* last nick speaking */
t_gui_buffer *buffer; /* GUI buffer allocated for channel */
t_irc_channel *prev_channel; /* link to previous channel */
t_irc_channel *next_channel; /* link to next channel */
@ -415,6 +420,7 @@ extern void channel_set_away (t_irc_channel *, char *, int);
extern int channel_create_dcc (t_irc_dcc *);
extern int channel_get_notify_level (t_irc_server *, t_irc_channel *);
extern void channel_set_notify_level (t_irc_server *, t_irc_channel *, int);
extern void channel_add_nick_speaking (t_irc_channel *, char *);
extern void channel_print_log (t_irc_channel *);
/* nick functions (irc-nick.c) */

View File

@ -322,7 +322,8 @@ plugin_cmd_handler_add (t_weechat_plugin *plugin, char *command,
/* add command to WeeChat commands list */
if (!weelist_search (index_commands, command))
weelist_add (&index_commands, &last_index_command, command);
weelist_add (&index_commands, &last_index_command, command,
WEELIST_POS_SORT);
}
else
{