Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
2336340ad8
|
|||
|
8f5dec0456
|
|||
|
3dc6ee9a5b
|
|||
|
821ce04915
|
|||
|
2fe3b95ecd
|
|||
|
32c99c9d66
|
|||
|
cd7133e173
|
|||
|
b4ed52015a
|
|||
|
271689da99
|
|||
|
38c23d0d38
|
|||
|
439af8884c
|
|||
|
8ccf38ad76
|
|||
|
47a4c8beca
|
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required (VERSION 3.0)
|
||||
project (uirc3 VERSION 1.0.0 LANGUAGES C)
|
||||
project (uirc3 VERSION 1.1.0 LANGUAGES C)
|
||||
|
||||
# Options
|
||||
option (WANT_READLINE "Use GNU Readline for the UI (better)" ON)
|
||||
@@ -54,8 +54,6 @@ include_directories (${libssl_INCLUDE_DIRS})
|
||||
link_directories (${libssl_LIBRARY_DIRS})
|
||||
|
||||
if ("${CMAKE_SYSTEM_NAME}" MATCHES "BSD")
|
||||
include_directories (/usr/local/include)
|
||||
link_directories (/usr/local/lib)
|
||||
# Need this for SIGWINCH in FreeBSD and OpenBSD respectively;
|
||||
# our POSIX version macros make it undefined
|
||||
add_definitions (-D__BSD_VISIBLE=1 -D_BSD_SOURCE=1)
|
||||
@@ -115,7 +113,7 @@ if ((WANT_READLINE AND WANT_LIBEDIT) OR (NOT WANT_READLINE AND NOT WANT_LIBEDIT)
|
||||
elseif (WANT_READLINE)
|
||||
# OpenBSD's default readline is too old
|
||||
if ("${CMAKE_SYSTEM_NAME}" MATCHES "OpenBSD")
|
||||
include_directories (/usr/local/include/ereadline)
|
||||
include_directories (${OPENBSD_LOCALBASE}/include/ereadline)
|
||||
list (APPEND degesch_libraries ereadline)
|
||||
else ()
|
||||
list (APPEND degesch_libraries readline)
|
||||
@@ -218,7 +216,7 @@ foreach (page ${project_MAN_PAGES})
|
||||
endforeach ()
|
||||
|
||||
# CPack
|
||||
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Experimental IRC client, daemon and bot")
|
||||
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Unethical IRC client, daemon and bot")
|
||||
set (CPACK_PACKAGE_VERSION "${project_version_safe}")
|
||||
set (CPACK_PACKAGE_VENDOR "Premysl Eric Janouch")
|
||||
set (CPACK_PACKAGE_CONTACT "Přemysl Eric Janouch <p@janouch.name>")
|
||||
|
||||
9
NEWS
9
NEWS
@@ -1,3 +1,12 @@
|
||||
1.1.0 (2020-10-31) "What Do You Mean By 'This Isn't Germany'?"
|
||||
|
||||
* degesch: made fancy-prompt.lua work with libedit
|
||||
|
||||
* kike: fixed a regression with an unspecified "bind_host"
|
||||
|
||||
* Miscellaneous minor improvements
|
||||
|
||||
|
||||
1.0.0 (2020-10-29) "We're Finally There!"
|
||||
|
||||
* Coming with real manual pages instead of help2man-generated stubs
|
||||
|
||||
15
README.adoc
15
README.adoc
@@ -3,8 +3,8 @@ uirc3
|
||||
:compact-option:
|
||||
|
||||
The [line-through]#unethical# edgy IRC trinity. This project consists of an
|
||||
experimental IRC client, daemon, and bot. It's all you're ever going to need
|
||||
for chatting, as long as you can make do with minimalist software.
|
||||
IRC client, daemon, and bot. It's all you're ever going to need for chatting,
|
||||
as long as you can make do with minimalist software.
|
||||
|
||||
All of them have these potentially interesting properties:
|
||||
|
||||
@@ -103,6 +103,7 @@ Or you can try telling CMake to make a package for you. For Debian it is:
|
||||
Usage
|
||||
-----
|
||||
'degesch' has in-program configuration. Just run it and read the instructions.
|
||||
Consult its link:degesch.adoc[man page] for details about the interface.
|
||||
|
||||
For the rest you might want to generate a configuration file:
|
||||
|
||||
@@ -124,7 +125,7 @@ as a `forking` type systemd user service.
|
||||
|
||||
Client Certificates
|
||||
-------------------
|
||||
'kike' uses SHA1 fingerprints of TLS client certificates to authenticate users.
|
||||
'kike' uses SHA-1 fingerprints of TLS client certificates to authenticate users.
|
||||
To get the fingerprint from a certificate file in the required form, use:
|
||||
|
||||
$ openssl x509 -in public.pem -outform DER | sha1sum
|
||||
@@ -152,13 +153,13 @@ Beware that you can easily break the program if you're not careful.
|
||||
How do I make degesch look like the screenshot?
|
||||
-----------------------------------------------
|
||||
First of all, you must build it with Lua support. With the defaults, degesch
|
||||
doesn't look very fancy because some things are rather hackish, and I also don't
|
||||
want to depend on UTF-8 or 256color terminals in the code. In addition to that,
|
||||
I appear to be one of the few people who use black on white terminals.
|
||||
doesn't look too fancy because I don't want to depend on Lua or 256-colour
|
||||
terminals. In addition to that, I appear to be one of the few people who use
|
||||
black on white terminals.
|
||||
|
||||
/set behaviour.date_change_line = "%a %e %b %Y"
|
||||
/set behaviour.plugin_autoload += "fancy-prompt.lua"
|
||||
/set behaviour.backlog_helper = "LESSSECURE=1 less -R +Gb -Ps'Backlog ?ltlines %lt-%lb?L/%L. .?e(END):?pB%pB\\%..'"
|
||||
/set behaviour.backlog_helper = "LESSSECURE=1 less -R +Gb1d -Ps'Backlog ?ltlines %lt-%lb?L/%L. .?e(END):?pB%pB\\%..'"
|
||||
/set attributes.userhost = "\x1b[38;5;109m"
|
||||
/set attributes.join = "\x1b[38;5;108m"
|
||||
/set attributes.part = "\x1b[38;5;138m"
|
||||
|
||||
@@ -6,7 +6,7 @@ degesch(1)
|
||||
|
||||
Name
|
||||
----
|
||||
degesch - an experimental IRC client
|
||||
degesch - terminal-based IRC client
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
168
degesch.c
168
degesch.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* degesch.c: the experimental IRC client
|
||||
* degesch.c: a terminal-based IRC client
|
||||
*
|
||||
* Copyright (c) 2015 - 2020, Přemysl Eric Janouch <p@janouch.name>
|
||||
*
|
||||
@@ -1591,12 +1591,14 @@ static struct ispect_field g_buffer_ispect[] =
|
||||
};
|
||||
|
||||
static struct buffer *
|
||||
buffer_new (struct input *input)
|
||||
buffer_new (struct input *input, enum buffer_type type, char *name)
|
||||
{
|
||||
struct buffer *self = xcalloc (1, sizeof *self);
|
||||
self->ref_count = 1;
|
||||
self->input = input;
|
||||
self->input_data = CALL (input, buffer_new);
|
||||
self->type = type;
|
||||
self->name = name;
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -2458,7 +2460,7 @@ static struct config_schema g_config_behaviour[] =
|
||||
{ .name = "backlog_helper",
|
||||
.comment = "Shell command to display a buffer's history",
|
||||
.type = CONFIG_ITEM_STRING,
|
||||
.default_ = "\"LESSSECURE=1 less -M -R +G\"" },
|
||||
.default_ = "\"LESSSECURE=1 less -M -R +Gb\"" },
|
||||
{ .name = "backlog_helper_strip_formatting",
|
||||
.comment = "Strip formatting from backlog helper input",
|
||||
.type = CONFIG_ITEM_BOOLEAN,
|
||||
@@ -4446,9 +4448,8 @@ buffer_remove_safe (struct app_context *ctx, struct buffer *buffer)
|
||||
static void
|
||||
init_global_buffer (struct app_context *ctx)
|
||||
{
|
||||
struct buffer *global = ctx->global_buffer = buffer_new (ctx->input);
|
||||
global->type = BUFFER_GLOBAL;
|
||||
global->name = xstrdup (PROGRAM_NAME);
|
||||
struct buffer *global = ctx->global_buffer =
|
||||
buffer_new (ctx->input, BUFFER_GLOBAL, xstrdup (PROGRAM_NAME));
|
||||
|
||||
buffer_add (ctx, global);
|
||||
buffer_activate (ctx, global);
|
||||
@@ -4456,6 +4457,19 @@ init_global_buffer (struct app_context *ctx)
|
||||
|
||||
// --- Users, channels ---------------------------------------------------------
|
||||
|
||||
static char *
|
||||
irc_make_buffer_name (struct server *s, const char *target)
|
||||
{
|
||||
if (!target)
|
||||
return xstrdup (s->name);
|
||||
|
||||
// XXX: this may be able to trigger the uniqueness assertion with non-UTF-8
|
||||
char *target_utf8 = irc_to_utf8 (target);
|
||||
char *result = xstrdup_printf ("%s.%s", s->name, target_utf8);
|
||||
free (target_utf8);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
irc_user_on_destroy (void *object, void *user_data)
|
||||
{
|
||||
@@ -4495,9 +4509,8 @@ irc_get_or_make_user_buffer (struct server *s, const char *nickname)
|
||||
struct user *user = irc_get_or_make_user (s, nickname);
|
||||
|
||||
// Open a new buffer for the user
|
||||
buffer = buffer_new (s->ctx->input);
|
||||
buffer->type = BUFFER_PM;
|
||||
buffer->name = xstrdup_printf ("%s.%s", s->name, nickname);
|
||||
buffer = buffer_new (s->ctx->input,
|
||||
BUFFER_PM, irc_make_buffer_name (s, nickname));
|
||||
buffer->server = s;
|
||||
buffer->user = user;
|
||||
str_map_set (&s->irc_buffer_map, user->nickname, buffer);
|
||||
@@ -6028,6 +6041,14 @@ make_prompt (struct app_context *ctx, struct str *output)
|
||||
static void
|
||||
input_maybe_set_prompt (struct input *self, char *new_prompt)
|
||||
{
|
||||
// Fix libedit's expectations to see a non-control character following
|
||||
// the end mark (see prompt.c and literal.c) by cleaning this up
|
||||
for (char *p = new_prompt; *p; )
|
||||
if (p[0] == INPUT_END_IGNORE && p[1] == INPUT_START_IGNORE)
|
||||
memmove (p, p + 2, strlen (p + 2) + 1);
|
||||
else
|
||||
p++;
|
||||
|
||||
// Redisplay can be an expensive operation
|
||||
const char *prompt = CALL (self, get_prompt);
|
||||
if (prompt && !strcmp (new_prompt, prompt))
|
||||
@@ -6055,6 +6076,12 @@ on_refresh_prompt (struct app_context *ctx)
|
||||
prompt.str[--prompt.len] = 0;
|
||||
attributed_suffix = " ";
|
||||
}
|
||||
|
||||
// Also enable a uniform interface for prompt hooks by assuming it uses
|
||||
// GNU Readline escapes: turn this into libedit's almost-flip-flop
|
||||
for (size_t i = 0; i < prompt.len; i++)
|
||||
if (prompt.str[i] == '\x01' || prompt.str[i] == '\x02')
|
||||
prompt.str[i] = INPUT_START_IGNORE /* == INPUT_END_IGNORE */;
|
||||
#endif // HAVE_EDITLINE
|
||||
|
||||
char *localized = iconv_xstrdup (ctx->term_from_utf8, prompt.str, -1, NULL);
|
||||
@@ -6628,15 +6655,15 @@ irc_handle_join (struct server *s, const struct irc_message *msg)
|
||||
if (!irc_is_this_us (s, msg->prefix))
|
||||
return;
|
||||
|
||||
buffer = buffer_new (s->ctx->input);
|
||||
buffer->type = BUFFER_CHANNEL;
|
||||
buffer->name = xstrdup_printf ("%s.%s", s->name, channel_name);
|
||||
buffer = buffer_new (s->ctx->input,
|
||||
BUFFER_CHANNEL, irc_make_buffer_name (s, channel_name));
|
||||
buffer->server = s;
|
||||
buffer->channel = channel =
|
||||
irc_make_channel (s, xstrdup (channel_name));
|
||||
str_map_set (&s->irc_buffer_map, channel->name, buffer);
|
||||
|
||||
buffer_add (s->ctx, buffer);
|
||||
// XXX: this is annoying, consider only doing it a while after /join
|
||||
buffer_activate (s->ctx, buffer);
|
||||
}
|
||||
|
||||
@@ -8299,9 +8326,8 @@ server_add (struct app_context *ctx,
|
||||
s->config = subtree;
|
||||
|
||||
// Add a buffer and activate it
|
||||
struct buffer *buffer = s->buffer = buffer_new (ctx->input);
|
||||
buffer->type = BUFFER_SERVER;
|
||||
buffer->name = xstrdup (s->name);
|
||||
struct buffer *buffer = s->buffer = buffer_new (ctx->input,
|
||||
BUFFER_SERVER, irc_make_buffer_name (s, NULL));
|
||||
buffer->server = s;
|
||||
|
||||
buffer_add (ctx, buffer);
|
||||
@@ -12341,15 +12367,12 @@ completion_locate (struct completion *self, size_t offset)
|
||||
self->location = i - 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
completion_matches (struct completion *self, int word, const char *pattern)
|
||||
static char *
|
||||
completion_word (struct completion *self, int word)
|
||||
{
|
||||
hard_assert (word >= 0 && word < (int) self->words_len);
|
||||
char *text = xstrndup (self->line + self->words[word].start,
|
||||
return xstrndup (self->line + self->words[word].start,
|
||||
self->words[word].end - self->words[word].start);
|
||||
bool result = !fnmatch (pattern, text, 0);
|
||||
free (text);
|
||||
return result;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@@ -12444,6 +12467,66 @@ complete_option (struct app_context *ctx, struct completion *data,
|
||||
strv_free (&options);
|
||||
}
|
||||
|
||||
static void
|
||||
complete_set_value (struct config_item *item, const char *word,
|
||||
struct strv *output)
|
||||
{
|
||||
struct str serialized = str_make ();
|
||||
config_item_write (item, false, &serialized);
|
||||
if (!strncmp (serialized.str, word, strlen (word)))
|
||||
strv_append_owned (output, str_steal (&serialized));
|
||||
else
|
||||
str_free (&serialized);
|
||||
}
|
||||
|
||||
static void
|
||||
complete_set_value_array (struct config_item *item, const char *word,
|
||||
struct strv *output)
|
||||
{
|
||||
if (!item->schema || item->schema->type != CONFIG_ITEM_STRING_ARRAY)
|
||||
return;
|
||||
|
||||
struct strv items = strv_make ();
|
||||
cstr_split (item->value.string.str, ",", false, &items);
|
||||
for (size_t i = 0; i < items.len; i++)
|
||||
{
|
||||
struct str wrapped = str_make (), serialized = str_make ();
|
||||
str_append (&wrapped, items.vector[i]);
|
||||
config_item_write_string (&serialized, &wrapped);
|
||||
str_free (&wrapped);
|
||||
|
||||
if (!strncmp (serialized.str, word, strlen (word)))
|
||||
strv_append_owned (output, str_steal (&serialized));
|
||||
else
|
||||
str_free (&serialized);
|
||||
}
|
||||
strv_free (&items);
|
||||
}
|
||||
|
||||
static void
|
||||
complete_set (struct app_context *ctx, struct completion *data,
|
||||
const char *word, struct strv *output)
|
||||
{
|
||||
if (data->location == 1)
|
||||
{
|
||||
complete_option (ctx, data, word, output);
|
||||
return;
|
||||
}
|
||||
if (data->location != 3)
|
||||
return;
|
||||
|
||||
char *key = completion_word (data, 1);
|
||||
struct config_item *item = config_item_get (ctx->config.root, key, NULL);
|
||||
if (item)
|
||||
{
|
||||
char *op = completion_word (data, 2);
|
||||
if (!strcmp (op, "-=")) complete_set_value_array (item, word, output);
|
||||
if (!strcmp (op, "=")) complete_set_value (item, word, output);
|
||||
free (op);
|
||||
}
|
||||
free (key);
|
||||
}
|
||||
|
||||
static void
|
||||
complete_topic (struct app_context *ctx, struct completion *data,
|
||||
const char *word, struct strv *output)
|
||||
@@ -12497,33 +12580,30 @@ static char **
|
||||
complete_word (struct app_context *ctx, struct completion *data,
|
||||
const char *word)
|
||||
{
|
||||
// First figure out what exactly we need to complete
|
||||
bool try_commands = false;
|
||||
bool try_options = false;
|
||||
bool try_topic = false;
|
||||
bool try_nicknames = false;
|
||||
|
||||
if (data->location == 0 && completion_matches (data, 0, "/*"))
|
||||
try_commands = true;
|
||||
else if (data->location == 1 && completion_matches (data, 0, "/set"))
|
||||
try_options = true;
|
||||
else if (data->location == 1 && completion_matches (data, 0, "/help"))
|
||||
try_commands = try_options = true;
|
||||
else if (data->location == 1 && completion_matches (data, 0, "/topic"))
|
||||
try_topic = try_nicknames = true;
|
||||
else
|
||||
try_nicknames = true;
|
||||
char *initial = completion_word (data, 0);
|
||||
|
||||
// Start with a placeholder for the longest common prefix
|
||||
struct strv words = strv_make ();
|
||||
|
||||
// Add placeholder
|
||||
strv_append_owned (&words, NULL);
|
||||
|
||||
if (try_commands) complete_command (ctx, data, word, &words);
|
||||
if (try_options) complete_option (ctx, data, word, &words);
|
||||
if (try_topic) complete_topic (ctx, data, word, &words);
|
||||
if (try_nicknames) complete_nicknames (ctx, data, word, &words);
|
||||
if (data->location == 0 && *initial == '/')
|
||||
complete_command (ctx, data, word, &words);
|
||||
else if (data->location >= 1 && !strcmp (initial, "/set"))
|
||||
complete_set (ctx, data, word, &words);
|
||||
else if (data->location == 1 && !strcmp (initial, "/help"))
|
||||
{
|
||||
complete_command (ctx, data, word, &words);
|
||||
complete_option (ctx, data, word, &words);
|
||||
}
|
||||
else if (data->location == 1 && !strcmp (initial, "/topic"))
|
||||
{
|
||||
complete_topic (ctx, data, word, &words);
|
||||
complete_nicknames (ctx, data, word, &words);
|
||||
}
|
||||
else
|
||||
complete_nicknames (ctx, data, word, &words);
|
||||
|
||||
cstr_set (&initial, NULL);
|
||||
LIST_FOR_EACH (struct hook, iter, ctx->completion_hooks)
|
||||
{
|
||||
struct completion_hook *hook = (struct completion_hook *) iter;
|
||||
@@ -14064,7 +14144,7 @@ main (int argc, char *argv[])
|
||||
};
|
||||
|
||||
struct opt_handler oh =
|
||||
opt_handler_make (argc, argv, opts, NULL, "Experimental IRC client.");
|
||||
opt_handler_make (argc, argv, opts, NULL, "Terminal-based IRC client.");
|
||||
bool format_mode = false;
|
||||
|
||||
int c;
|
||||
|
||||
@@ -6,7 +6,7 @@ kike(1)
|
||||
|
||||
Name
|
||||
----
|
||||
kike - an experimental IRC daemon
|
||||
kike - IRC daemon
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
33
kike.c
33
kike.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* kike.c: the experimental IRC daemon
|
||||
* kike.c: an IRC daemon
|
||||
*
|
||||
* Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name>
|
||||
*
|
||||
@@ -614,7 +614,8 @@ struct server_context
|
||||
{
|
||||
int *listen_fds; ///< Listening socket FD's
|
||||
struct poller_fd *listen_events; ///< New connections available
|
||||
size_t n_listen_fds; ///< Number of listening sockets
|
||||
size_t listen_len; ///< Number of listening sockets
|
||||
size_t listen_alloc; ///< How many we've allocated
|
||||
|
||||
time_t started; ///< When has the server been started
|
||||
|
||||
@@ -695,7 +696,7 @@ server_context_free (struct server_context *self)
|
||||
{
|
||||
str_map_free (&self->config);
|
||||
|
||||
for (size_t i = 0; i < self->n_listen_fds; i++)
|
||||
for (size_t i = 0; i < self->listen_len; i++)
|
||||
{
|
||||
poller_fd_reset (&self->listen_events[i]);
|
||||
xclose (self->listen_fds[i]);
|
||||
@@ -746,12 +747,12 @@ irc_initiate_quit (struct server_context *ctx)
|
||||
{
|
||||
print_status ("shutting down");
|
||||
|
||||
for (size_t i = 0; i < ctx->n_listen_fds; i++)
|
||||
for (size_t i = 0; i < ctx->listen_len; i++)
|
||||
{
|
||||
poller_fd_reset (&ctx->listen_events[i]);
|
||||
xclose (ctx->listen_fds[i]);
|
||||
}
|
||||
ctx->n_listen_fds = 0;
|
||||
ctx->listen_len = 0;
|
||||
|
||||
for (struct client *iter = ctx->clients; iter; iter = iter->next)
|
||||
if (!iter->closing_link)
|
||||
@@ -3852,16 +3853,19 @@ irc_listen_resolve (struct server_context *ctx,
|
||||
int fd;
|
||||
for (gai_iter = gai_result; gai_iter; gai_iter = gai_iter->ai_next)
|
||||
{
|
||||
if (ctx->listen_len == ctx->listen_alloc)
|
||||
break;
|
||||
|
||||
if ((fd = irc_listen (gai_iter)) == -1)
|
||||
continue;
|
||||
set_blocking (fd, false);
|
||||
|
||||
struct poller_fd *event = &ctx->listen_events[ctx->n_listen_fds];
|
||||
struct poller_fd *event = &ctx->listen_events[ctx->listen_len];
|
||||
*event = poller_fd_make (&ctx->poller, fd);
|
||||
event->dispatcher = (poller_fd_fn) on_irc_client_available;
|
||||
event->user_data = ctx;
|
||||
|
||||
ctx->listen_fds[ctx->n_listen_fds++] = fd;
|
||||
ctx->listen_fds[ctx->listen_len++] = fd;
|
||||
poller_fd_set (event, POLLIN);
|
||||
}
|
||||
freeaddrinfo (gai_result);
|
||||
@@ -3882,13 +3886,20 @@ irc_setup_listen_fds (struct server_context *ctx, struct error **e)
|
||||
|
||||
struct strv ports = strv_make ();
|
||||
cstr_split (bind_port, ",", true, &ports);
|
||||
ctx->listen_fds = xcalloc (ports.len, sizeof *ctx->listen_fds);
|
||||
ctx->listen_events = xcalloc (ports.len, sizeof *ctx->listen_events);
|
||||
|
||||
// For C and simplicity's sake let's assume that the host will resolve
|
||||
// to at most two different addresses: IPv4 and IPv6 in case it is NULL
|
||||
ctx->listen_alloc = ports.len * 2;
|
||||
|
||||
ctx->listen_fds =
|
||||
xcalloc (ctx->listen_alloc, sizeof *ctx->listen_fds);
|
||||
ctx->listen_events =
|
||||
xcalloc (ctx->listen_alloc, sizeof *ctx->listen_events);
|
||||
for (size_t i = 0; i < ports.len; i++)
|
||||
irc_listen_resolve (ctx, bind_host, ports.vector[i], &gai_hints);
|
||||
strv_free (&ports);
|
||||
|
||||
if (!ctx->n_listen_fds)
|
||||
if (!ctx->listen_len)
|
||||
{
|
||||
error_set (e, "%s: %s",
|
||||
"network setup failed", "no ports to listen on");
|
||||
@@ -3991,7 +4002,7 @@ main (int argc, char *argv[])
|
||||
};
|
||||
|
||||
struct opt_handler oh =
|
||||
opt_handler_make (argc, argv, opts, NULL, "Experimental IRC daemon.");
|
||||
opt_handler_make (argc, argv, opts, NULL, "IRC daemon.");
|
||||
|
||||
int c;
|
||||
while ((c = opt_handler_get (&oh)) != -1)
|
||||
|
||||
@@ -64,12 +64,13 @@ degesch.hook_prompt (function (hook)
|
||||
local lines, cols = degesch.get_screen_size ()
|
||||
x = x .. " " .. active .. string.rep (" ", cols)
|
||||
|
||||
-- Readline seems to be broken and completely corrupts the prompt
|
||||
-- (tested on 7.0.003 Archlinux, 7.0-5 Debian buster)
|
||||
x = x:gsub("[\128-\255]", "?")
|
||||
-- Readline 7.0.003 seems to be broken and completely corrupts the prompt.
|
||||
-- However 8.0.004 seems to be fine with these, as is libedit 20191231-3.1.
|
||||
--x = x:gsub("[\128-\255]", "?")
|
||||
|
||||
-- Cut off extra characters and apply formatting, including the hack.
|
||||
-- Note that this doesn't count with full-width or zero-width characters.
|
||||
-- FIXME: this doesn't count with full-width or zero-width characters.
|
||||
-- We might want to export wcwidth() above term_from_utf8 somehow.
|
||||
local overflow = utf8.offset (x, cols - 1)
|
||||
if overflow then x = x:sub (1, overflow) end
|
||||
x = "\x01\x1b[0;4;1;38;5;16m\x1b[48;5;" .. bg_color .. "m\x02" ..
|
||||
|
||||
@@ -6,7 +6,7 @@ zyklonb(1)
|
||||
|
||||
Name
|
||||
----
|
||||
zyklonb - an experimental IRC bot
|
||||
zyklonb - modular IRC bot
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* zyklonb.c: the experimental IRC bot
|
||||
* zyklonb.c: a modular IRC bot
|
||||
*
|
||||
* Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name>
|
||||
*
|
||||
@@ -1983,7 +1983,7 @@ main (int argc, char *argv[])
|
||||
};
|
||||
|
||||
struct opt_handler oh =
|
||||
opt_handler_make (argc, argv, opts, NULL, "Experimental IRC bot.");
|
||||
opt_handler_make (argc, argv, opts, NULL, "Modular IRC bot.");
|
||||
|
||||
int c;
|
||||
while ((c = opt_handler_get (&oh)) != -1)
|
||||
|
||||
Reference in New Issue
Block a user