Allow commands to take multiline input

master
C. McEnroe 2020-03-23 14:54:46 -04:00
parent 7ea1a416a1
commit 3cb7cc97f6
1 changed files with 48 additions and 38 deletions

View File

@ -64,14 +64,14 @@ static void splitMessage(char *cmd, uint id, char *params) {
); );
assert(overhead > 0 && overhead < 512); assert(overhead > 0 && overhead < 512);
int chunk = 512 - overhead; int chunk = 512 - overhead;
if (strlen(params) <= (size_t)chunk) { if (strlen(params) <= (size_t)chunk && !strchr(params, '\n')) {
echoMessage(cmd, id, params); echoMessage(cmd, id, params);
return; return;
} }
while (*params) { while (*params) {
int len = 0; int len = 0;
for (int n = 0; len + n <= chunk; len += n) { for (int n = 0; params[len] != '\n' && len + n <= chunk; len += n) {
n = mblen(&params[len], 1 + strlen(&params[len])); n = mblen(&params[len], 1 + strlen(&params[len]));
if (n < 0) { if (n < 0) {
n = 1; n = 1;
@ -84,6 +84,7 @@ static void splitMessage(char *cmd, uint id, char *params) {
echoMessage(cmd, id, params); echoMessage(cmd, id, params);
params[len] = ch; params[len] = ch;
params += len; params += len;
if (ch == '\n') params++;
} }
} }
@ -360,45 +361,50 @@ static void commandHelp(uint id, char *params) {
_exit(EX_UNAVAILABLE); _exit(EX_UNAVAILABLE);
} }
enum Flag {
BIT(Multiline),
BIT(Restricted),
};
static const struct Handler { static const struct Handler {
const char *cmd; const char *cmd;
Command *fn; Command *fn;
bool restricted; enum Flag flags;
} Commands[] = { } Commands[] = {
{ "/away", .fn = commandAway }, { "/away", commandAway, 0 },
{ "/ban", .fn = commandBan }, { "/ban", commandBan, 0 },
{ "/close", .fn = commandClose }, { "/close", commandClose, 0 },
{ "/copy", .fn = commandCopy, .restricted = true }, { "/copy", commandCopy, Restricted },
{ "/cs", .fn = commandCS }, { "/cs", commandCS, 0 },
{ "/debug", .fn = commandDebug, .restricted = true }, { "/debug", commandDebug, Restricted },
{ "/except", .fn = commandExcept }, { "/except", commandExcept, 0 },
{ "/exec", .fn = commandExec, .restricted = true }, { "/exec", commandExec, Multiline | Restricted },
{ "/help", .fn = commandHelp }, { "/help", commandHelp, 0 },
{ "/invex", .fn = commandInvex }, { "/invex", commandInvex, 0 },
{ "/invite", .fn = commandInvite }, { "/invite", commandInvite, 0 },
{ "/join", .fn = commandJoin, .restricted = true }, { "/join", commandJoin, Restricted },
{ "/kick", .fn = commandKick }, { "/kick", commandKick, 0 },
{ "/list", .fn = commandList }, { "/list", commandList, 0 },
{ "/me", .fn = commandMe }, { "/me", commandMe, 0 },
{ "/mode", .fn = commandMode }, { "/mode", commandMode, 0 },
{ "/move", .fn = commandMove }, { "/move", commandMove, 0 },
{ "/msg", .fn = commandMsg, .restricted = true }, { "/msg", commandMsg, Multiline | Restricted },
{ "/names", .fn = commandNames }, { "/names", commandNames, 0 },
{ "/nick", .fn = commandNick }, { "/nick", commandNick, 0 },
{ "/notice", .fn = commandNotice }, { "/notice", commandNotice, Multiline },
{ "/ns", .fn = commandNS }, { "/ns", commandNS, 0 },
{ "/open", .fn = commandOpen, .restricted = true }, { "/open", commandOpen, Restricted },
{ "/part", .fn = commandPart }, { "/part", commandPart, 0 },
{ "/query", .fn = commandQuery, .restricted = true }, { "/query", commandQuery, Restricted },
{ "/quit", .fn = commandQuit }, { "/quit", commandQuit, 0 },
{ "/quote", .fn = commandQuote, .restricted = true }, { "/quote", commandQuote, Multiline | Restricted },
{ "/say", .fn = commandPrivmsg }, { "/say", commandPrivmsg, Multiline },
{ "/topic", .fn = commandTopic }, { "/topic", commandTopic, 0 },
{ "/unban", .fn = commandUnban }, { "/unban", commandUnban, 0 },
{ "/unexcept", .fn = commandUnexcept }, { "/unexcept", commandUnexcept, 0 },
{ "/uninvex", .fn = commandUninvex }, { "/uninvex", commandUninvex, 0 },
{ "/whois", .fn = commandWhois }, { "/whois", commandWhois, 0 },
{ "/window", .fn = commandWindow }, { "/window", commandWindow, 0 },
}; };
static int compar(const void *cmd, const void *_handler) { static int compar(const void *cmd, const void *_handler) {
@ -455,10 +461,14 @@ void command(uint id, char *input) {
uiFormat(id, Warm, NULL, "No such command %s", cmd); uiFormat(id, Warm, NULL, "No such command %s", cmd);
return; return;
} }
if (self.restricted && handler->restricted) { if (self.restricted && handler->flags & Restricted) {
uiFormat(id, Warm, NULL, "Command %s is restricted", cmd); uiFormat(id, Warm, NULL, "Command %s is restricted", cmd);
return; return;
} }
if (!(handler->flags & Multiline)) {
char *nl = strchr(input, '\n');
if (nl) *nl = '\0';
}
if (input) { if (input) {
input += strspn(input, " "); input += strspn(input, " ");