Skip to content

Commit

Permalink
Implement sorting nick completions by speaking
Browse files Browse the repository at this point in the history
  • Loading branch information
Tony Olagbaiye committed May 14, 2018
1 parent 0e8ea07 commit 58d46c7
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 3 deletions.
6 changes: 3 additions & 3 deletions README.org
Expand Up @@ -29,11 +29,11 @@

* Usage

1. Start with `/slack register` for instructions on how
1. Start with =/slack register= for instructions on how
to obtain a token, or if you already have a token, use
`/slack register <token>`.
=/slack register <token>=.

2. Use `/slack connect <workspace-name>` with the name
2. Use =/slack connect <workspace-name>= with the name
returned by register

* Installing
Expand Down
4 changes: 4 additions & 0 deletions api/slack-api-message.c
Expand Up @@ -107,6 +107,10 @@ int slack_api_message_message_handle(struct t_slack_workspace *workspace,
_("%s%s"),
slack_user_as_prefix(workspace, ptr_user, NULL),
message);
slack_channel_member_speaking_add(channel, ptr_user->profile.display_name,
weechat_string_has_highlight(
message,
ptr_user->profile.display_name));
free(message);

ptr_typing = slack_channel_typing_search(ptr_channel,
Expand Down
95 changes: 95 additions & 0 deletions slack-channel.c
Expand Up @@ -237,6 +237,8 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace,
new_channel->is_user_deleted = 0;

new_channel->typing_hook_timer = typing_timer;
new_channel->members_speaking[0] = NULL;
new_channel->members_speaking[1] = NULL;
new_channel->typings = NULL;
new_channel->last_typing = NULL;
new_channel->members = NULL;
Expand All @@ -255,6 +257,95 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace,
return new_channel;
}

void slack_channel_member_speaking_add_to_list(struct t_slack_channel *channel,
const char *nick,
int highlight)
{
int size, to_remove, i;
struct t_weelist_item *ptr_item;

/* create list if it does not exist */
if (!channel->members_speaking[highlight])
channel->members_speaking[highlight] = weechat_list_new();

/* remove item if it was already in list */
ptr_item = weechat_list_casesearch(channel->members_speaking[highlight], nick);
if (ptr_item)
weechat_list_remove(channel->members_speaking[highlight], ptr_item);

/* add nick in list */
weechat_list_add(channel->members_speaking[highlight], nick,
WEECHAT_LIST_POS_END, NULL);

/* reduce list size if it's too big */
size = weechat_list_size(channel->members_speaking[highlight]);
if (size > SLACK_CHANNEL_MEMBERS_SPEAKING_LIMIT)
{
to_remove = size - SLACK_CHANNEL_MEMBERS_SPEAKING_LIMIT;
for (i = 0; i < to_remove; i++)
{
weechat_list_remove(
channel->members_speaking[highlight],
weechat_list_get(channel->members_speaking[highlight], 0));
}
}
}

void slack_channel_member_speaking_add(struct t_slack_channel *channel,
const char *nick, int highlight)
{
if (highlight < 0)
highlight = 0;
if (highlight > 1)
highlight = 1;
if (highlight)
slack_channel_member_speaking_add_to_list(channel, nick, 1);

slack_channel_member_speaking_add_to_list(channel, nick, 0);
}

void slack_channel_member_speaking_rename(struct t_slack_channel *channel,
const char *old_nick,
const char *new_nick)
{
struct t_weelist_item *ptr_item;
int i;

for (i = 0; i < 2; i++)
{
if (channel->members_speaking[i])
{
ptr_item = weechat_list_search(channel->members_speaking[i], old_nick);
if (ptr_item)
weechat_list_set(ptr_item, new_nick);
}
}
}

void slack_channel_member_speaking_rename_if_present(struct t_slack_workspace *workspace,
struct t_slack_channel *channel,
const char *nick)
{
struct t_weelist_item *ptr_item;
int i, j, list_size;

(void) workspace;

for (i = 0; i < 2; i++)
{
if (channel->members_speaking[i])
{
list_size = weechat_list_size(channel->members_speaking[i]);
for (j = 0; j < list_size; j++)
{
ptr_item = weechat_list_get (channel->members_speaking[i], j);
if (ptr_item && (strcasecmp(weechat_list_string(ptr_item), nick) == 0))
weechat_list_set(ptr_item, nick);
}
}
}
}

void slack_channel_typing_free(struct t_slack_channel *channel,
struct t_slack_channel_typing *typing)
{
Expand Down Expand Up @@ -473,6 +564,10 @@ void slack_channel_free(struct t_slack_workspace *workspace,
free(channel->purpose.creator);
if (channel->creator)
free(channel->creator);
if (channel->members_speaking[0])
weechat_list_free(channel->members_speaking[0]);
if (channel->members_speaking[1])
weechat_list_free(channel->members_speaking[1]);
if (channel->buffer_as_string)
free(channel->buffer_as_string);

Expand Down
14 changes: 14 additions & 0 deletions slack-channel.h
Expand Up @@ -5,6 +5,8 @@
#ifndef _SLACK_CHANNEL_H_
#define _SLACK_CHANNEL_H_

#define SLACK_CHANNEL_MEMBERS_SPEAKING_LIMIT 128

#define SLACK_CHANNEL_NAME_MAX_LEN 22

enum t_slack_channel_type
Expand Down Expand Up @@ -76,6 +78,7 @@ struct t_slack_channel
int is_user_deleted;

struct t_hook *typing_hook_timer;
struct t_weelist *members_speaking[2];
struct t_slack_channel_typing *typings;
struct t_slack_channel_typing *last_typing;
struct t_slack_channel_member *members;
Expand All @@ -97,6 +100,17 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace,
enum t_slack_channel_type type,
const char *id, const char *name);

void slack_channel_member_speaking_add(struct t_slack_channel *channel,
const char *nick, int highlight);

void slack_channel_member_speaking_rename(struct t_slack_channel *channel,
const char *old_nick,
const char *new_nick);

void slack_channel_member_speaking_rename_if_present(struct t_slack_workspace *workspace,
struct t_slack_channel *channel,
const char *nick);

void slack_channel_typing_free(struct t_slack_channel *channel,
struct t_slack_channel_typing *typing);

Expand Down
94 changes: 94 additions & 0 deletions slack-completion.c
Expand Up @@ -8,11 +8,99 @@

#include "weechat-plugin.h"
#include "slack.h"
#include "slack-config.h"
#include "slack-emoji.h"
#include "slack-workspace.h"
#include "slack-channel.h"
#include "slack-user.h"
#include "slack-buffer.h"
#include "slack-completion.h"

void slack_completion_channel_nicks_add_speakers(struct t_gui_completion *completion,
struct t_slack_workspace *workspace,
struct t_slack_channel *channel,
int highlight)
{
struct t_slack_user *user;
const char *member;
int list_size, i;

if (channel->members_speaking[highlight])
{
list_size = weechat_list_size(channel->members_speaking[highlight]);
for (i = 0; i < list_size; i++)
{
member = weechat_list_string (
weechat_list_get(channel->members_speaking[highlight], i));
if (member)
{
user = slack_user_search(workspace, member);
if (user)
weechat_hook_completion_list_add(completion,
user->profile.display_name,
1, WEECHAT_LIST_POS_BEGINNING);
}
}
}
}

int slack_completion_channel_nicks_cb(const void *pointer, void *data,
const char *completion_item,
struct t_gui_buffer *buffer,
struct t_gui_completion *completion)
{
struct t_slack_workspace *ptr_workspace;
struct t_slack_channel *ptr_channel;
struct t_slack_channel_member *ptr_member;
struct t_slack_user *ptr_user;

/* make C compiler happy */
(void) pointer;
(void) data;
(void) completion_item;

ptr_workspace = NULL;
ptr_channel = NULL;
slack_buffer_get_workspace_and_channel(buffer, &ptr_workspace, &ptr_channel);

if (ptr_channel)
{
switch (ptr_channel->type)
{
case SLACK_CHANNEL_TYPE_CHANNEL:
case SLACK_CHANNEL_TYPE_GROUP:
case SLACK_CHANNEL_TYPE_MPIM:
case SLACK_CHANNEL_TYPE_IM:
for (ptr_member = ptr_channel->members; ptr_member;
ptr_member = ptr_member->next_member)
{
ptr_user = slack_user_search(ptr_workspace, ptr_member->id);
if (ptr_user)
weechat_hook_completion_list_add(completion,
ptr_user->profile.display_name,
1, WEECHAT_LIST_POS_SORT);
}
/* add recent speakers on channel */
if (weechat_config_integer(slack_config_look_nick_completion_smart) == SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS)
{
slack_completion_channel_nicks_add_speakers(completion, ptr_workspace, ptr_channel, 0);
}
/* add members whose make highlights on me recently on this channel */
if (weechat_config_integer(slack_config_look_nick_completion_smart) == SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS_HIGHLIGHTS)
{
slack_completion_channel_nicks_add_speakers(completion, ptr_workspace, ptr_channel, 1);
}
/* add self member at the end */
weechat_hook_completion_list_add(completion,
ptr_workspace->nick,
1, WEECHAT_LIST_POS_END);
break;
}
}

return WEECHAT_RC_OK;
}

int slack_completion_workspaces_cb(const void *pointer, void *data,
const char *completion_item,
struct t_gui_buffer *buffer,
Expand Down Expand Up @@ -40,6 +128,12 @@ void slack_completion_init()
{
struct t_config_option *option;
const char *default_template;


weechat_hook_completion ("nick",
N_("nicks of current Slack channel"),
&slack_completion_channel_nicks_cb,
NULL, NULL);

weechat_hook_completion("slack_workspace",
N_("slack workspaces"),
Expand Down
27 changes: 27 additions & 0 deletions slack-config.c
Expand Up @@ -15,6 +15,8 @@ struct t_config_file *slack_config_file;
struct t_config_section *slack_config_section_workspace_default;
struct t_config_section *slack_config_section_workspace;

struct t_config_option *slack_config_look_nick_completion_smart;

struct t_config_option *slack_config_workspace_default[SLACK_WORKSPACE_NUM_OPTIONS];

int slack_config_workspace_check_value_cb(const void *pointer, void *data,
Expand Down Expand Up @@ -243,6 +245,31 @@ int slack_config_init()
if(!slack_config_file)
return 0;

ptr_section = weechat_config_new_section(
slack_config_file, "look",
0, 0,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL);

if (!ptr_section)
{
weechat_config_free(slack_config_file);
slack_config_file = NULL;
return 0;
}

slack_config_look_nick_completion_smart = weechat_config_new_option (
slack_config_file, ptr_section,
"nick_completion_smart", "integer",
N_("smart completion for nicks (completes first with last speakers): "
"speakers = all speakers (including highlights), "
"speakers_highlights = only speakers with highlight"),
"off|speakers|speakers_highlights", 0, 0, "speakers", NULL, 0,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);

ptr_section = weechat_config_new_section(
slack_config_file, "workspace_default",
0, 0,
Expand Down
9 changes: 9 additions & 0 deletions slack-config.h
Expand Up @@ -7,11 +7,20 @@

#define SLACK_CONFIG_NAME "slack"

enum t_slack_config_nick_completion
{
SLACK_CONFIG_NICK_COMPLETION_SMART_OFF = 0,
SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS,
SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS_HIGHLIGHTS,
};

extern struct t_config_file *slack_config_file;

extern struct t_config_section *slack_config_section_workspace_default;
extern struct t_config_section *slack_config_section_workspace;

extern struct t_config_option *slack_config_look_nick_completion_smart;

extern struct t_config_option *slack_config_workspace_default[];

int slack_config_workspace_check_value_cb(const void *pointer, void *data,
Expand Down

0 comments on commit 58d46c7

Please sign in to comment.