Compare commits
5 Commits
1639235a48
...
d7b0b447b7
Author | SHA1 | Date | |
---|---|---|---|
d7b0b447b7 | |||
25ad5ae0ec | |||
10f6072da9 | |||
aceac26cbb | |||
e250ae8255 |
19
README.adoc
19
README.adoc
@ -23,15 +23,16 @@ command aliases, SOCKS proxying, SASL EXTERNAL authentication using TLS client
|
|||||||
certificates, a remote relay interface, or basic support for Lua scripting.
|
certificates, a remote relay interface, or basic support for Lua scripting.
|
||||||
As a unique bonus, you can launch a full text editor from within.
|
As a unique bonus, you can launch a full text editor from within.
|
||||||
|
|
||||||
xF
|
|
||||||
--
|
|
||||||
The X11 frontend for 'xC', making use of its networked relay interface.
|
|
||||||
It's currently in development, and is hidden behind a CMake option.
|
|
||||||
|
|
||||||
xP
|
xP
|
||||||
--
|
--
|
||||||
The web frontend for 'xC', making use of its networked relay interface.
|
The web frontend for 'xC', making use of its networked relay interface.
|
||||||
It's currently rather elementary, and can be built from within its directory.
|
So far it's quite basic, yet usable. Build it using `make` in its directory,
|
||||||
|
and run it from within the _public_ subdirectory.
|
||||||
|
|
||||||
|
xF
|
||||||
|
--
|
||||||
|
The X11 frontend for 'xC', making use of its networked relay interface.
|
||||||
|
It's currently in development, and hidden behind a CMake option.
|
||||||
|
|
||||||
xD
|
xD
|
||||||
--
|
--
|
||||||
@ -72,15 +73,15 @@ Building
|
|||||||
Build-only dependencies:
|
Build-only dependencies:
|
||||||
CMake, pkg-config, asciidoctor or asciidoc, awk, liberty (included) +
|
CMake, pkg-config, asciidoctor or asciidoc, awk, liberty (included) +
|
||||||
Common runtime dependencies: openssl +
|
Common runtime dependencies: openssl +
|
||||||
Additionally for 'xC': curses, libffi, +
|
Additionally for 'xC': curses, libffi, readline >= 6.0 or libedit >= 2013-07-12,
|
||||||
readline >= 6.0 or libedit >= 2013-07-12, lua >= 5.3 (optional) +
|
lua >= 5.3 (optional) +
|
||||||
Additionally for 'xF': x11, xft
|
Additionally for 'xF': x11, xft
|
||||||
|
|
||||||
$ git clone --recursive https://git.janouch.name/p/xK.git
|
$ git clone --recursive https://git.janouch.name/p/xK.git
|
||||||
$ mkdir xK/build
|
$ mkdir xK/build
|
||||||
$ cd xK/build
|
$ cd xK/build
|
||||||
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
-DWANT_READLINE=ON -DWANT_LIBEDIT=OFF -DWANT_LUA=ON
|
-DWANT_READLINE=ON -DWANT_LIBEDIT=OFF -DWITH_LUA=ON
|
||||||
$ make
|
$ make
|
||||||
|
|
||||||
To install the application, you can do either the usual:
|
To install the application, you can do either the usual:
|
||||||
|
1
xC-proto
1
xC-proto
@ -69,6 +69,7 @@ struct EventMessage {
|
|||||||
ERROR,
|
ERROR,
|
||||||
JOIN,
|
JOIN,
|
||||||
PART,
|
PART,
|
||||||
|
ACTION,
|
||||||
} rendition;
|
} rendition;
|
||||||
// Unix timestamp in seconds.
|
// Unix timestamp in seconds.
|
||||||
u64 when;
|
u64 when;
|
||||||
|
22
xC.c
22
xC.c
@ -1480,7 +1480,7 @@ struct formatter_item
|
|||||||
{
|
{
|
||||||
enum formatter_item_type type : 16; ///< Type of this item
|
enum formatter_item_type type : 16; ///< Type of this item
|
||||||
int attribute : 16; ///< Attribute ID or a TEXT_* mask
|
int attribute : 16; ///< Attribute ID or a TEXT_* mask
|
||||||
int color; ///< Colour
|
int color; ///< Colour ([256 << 16] | 16)
|
||||||
char *text; ///< String
|
char *text; ///< String
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1536,6 +1536,7 @@ enum buffer_line_rendition
|
|||||||
BUFFER_LINE_ERROR, ///< Error message
|
BUFFER_LINE_ERROR, ///< Error message
|
||||||
BUFFER_LINE_JOIN, ///< Join arrow
|
BUFFER_LINE_JOIN, ///< Join arrow
|
||||||
BUFFER_LINE_PART, ///< Part arrow
|
BUFFER_LINE_PART, ///< Part arrow
|
||||||
|
BUFFER_LINE_ACTION, ///< Highlighted asterisk
|
||||||
};
|
};
|
||||||
|
|
||||||
struct buffer_line
|
struct buffer_line
|
||||||
@ -3114,6 +3115,9 @@ relay_prepare_buffer_line (struct app_context *ctx, struct buffer *buffer,
|
|||||||
union relay_item_data *p = e->items = xcalloc (len * 6, sizeof *e->items);
|
union relay_item_data *p = e->items = xcalloc (len * 6, sizeof *e->items);
|
||||||
for (struct formatter_item *i = line->items; len--; i++)
|
for (struct formatter_item *i = line->items; len--; i++)
|
||||||
{
|
{
|
||||||
|
// XXX: See attr_printer_decode_color(), this is a footgun.
|
||||||
|
int16_t c16 = i->color;
|
||||||
|
int16_t c256 = i->color >> 16;
|
||||||
switch (i->type)
|
switch (i->type)
|
||||||
{
|
{
|
||||||
case FORMATTER_ITEM_TEXT:
|
case FORMATTER_ITEM_TEXT:
|
||||||
@ -3125,11 +3129,11 @@ relay_prepare_buffer_line (struct app_context *ctx, struct buffer *buffer,
|
|||||||
(p++)->kind = RELAY_ITEM_RESET;
|
(p++)->kind = RELAY_ITEM_RESET;
|
||||||
break;
|
break;
|
||||||
case FORMATTER_ITEM_FG_COLOR:
|
case FORMATTER_ITEM_FG_COLOR:
|
||||||
p->fg_color.color = i->color;
|
p->fg_color.color = c256 <= 0 ? c16 : c256;
|
||||||
(p++)->kind = RELAY_ITEM_FG_COLOR;
|
(p++)->kind = RELAY_ITEM_FG_COLOR;
|
||||||
break;
|
break;
|
||||||
case FORMATTER_ITEM_BG_COLOR:
|
case FORMATTER_ITEM_BG_COLOR:
|
||||||
p->bg_color.color = i->color;
|
p->bg_color.color = c256 <= 0 ? c16 : c256;
|
||||||
(p++)->kind = RELAY_ITEM_BG_COLOR;
|
(p++)->kind = RELAY_ITEM_BG_COLOR;
|
||||||
break;
|
break;
|
||||||
case FORMATTER_ITEM_SIMPLE:
|
case FORMATTER_ITEM_SIMPLE:
|
||||||
@ -4475,6 +4479,7 @@ buffer_line_flush (struct buffer_line *line, struct formatter *f, FILE *output,
|
|||||||
case BUFFER_LINE_ERROR: formatter_add (f, "#a=!=#r ", ATTR_ERROR); break;
|
case BUFFER_LINE_ERROR: formatter_add (f, "#a=!=#r ", ATTR_ERROR); break;
|
||||||
case BUFFER_LINE_JOIN: formatter_add (f, "#a-->#r ", ATTR_JOIN); break;
|
case BUFFER_LINE_JOIN: formatter_add (f, "#a-->#r ", ATTR_JOIN); break;
|
||||||
case BUFFER_LINE_PART: formatter_add (f, "#a<--#r ", ATTR_PART); break;
|
case BUFFER_LINE_PART: formatter_add (f, "#a<--#r ", ATTR_PART); break;
|
||||||
|
case BUFFER_LINE_ACTION: formatter_add (f, " #a*#r ", ATTR_ACTION); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (struct formatter_item *iter = line->items; iter->type; iter++)
|
for (struct formatter_item *iter = line->items; iter->type; iter++)
|
||||||
@ -4691,16 +4696,16 @@ log_full (struct app_context *ctx, struct server *s, struct buffer *buffer,
|
|||||||
#define log_outcoming_privmsg(s, buffer, prefixes, who, text) \
|
#define log_outcoming_privmsg(s, buffer, prefixes, who, text) \
|
||||||
log_server ((s), (buffer), 0, 0, "<#s#n> #m", (prefixes), (who), (text))
|
log_server ((s), (buffer), 0, 0, "<#s#n> #m", (prefixes), (who), (text))
|
||||||
#define log_outcoming_action(s, buffer, who, text) \
|
#define log_outcoming_action(s, buffer, who, text) \
|
||||||
log_server ((s), (buffer), 0, 0, " #a*#r #n #m", \
|
log_server ((s), (buffer), 0, BUFFER_LINE_ACTION, "#n #m", (who), (text))
|
||||||
ATTR_ACTION, (who), (text))
|
|
||||||
|
|
||||||
#define log_outcoming_orphan_notice(s, target, text) \
|
#define log_outcoming_orphan_notice(s, target, text) \
|
||||||
log_server_status ((s), (s)->buffer, "Notice -> #n: #m", (target), (text))
|
log_server_status ((s), (s)->buffer, "Notice -> #n: #m", (target), (text))
|
||||||
#define log_outcoming_orphan_privmsg(s, target, text) \
|
#define log_outcoming_orphan_privmsg(s, target, text) \
|
||||||
log_server_status ((s), (s)->buffer, "MSG(#n): #m", (target), (text))
|
log_server ((s), (s)->buffer, 0, BUFFER_LINE_STATUS, \
|
||||||
|
"MSG(#n): #m", (target), (text))
|
||||||
#define log_outcoming_orphan_action(s, target, text) \
|
#define log_outcoming_orphan_action(s, target, text) \
|
||||||
log_server_status ((s), (s)->buffer, "MSG(#n): #a*#r #m", (target), \
|
log_server ((s), (s)->buffer, 0, BUFFER_LINE_ACTION, \
|
||||||
ATTR_ACTION, (text))
|
"MSG(#n): #m", (target), (text))
|
||||||
|
|
||||||
#define log_ctcp_query(s, target, tag) \
|
#define log_ctcp_query(s, target, tag) \
|
||||||
log_server_status ((s), (s)->buffer, "CTCP query to #S: #S", target, tag)
|
log_server_status ((s), (s)->buffer, "CTCP query to #S: #S", target, tag)
|
||||||
@ -8763,6 +8768,7 @@ irc_process_numeric (struct server *s,
|
|||||||
if (msg->params.len == 2)
|
if (msg->params.len == 2)
|
||||||
irc_try_parse_welcome_for_userhost (s, msg->params.vector[1]);
|
irc_try_parse_welcome_for_userhost (s, msg->params.vector[1]);
|
||||||
break;
|
break;
|
||||||
|
case IRC_RPL_MOTDSTART:
|
||||||
case IRC_RPL_MOTD:
|
case IRC_RPL_MOTD:
|
||||||
if (copy.len)
|
if (copy.len)
|
||||||
irc_adjust_motd (©.vector[0]);
|
irc_adjust_motd (©.vector[0]);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
module janouch.name/xK
|
module janouch.name/xK/xP
|
||||||
|
|
||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
|
@ -79,6 +79,9 @@ body {
|
|||||||
.mark.part {
|
.mark.part {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
.mark.action {
|
||||||
|
color: darkred;
|
||||||
|
}
|
||||||
.content {
|
.content {
|
||||||
padding: .1rem .3rem;
|
padding: .1rem .3rem;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
@ -1,3 +1,40 @@
|
|||||||
|
// Copyright (c) 2022, Přemysl Eric Janouch <p@janouch.name>
|
||||||
|
// SPDX-License-Identifier: 0BSD
|
||||||
|
|
||||||
|
// --- Colours -----------------------------------------------------------------
|
||||||
|
|
||||||
|
let palette = [
|
||||||
|
'#000', '#800', '#080', '#880', '#008', '#808', '#088', '#ccc',
|
||||||
|
'#888', '#f00', '#0f0', '#ff0', '#00f', '#f0f', '#0ff', '#fff',
|
||||||
|
]
|
||||||
|
palette.length = 256
|
||||||
|
for (let i = 0; i < 216; i++) {
|
||||||
|
let r = i / 36 >> 0, g = (i / 6 >> 0) % 6, b = i % 6
|
||||||
|
r = !r ? '00' : (55 + 40 * r).toString(16)
|
||||||
|
g = !g ? '00' : (55 + 40 * g).toString(16)
|
||||||
|
b = !b ? '00' : (55 + 40 * b).toString(16)
|
||||||
|
palette[16 + i] = `#${r}${g}${b}`
|
||||||
|
}
|
||||||
|
for (let i = 0; i < 24; i++) {
|
||||||
|
let g = ('0' + (8 + i * 10).toString(16)).slice(-2)
|
||||||
|
palette[232 + i] = `#${g}${g}${g}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyColor(fg, bg, inverse) {
|
||||||
|
if (inverse)
|
||||||
|
[fg, bg] = [bg >= 0 ? bg : 15, fg >= 0 ? fg : 0]
|
||||||
|
|
||||||
|
let style = ''
|
||||||
|
if (fg >= 0)
|
||||||
|
style += `color: ${palette[fg]};`
|
||||||
|
if (bg >= 0)
|
||||||
|
style += `background-color: ${palette[bg]};`
|
||||||
|
if (style)
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Event processing -------------------------------------------------------
|
||||||
|
|
||||||
// TODO: Probably reset state on disconnect, and indicate to user.
|
// TODO: Probably reset state on disconnect, and indicate to user.
|
||||||
let socket = new WebSocket(proxy)
|
let socket = new WebSocket(proxy)
|
||||||
|
|
||||||
@ -59,6 +96,8 @@ socket.onmessage = function(event) {
|
|||||||
m.redraw()
|
m.redraw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---- UI ---------------------------------------------------------------------
|
||||||
|
|
||||||
let BufferList = {
|
let BufferList = {
|
||||||
view: vnode => {
|
view: vnode => {
|
||||||
let items = []
|
let items = []
|
||||||
@ -86,6 +125,7 @@ let Content = {
|
|||||||
case 'Error': content.push(m('span.mark.error', {}, '⚠')); break
|
case 'Error': content.push(m('span.mark.error', {}, '⚠')); break
|
||||||
case 'Join': content.push(m('span.mark.join', {}, '→')); break
|
case 'Join': content.push(m('span.mark.join', {}, '→')); break
|
||||||
case 'Part': content.push(m('span.mark.part', {}, '←')); break
|
case 'Part': content.push(m('span.mark.part', {}, '←')); break
|
||||||
|
case 'Action': content.push(m('span.mark.action', {}, '✶')); break
|
||||||
}
|
}
|
||||||
|
|
||||||
let classes = new Set()
|
let classes = new Set()
|
||||||
@ -95,22 +135,33 @@ let Content = {
|
|||||||
else
|
else
|
||||||
classes.add(c)
|
classes.add(c)
|
||||||
}
|
}
|
||||||
|
let fg = -1, bg = -1, inverse = false
|
||||||
line.items.forEach(item => {
|
line.items.forEach(item => {
|
||||||
// TODO: Colours.
|
|
||||||
switch (item.kind) {
|
switch (item.kind) {
|
||||||
case 'Text':
|
case 'Text':
|
||||||
// TODO: Detect and transform links.
|
// TODO: Detect and transform links.
|
||||||
content.push(m('span', {
|
content.push(m('span', {
|
||||||
class: Array.from(classes.keys()).join(' '),
|
class: Array.from(classes.keys()).join(' '),
|
||||||
|
style: applyColor(fg, bg, inverse),
|
||||||
}, item.text))
|
}, item.text))
|
||||||
break
|
break
|
||||||
case 'Reset':
|
case 'Reset':
|
||||||
classes.clear()
|
classes.clear()
|
||||||
|
fg = bg = -1
|
||||||
|
inverse = false
|
||||||
|
break
|
||||||
|
case 'FgColor':
|
||||||
|
fg = item.color
|
||||||
|
break
|
||||||
|
case 'BgColor':
|
||||||
|
bg = item.color
|
||||||
|
break
|
||||||
|
case 'FlipInverse':
|
||||||
|
inverse = !inverse
|
||||||
break
|
break
|
||||||
case 'FlipBold': flip('b'); break
|
case 'FlipBold': flip('b'); break
|
||||||
case 'FlipItalic': flip('i'); break
|
case 'FlipItalic': flip('i'); break
|
||||||
case 'FlipUnderline': flip('u'); break
|
case 'FlipUnderline': flip('u'); break
|
||||||
case 'FlipInverse': flip('i'); break
|
|
||||||
case 'FlipCrossedOut': flip('s'); break
|
case 'FlipCrossedOut': flip('s'); break
|
||||||
case 'FlipMonospace': flip('m'); break
|
case 'FlipMonospace': flip('m'); break
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user