Add Completion module and emoji completion hook

Note: this doesn't enable emoji completion.

Weechat seems to require hooking on the commands
  /input complete_*
rather than just invoking hook_completion.
v1
Tony Olagbaiye 6 years ago
parent 48257b7cc1
commit 5217251e94
No known key found for this signature in database
GPG Key ID: 7420820577A31D11

@ -19,6 +19,7 @@ SRCS=slack.c \
slack-channel.c \
slack-config.c \
slack-command.c \
slack-completion.c \
slack-emoji.c \
slack-input.c \
slack-message.c \

@ -0,0 +1,20 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, version 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <string.h>
#include "weechat-plugin.h"
#include "slack.h"
#include "slack-emoji.h"
#include "slack-workspace.h"
#include "slack-channel.h"
#include "slack-completion.h"
void slack_completion_init()
{
weechat_hook_completion("slack_emoji",
N_("slack emoji"),
&slack_emoji_complete_by_name_cb,
NULL, NULL);
}

@ -0,0 +1,10 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, version 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef _SLACK_COMPLETION_H_
#define _SLACK_COMPLETION_H_
void slack_completion_init();
#endif /*SLACK_COMPLETION_H*/

@ -2,6 +2,7 @@
// License, version 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <stdlib.h>
#include <string.h>
#include "weechat-plugin.h"
@ -10,6 +11,8 @@
#include "slack-emoji.inc"
#define MIN(a,b) (((a)<(b))?(a):(b))
static int emoji_byname_cmp(const void *p1, const void *p2)
{
return strcasecmp(((struct t_slack_emoji_by_name *)p1)->name,
@ -22,6 +25,88 @@ static int emoji_bytext_cmp(const void *p1, const void *p2)
((struct t_slack_emoji_by_text *)p2)->text);
}
static size_t levenshtein_dist(const char *s, size_t len_s, const char *t, size_t len_t)
{
size_t cost;
/* base case: empty strings */
if (len_s == 0) return len_t;
if (len_t == 0) return len_s;
/* test if last characters of the strings match */
if (s[len_s-1] == t[len_t-1])
cost = 0;
else
cost = 1;
/* delete char from s, delete char from t, and delete char from both */
size_t delete = levenshtein_dist(s, len_s - 1, t, len_t ) + 1;
size_t insert = levenshtein_dist(s, len_s , t, len_t - 1) + 1;
size_t replace = levenshtein_dist(s, len_s - 1, t, len_t - 1) + cost;
return MIN( MIN( delete, insert ), replace );
}
static size_t wagner_fischer(const char *src, const char *targ)
{
size_t len = strlen(targ) + 1;
size_t above[len], below[len];
for (size_t *k = above, c = 0; k < above+len; ++k, ++c) *k=c;
const char *src_at = src, *targ_at;
for (size_t j = 1; j < strlen(src)+1; ++j)
{
*below = j;
targ_at = targ;
for (size_t *d = above, *a = above+1, *l = below, *c = below + 1;
c < below + len; ++d, ++a, ++l, ++c)
{
*c = MIN( *src_at == *targ_at ? *d : *d + 1, MIN( *a + 1, *l + 1 ) );
++targ_at;
}
for (size_t *a = above, *b = below; a < above + len; ++a, ++b) *a = *b;
++src_at;
}
return above[len-1];
}
int slack_emoji_complete_by_name_cb(const void *pointer, void *data,
const char *completion_item,
struct t_gui_buffer *buffer,
struct t_gui_completion *completion)
{
struct t_slack_emoji_by_name *closest_emoji;
(void) pointer;
(void) data;
weechat_printf(NULL, "Completing!");
size_t i, emoji_count = sizeof(slack_emoji_by_name)
/ sizeof(struct t_slack_emoji_by_name);
closest_emoji = malloc(sizeof(slack_emoji_by_name));
memcpy(closest_emoji, slack_emoji_by_name,
sizeof(slack_emoji_by_name));
int edit_dist_cmp(const void *p1, const void *p2)
{
return 0;
};
qsort(closest_emoji, emoji_count,
sizeof(struct t_slack_emoji_by_name),
edit_dist_cmp);
for (i = 0; i < emoji_count; i++)
{
weechat_printf(NULL, closest_emoji[i].name);
weechat_hook_completion_list_add(completion, closest_emoji[i].name,
0, WEECHAT_LIST_POS_END);
}
free(closest_emoji);
return WEECHAT_RC_OK;
}
const char *slack_emoji_get_unicode_by_name(const char *name)
{
struct t_slack_emoji_by_name *result;
@ -70,7 +155,7 @@ const char *slack_emoji_get_text_by_name(const char *name)
return result->text_to;
}
const char *slack_emoji_get_text_by_text(const char *text)
const char *slack_emoji_get_name_by_text(const char *text)
{
struct t_slack_emoji_by_text *result;
struct t_slack_emoji_by_text key;
@ -83,5 +168,5 @@ const char *slack_emoji_get_text_by_text(const char *text)
sizeof(struct t_slack_emoji_by_text),
emoji_bytext_cmp);
return result->text_to;
return result->name_to;
}

@ -5,12 +5,17 @@
#ifndef _SLACK_EMOJI_H_
#define _SLACK_EMOJI_H_
int slack_emoji_complete_by_name_cb(const void *pointer, void *data,
const char *completion_item,
struct t_gui_buffer *buffer,
struct t_gui_completion *completion);
const char *slack_emoji_get_unicode_by_name(const char *name);
const char *slack_emoji_get_unicode_by_text(const char *text);
const char *slack_emoji_get_text_by_name(const char *name);
const char *slack_emoji_get_text_by_text(const char *text);
const char *slack_emoji_get_name_by_text(const char *text);
#endif /*SLACK_EMOJI_H*/

File diff suppressed because it is too large Load Diff

@ -51,16 +51,21 @@ my %byname = map { my $o = $_; map {($_, $o)} @{$o->{'short_names'}} } @array;
my @sortedbyname = sort { $a cmp $b } keys %byname;
foreach my $name (@sortedbyname)
{
my $_0 = "\"$name\"";
my $_0 = "\":$name:\"";
my @_1 = split /-/, $byname{$name}->{'unified'};
my $_1 = "\"";
foreach my $codepoint (@_1) { $_1 .= "\\u$codepoint" };
foreach my $codepoint (@_1) {
if (hex $codepoint < 0xA0) { $_1 .= chr hex $codepoint } else { $_1 .= "\\u$codepoint" }
};
$_1 .= "\"";
$_1 =~ tr/A-Za-z/a-za-z/;
my $_2 = $byname{$name}->{'text'};
if (defined $_2) { $_2 = "\"$_2\"" } else { $_2 = "NULL" };
$_2 =~ s/\\/\\\\/g;
my $_3 = "{";
foreach my $text (@{$byname{$name}->{'texts'}}) { if (defined $text) { $_3 .= "\"$text\", " } };
$_3 .= "NULL}";
$_3 =~ s/\\/\\\\/g;
print "$c { $_0, $_1, $_2, $_3 }";
$c = ',';
}
@ -73,14 +78,18 @@ my @sortedbytext = sort { $a cmp $b } keys %bytext;
foreach my $text (@sortedbytext)
{
my $_0 = "\"$text\"";
$_0 =~ s/\\/\\\\/g;
my @_1 = split /-/, $bytext{$text}->{'unified'};
my $_1 = "\"";
foreach my $codepoint (@_1) { $_1 .= "\\u$codepoint" };
foreach my $codepoint (@_1) {
if (hex $codepoint < 0xA0) { $_1 .= chr hex $codepoint } else { $_1 .= "\\u$codepoint" }
};
$_1 .= "\"";
$_1 =~ tr/A-Za-z/a-za-z/;
my $_2 = $bytext{$text}->{'short_name'};
if (defined $_2) { $_2 = "\"$_2\"" } else { $_2 = "NULL" };
if (defined $_2) { $_2 = "\":$_2:\"" } else { $_2 = "NULL" };
my $_3 = "{";
foreach my $name (@{$bytext{$text}->{'short_names'}}) { if (defined $name) { $_3 .= "\"$name\", " } };
foreach my $name (@{$bytext{$text}->{'short_names'}}) { if (defined $name) { $_3 .= "\":$name:\", " } };
$_3 .= "NULL}";
print "$c { $_0, $_1, $_2, $_3 }";
$c = ',';

@ -1,5 +1,4 @@
#!/usr/bin/python
# Compatible with python v2 and v3
#!/usr/bin/env python3
# This Source Code Form is subject to the terms of the Mozilla Public
# License, version 2.0. If a copy of the MPL was not distributed with this
@ -38,7 +37,7 @@ struct t_slack_emoji_by_text {
max(len(o['short_names'] if o['short_names'] else []) for o in emoji) + 1))
print("static struct t_slack_emoji_by_name slack_emoji_by_name[] =")
print("{"+"\n".join(", {{ {0}, {1}, {2}, {3} }}".format(
json.dumps(name),
json.dumps(":"+name+":"),
json.dumps(ast.parse("\"\\u"+"\\u".join(o['unified'].split('-'))+"\"", mode='eval').body.s),
json.dumps(o['text']),
"{"+json.dumps(o['texts']+[None] if o['texts'] else [None])[1:-1]+"}")
@ -51,8 +50,9 @@ print("static struct t_slack_emoji_by_text slack_emoji_by_text[] =")
print("{"+"\n".join(", {{ {0}, {1}, {2}, {3} }}".format(
json.dumps(text),
json.dumps(ast.parse("\"\\u"+"\\u".join(o['unified'].split('-'))+"\"", mode='eval').body.s),
json.dumps(o['short_name']),
"{"+json.dumps(o['short_names']+[None] if o['short_names'] else [None])[1:-1]+"}")
json.dumps(":"+o['short_name']+":"),
"{"+json.dumps(list(map(lambda name: ":"+name+":", o['short_names']))+[None]
if o['short_names'] else [None])[1:-1]+"}")
for o,text in sorted(((o,text) for o in emoji if o['texts'] for text in o['texts']),
key=lambda x:x[1])
).replace("null", "NULL")[1:])

@ -15,6 +15,7 @@
#include "slack-workspace.h"
#include "slack-api.h"
#include "slack-buffer.h"
#include "slack-completion.h"
WEECHAT_PLUGIN_NAME(SLACK_PLUGIN_NAME);
@ -49,7 +50,7 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[])
weechat_plugin = plugin;
lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE /*| LLL_INFO | LLL_DEBUG
lws_set_log_level(LLL_ERR | LLL_WARN /*| LLL_NOTICE | LLL_INFO | LLL_DEBUG
| LLL_PARSER | LLL_HEADER | LLL_EXT | LLL_CLIENT
| LLL_LATENCY | LLL_USER | LLL_COUNT*/,
slack_lwsl_emit_weechat);
@ -63,6 +64,8 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[])
slack_api_init();
slack_completion_init();
slack_hook_timer = weechat_hook_timer(0.1 * 1000, 0, 0,
&slack_workspace_timer_cb,
NULL, NULL);

Loading…
Cancel
Save