commit 11443af4801fc3d79decb227372e53f13a9afad0
parent ab224b4c02cb56e79eb914db542584fc0f7ef3db
Author: hhvn <dev@hhvn.uk>
Date: Thu, 9 Dec 2021 21:46:02 +0000
commands.c config.c ui.c hirc.h struct.h: aliases
Diffstat:
5 files changed, 173 insertions(+), 3 deletions(-)
diff --git a/commands.c b/commands.c
@@ -27,6 +27,7 @@ static void command_help(struct Server *server, char *str);
static void command_echo(struct Server *server, char *str);
static void command_grep(struct Server *server, char *str);
static void command_clear(struct Server *server, char *str);
+static void command_alias(struct Server *server, char *str);
static char *command_optarg;
enum {
@@ -108,9 +109,15 @@ struct Command commands[] = {
{"clear", command_clear, {
"usage: /clear [-tmp]",
"Clear selected buffer of (temporary if -tmp) messages", NULL}},
+ {"alias", command_alias, {
+ "usage: /alias [<alias> [cmd]]",
+ " /alias -delete <alias>",
+ "Add or remove an alias that expands to a command.", NULL}},
{NULL, NULL},
};
+struct Alias *aliases = NULL;
+
static void
command_quit(struct Server *server, char *str) {
cleanup(str ? str : config_gets("misc.quitmessage"));
@@ -580,6 +587,59 @@ command_bind(struct Server *server, char *str) {
}
}
+static
+void
+command_alias(struct Server *server, char *str) {
+ struct Alias *p;
+ char *alias = NULL, *cmd = NULL;
+ int delete = 0, ret;
+ enum { opt_delete, };
+ struct CommandOpts opts[] = {
+ {"delete", CMD_NARG, opt_delete},
+ {NULL, 0, 0},
+ };
+
+ while ((ret = command_getopt(&str, opts)) != opt_done) {
+ switch (ret) {
+ case opt_error:
+ return;
+ case opt_delete:
+ delete = 1;
+ break;
+ }
+ }
+
+ if (str)
+ alias = strtok_r(str, " ", &cmd);
+
+ if (delete) {
+ if (alias_remove(alias) == -1)
+ ui_error("no such alias: '%s'", alias);
+ return;
+ }
+
+ if (!alias) {
+ hist_format(selected.history, Activity_none, HIST_SHOW|HIST_TMP|HIST_MAIN, "SELF_ALIAS_START :Aliases:");
+ for (p = aliases; p; p = p->next)
+ hist_format(selected.history, Activity_none, HIST_SHOW|HIST_TMP|HIST_MAIN, "SELF_ALIAS_LIST %s :%s", p->alias, p->cmd);
+ hist_format(selected.history, Activity_none, HIST_SHOW|HIST_TMP|HIST_MAIN, "SELF_ALIAS_END :End of aliases");
+ } else if (!cmd) {
+ for (p = aliases; p; p = p->next) {
+ if (strcmp(p->alias, alias) == 0) {
+ hist_format(selected.history, Activity_none, HIST_SHOW|HIST_TMP|HIST_MAIN, "SELF_ALIAS_START :Aliases:");
+ hist_format(selected.history, Activity_none, HIST_SHOW|HIST_TMP|HIST_MAIN, "SELF_ALIAS_LIST %s :%s", p->alias, p->cmd);
+ hist_format(selected.history, Activity_none, HIST_SHOW|HIST_TMP|HIST_MAIN, "SELF_ALIAS_END :End of aliases");
+ return;
+ }
+ }
+
+ ui_error("no such alias: '%s'", alias);
+ } else {
+ alias_add(alias, cmd);
+ }
+}
+
+
static void
command_help(struct Server *server, char *str) {
int cmdonly = 0;
@@ -773,6 +833,87 @@ command_getopt(char **str, struct CommandOpts *opts) {
return opt_error;
}
+int
+alias_add(char *alias, char *cmd) {
+ struct Alias *p;
+ char *tmp;
+
+ if (!alias || !cmd)
+ return -1;
+
+ p = malloc(sizeof(struct Alias));
+ if (*alias != '/') {
+ tmp = malloc(strlen(alias) + 2);
+ snprintf(tmp, strlen(alias) + 2, "/%s", alias);
+ p->alias = tmp;
+ } else p->alias = strdup(alias);
+ if (*cmd != '/') {
+ tmp = malloc(strlen(cmd) + 2);
+ snprintf(tmp, strlen(cmd) + 2, "/%s", cmd);
+ p->cmd = tmp;
+ } else p->cmd = strdup(cmd);
+ p->prev = NULL;
+ p->next = aliases;
+ if (aliases)
+ aliases->prev = p;
+ aliases = p;
+
+ return 0;
+}
+
+int
+alias_remove(char *alias) {
+ struct Alias *p;
+
+ if (!alias)
+ return -1;
+
+ for (p=aliases; p; p = p->next) {
+ if (strcmp(p->alias, alias) == 0) {
+ if (p->prev)
+ p->prev->next = p->next;
+ else
+ aliases = p->next;
+
+ if (p->next)
+ p->next->prev = p->prev;
+
+ free(p->alias);
+ free(p->cmd);
+ free(p);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+char *
+alias_eval(char *cmd) {
+ static char ret[8192];
+ struct Alias *p;
+ int len, rc = 0;
+ char *s;
+
+ if ((s = strchr(cmd, ' ')) != NULL)
+ len = s - cmd;
+ else
+ len = strlen(cmd);
+
+ for (p = aliases; p; p = p->next) {
+ if (p->cmd && strlen(p->alias) == len && strncmp(p->alias, cmd, len) == 0) {
+ rc += strlcpy(&ret[rc], p->cmd, sizeof(ret) - rc);
+ break;
+ }
+ }
+
+ if (!rc)
+ return cmd;
+
+ rc += strlcpy(&ret[rc], cmd + len, sizeof(ret) - rc);
+ return ret;
+}
+
void
command_eval(char *str) {
struct Command *cmdp;
@@ -780,7 +921,7 @@ command_eval(char *str) {
char *cmd;
char *s;
- s = strdup(str);
+ s = strdup(alias_eval(str));
if (*s != '/' || strncmp(s, "/ /", sizeof("/ /")) == 0) {
/* Provide a way to escape commands
@@ -793,9 +934,9 @@ command_eval(char *str) {
snprintf(msg, sizeof(msg), "PRIVMSG %s :%s", selected.channel->name, s);
ircprintf(selected.server, "%s\r\n", msg);
hist_format(selected.channel->history, Activity_self, HIST_SHOW|HIST_LOG|HIST_SELF, msg);
- } else
+ } else {
ui_error("channel not selected, message ignored", NULL);
-
+ }
return;
} else {
s++;
diff --git a/config.c b/config.c
@@ -257,6 +257,21 @@ struct Config config[] = {
.strhandle = config_redraws,
.description = {
"Format of end of /grep output", NULL}},
+ {"format.ui.alias", 1, Val_string,
+ .str = " ${1}: ${2}",
+ .strhandle = config_redraws,
+ .description = {
+ "Format of /alias output", NULL}},
+ {"format.ui.alias.start", 1, Val_string,
+ .str = "Aliases:",
+ .strhandle = config_redraws,
+ .description = {
+ "Format of header of /alias output", NULL}},
+ {"format.ui.alias.end", 1, Val_string,
+ .str = "",
+ .strhandle = config_redraws,
+ .description = {
+ "Format of footer of /alias output", NULL}},
{"format.privmsg", 1, Val_string,
.str = "%{nick:${nick}}${nick}%{o}%{=}${2}",
.strhandle = config_redraws,
diff --git a/hirc.h b/hirc.h
@@ -136,6 +136,9 @@ void ui_tls_error_(char *file, int line, struct tls *ctx, char *str);
/* commands.c */
void command_eval(char *str);
int command_getopt(char **str, struct CommandOpts *opts);
+int alias_add(char *binding, char *cmd);
+int alias_remove(char *binding);
+char * alias_eval(char *cmd);
/* config.c */
void config_get_print(char *name);
@@ -164,5 +167,6 @@ extern int readingconf;
/* commands.c */
extern struct Command commands[];
+extern struct Alias *aliases;
#endif /* H_HIRC */
diff --git a/struct.h b/struct.h
@@ -219,4 +219,11 @@ struct Keybind {
struct Keybind *next;
};
+struct Alias {
+ struct Alias *prev;
+ char *alias;
+ char *cmd;
+ struct Alias *next;
+};
+
#endif /* H_STRUCT */
diff --git a/ui.c b/ui.c
@@ -62,6 +62,9 @@ struct {
{"SELF_KEYBIND_END", "format.ui.keybind.end"},
{"SELF_GREP_START", "format.ui.grep.start"},
{"SELF_GREP_END", "format.ui.grep.end"},
+ {"SELF_ALIAS_START", "format.ui.alias.start"},
+ {"SELF_ALIAS_LIST", "format.ui.alias"},
+ {"SELF_ALIAS_END", "format.ui.alias.end"},
/* Real commands/numerics from server */
{"PRIVMSG", "format.privmsg"},
{"JOIN", "format.join"},