From 0cedce5c26e249f2a42ea1a0a390a4e09e5a199b Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Tue, 31 Dec 2019 15:49:17 -0500 Subject: Implement nick-colored output --- scoop.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 16 deletions(-) diff --git a/scoop.c b/scoop.c index f32da90..298da05 100644 --- a/scoop.c +++ b/scoop.c @@ -65,6 +65,86 @@ static const char *Outer = SQL( ORDER BY time, event ); +typedef void Format( + const char *network, const char *context, const char *time, enum Type type, + const char *nick, const char *user, const char *target, const char *message +); + +static void formatPlain( + const char *network, const char *context, const char *time, enum Type type, + const char *nick, const char *user, const char *target, const char *message +) { + (void)user; + if (!target) target = ""; + if (!message) message = ""; + printf("%s/%s: [%s] ", network, context, time); + switch (type) { + break; case Privmsg: printf("<%s> %s\n", nick, message); + break; case Notice: printf("-%s- %s\n", nick, message); + break; case Action: printf("* %s %s\n", nick, message); + break; case Join: printf("%s joined\n", nick); + break; case Part: printf("%s parted: %s\n", nick, message); + break; case Quit: printf("%s quit: %s\n", nick, message); + break; case Kick: printf("%s kicked %s: %s\n", nick, target, message); + break; case Nick: printf("%s changed nick to %s\n", nick, target); + break; case Topic: printf("%s set the topic: %s\n", nick, message); + } +} + +static const int Colors[] = { + 31, 32, 33, 34, 35, 36, 37, + 90, 91, 92, 93, 94, 95, 96, 97, +}; + +static int color(const char *user) { + if (*user == '~') user++; + uint32_t hash = 0; + for (; *user; ++user) { + hash = (hash << 5) | (hash >> 27); + hash ^= *user; + hash *= 0x27220A95; + } + return Colors[hash % ARRAY_LEN(Colors)]; +} + +static void formatColor( + const char *network, const char *context, const char *time, enum Type type, + const char *nick, const char *user, const char *target, const char *message +) { + if (!target) target = ""; + if (!message) message = ""; + printf("%s/%s: [%s] ", network, context, time); + switch (type) { + break; case Privmsg: + printf("<\33[%dm%s\33[m> %s\n", color(user), nick, message); + break; case Notice: + printf("-\33[%dm%s\33[m- %s\n", color(user), nick, message); + break; case Action: + printf("* \33[%dm%s\33[m %s\n", color(user), nick, message); + break; case Join: + printf("\33[%dm%s\33[m joined\n", color(user), nick); + break; case Part: + printf("\33[%dm%s\33[m parted: %s\n", color(user), nick, message); + break; case Quit: + printf("\33[%dm%s\33[m quit: %s\n", color(user), nick, message); + break; case Kick: + printf( + "\33[%dm%s\33[m kicked %s: %s\n", + color(user), nick, target, message + ); + break; case Nick: + printf( + "\33[%dm%s\33[m changed nick to %s\n", + color(user), nick, target + ); + break; case Topic: + printf( + "\33[%dm%s\33[m set the topic: %s\n", + color(user), nick, message + ); + } +} + static const char *TypeNames[] = { #define X(id, name) [id] = name, ENUM_TYPE @@ -203,6 +283,8 @@ int main(int argc, char *argv[]) { sqlite3_free(expand); } + Format *format = (tty ? formatColor : formatPlain); + int result; while (SQLITE_ROW == (result = sqlite3_step(stmt))) { int i = 0; @@ -214,22 +296,7 @@ int main(int argc, char *argv[]) { const char *user = (const char *)sqlite3_column_text(stmt, i++); const char *target = (const char *)sqlite3_column_text(stmt, i++); const char *message = (const char *)sqlite3_column_text(stmt, i++); - if (!target) target = ""; - if (!message) message = ""; - - // TODO: Nick coloring. - printf("%s/%s: [%s] ", network, context, time); - switch (type) { - break; case Privmsg: printf("<%s> %s\n", nick, message); - break; case Notice: printf("-%s- %s\n", nick, message); - break; case Action: printf("* %s %s\n", nick, message); - break; case Join: printf("%s joined\n", nick); - break; case Part: printf("%s parted: %s\n", nick, message); - break; case Quit: printf("%s quit: %s\n", nick, message); - break; case Kick: printf("%s kicked %s: %s\n", nick, target, message); - break; case Nick: printf("%s changed nick to %s\n", nick, target); - break; case Topic: printf("%s set the topic: %s\n", nick, message); - } + format(network, context, time, type, nick, user, target, message); } if (result != SQLITE_DONE) warnx("%s", sqlite3_errmsg(db)); -- cgit 1.4.1 >June McEnroe 2019-10-28Add quit message optionJune McEnroe 2019-10-28Specify when command is allowed in Handlers listJune McEnroe 2019-10-28Disallow PRIVMSG/NOTICE before registrationJune McEnroe 2019-10-28Move entire login flow to state and reorganize itJune McEnroe 2019-10-27Wait for SASL success before sending CAP ENDJune McEnroe 2019-10-27Only increment consumer after successful sendJune McEnroe 2019-10-27Set SO_REUSEADDR on bindsJune McEnroe 2019-10-27Output ring info on SIGINFOJune McEnroe 2019-10-27Improve client/server error messagesJune McEnroe 2019-10-27Add reload cmd to rc scriptJune McEnroe 2019-10-27Reload certificate on SIGUSR1June McEnroe 2019-10-27Drop clients on zero-length readsJune McEnroe 2019-10-27Explicitly tls_handshake new clientsJune McEnroe 2019-10-26Document rationaleJune McEnroe 2019-10-26Handle nick collisionJune McEnroe 2019-10-26Wait for AUTHENTICATE + from serverJune McEnroe 2019-10-26Respond to PING with same parameterJune McEnroe 2019-10-26Add undocumented flag to disable verificationJune McEnroe 2019-10-26Do not require RPL_ISUPPORT for stateReadyJune McEnroe 2019-10-26Implement graceful shutdownJune McEnroe 2019-10-26Require PASS before USERJune McEnroe 2019-10-26Track channel topicsJune McEnroe 2019-10-26Set AWAY when no clients are connectedJune McEnroe 2019-10-26Add flags to request TOPIC and NAMES on client connectJune McEnroe 2019-10-26OopsJune McEnroe 2019-10-26Disconnect client on unknown commandJune McEnroe 2019-10-26Allow reading sensitive information from filesJune McEnroe 2019-10-26Add rc scriptJune McEnroe 2019-10-25Add install and uninstall targetsJune McEnroe 2019-10-25Expand documentationJune McEnroe 2019-10-25Add AGPLv3 notice on client registrationJune McEnroe 2019-10-25Rename project pounceJune McEnroe