Let nitpicking commence! Apart from nitpicks this looks good, will look at the other diffs a bit later.
On Sun, Apr 14, 2013 at 05:01:36PM +0100, Thomas Adam wrote: > This adds an implementation hooks using a RB tree to store the name of the > hook and the command-list it uses. These will be accessed via commands to > add/remove hooks. > --- > Makefile.am | 3 ++ > cmd-set-hook.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++ > cmd-show-hooks.c | 71 +++++++++++++++++++++++++++++++++++ > hooks.c | 110 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > session.c | 2 + > tmux.c | 2 + > tmux.h | 27 ++++++++++++++ > 7 files changed, 315 insertions(+) > create mode 100644 cmd-set-hook.c > create mode 100644 cmd-show-hooks.c > create mode 100644 hooks.c > > diff --git a/Makefile.am b/Makefile.am > index 2ce54b1..4a0bb2d 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -121,8 +121,10 @@ dist_tmux_SOURCES = \ > cmd-server-info.c \ > cmd-set-buffer.c \ > cmd-set-environment.c \ > + cmd-set-hook.c \ > cmd-set-option.c \ > cmd-show-environment.c \ > + cmd-show-hooks.c \ > cmd-show-messages.c \ > cmd-show-options.c \ > cmd-source-file.c \ > @@ -145,6 +147,7 @@ dist_tmux_SOURCES = \ > grid-cell.c \ > grid-view.c \ > grid.c \ > + hooks.c \ > input-keys.c \ > input.c \ > job.c \ > diff --git a/cmd-set-hook.c b/cmd-set-hook.c > new file mode 100644 > index 0000000..c732856 > --- /dev/null > +++ b/cmd-set-hook.c > @@ -0,0 +1,100 @@ > +/* $Id$ */ > + > +/* > + * Copyright (c) 2012 Thomas Adam <tho...@xteddy.org> > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER > + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING > + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#include <sys/types.h> > + > +#include <ctype.h> > +#include <stdlib.h> > + > +#include <string.h> Do we need ctype.h? Also a stray blank line above <string.h>. > + > +#include "tmux.h" > + > +enum cmd_retval cmd_set_hook_exec(struct cmd *, struct cmd_q *); > +void cmd_set_hook_prepare(struct cmd *, struct cmd_q *); > + > +const struct cmd_entry cmd_set_hook_entry = { > + "set-hook", NULL, > + "gn:t:u", 0, 1, > + "[-n hook-name] [-g]" CMD_TARGET_SESSION_USAGE " [-u hook-name] > [command]", > + 0, > + NULL, > + NULL, > + cmd_set_hook_exec, > + cmd_set_hook_prepare > +}; > + > +void > +cmd_set_hook_prepare(struct cmd *self, struct cmd_q *cmdq) > +{ > + struct args *args = self->args; Looks like too many tabs here. > + > + cmdq->cmd_ctx.s = cmd_find_session(cmdq, args_get(args, 't'), 0); > +} > + > +enum cmd_retval > +cmd_set_hook_exec(struct cmd *self, struct cmd_q *cmdq) > +{ > + struct args *args = self->args; > + struct session *s; > + struct cmd_list *cmdlist; > + struct hooks *hooks; > + struct hook *hook; > + char *cause; > + const char *hook_name, *hook_cmd; > + > + s = cmdq->cmd_ctx.s; > + > + if (args_has(args, 't') && s == NULL) > + return (CMD_RETURN_ERROR); > + > + if (s == NULL && cmdq->client != NULL) > + s = cmdq->client->session; > + > + if ((hook_name = args_get(args, 'n')) == NULL) { > + cmdq_error(cmdq, "No hook name given."); No capital letter and no period please. > + return (CMD_RETURN_ERROR); > + } > + > + hooks = args_has(args, 'g') ? &global_hooks : &s->hooks; > + > + if (s != NULL && args_has(args, 'u')) { > + if ((hook = hooks_find(hooks, (char *)hook_name)) != NULL) > + hooks_remove(hooks, hook); > + return (CMD_RETURN_NORMAL); > + } > + > + if (args->argc == 0) { > + cmdq_error(cmdq, "No command for hook '%s' given.", hook_name); And here. > + return (CMD_RETURN_ERROR); > + } > + hook_cmd = args->argv[0]; > + > + if (cmd_string_parse(hook_cmd, &cmdlist, NULL, 0, &cause) != 0) { > + if (cmdlist == NULL || cause != NULL) { > + cmdq_error(cmdq, "Hook error: (%s)", cause); > + return (CMD_RETURN_ERROR); > + } > + } > + > + if (cmdlist == NULL) > + return (CMD_RETURN_ERROR); > + > + hooks_add(hooks, hook_name, cmdlist); > + return (CMD_RETURN_NORMAL); > +} > diff --git a/cmd-show-hooks.c b/cmd-show-hooks.c > new file mode 100644 > index 0000000..b98dbe5 > --- /dev/null > +++ b/cmd-show-hooks.c > @@ -0,0 +1,71 @@ > +/* $Id$ */ > + > +/* > + * Copyright (c) 2012 Thomas Adam <tho...@xteddy.org> > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER > + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING > + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#include <sys/types.h> > + > +#include <ctype.h> > +#include <stdlib.h> > + > +#include <string.h> Same. > + > +#include "tmux.h" > + > +enum cmd_retval cmd_show_hooks_exec(struct cmd *, struct cmd_q *); > +void cmd_show_hooks_prepare(struct cmd *, struct cmd_q *); > + > +const struct cmd_entry cmd_show_hooks_entry = { > + "show-hooks", NULL, > + "gt:", 0, 1, > + "[-g] " CMD_TARGET_SESSION_USAGE, > + 0, > + NULL, > + NULL, > + cmd_show_hooks_exec, > + cmd_show_hooks_prepare > +}; > + > +void > +cmd_show_hooks_prepare(struct cmd *self, struct cmd_q *cmdq) > +{ > + struct args *args = self->args; Same :-). > + > + cmdq->cmd_ctx.s = cmd_find_session(cmdq, args_get(args, 't'), 0); > +} > + > +enum cmd_retval > +cmd_show_hooks_exec(struct cmd *self, struct cmd_q *cmdq) > +{ > + struct args *args = self->args; > + struct session *s; > + struct hooks *hooks; > + struct hook *hook; > + char tmp[BUFSIZ]; > + size_t used; > + > + if ((s = cmdq->cmd_ctx.s) == NULL) > + return (CMD_RETURN_ERROR); > + > + hooks = args_has(args, 'g') ? &global_hooks : &s->hooks; > + > + RB_FOREACH(hook, hooks_tree, &hooks->tree) { > + used = xsnprintf(tmp, sizeof tmp, "%s -> ", hook->name); > + cmd_list_print(hook->cmdlist, tmp + used, (sizeof tmp) - used); > + cmdq_print(cmdq, "%s", tmp); > + } > + return (CMD_RETURN_NORMAL); > +} > diff --git a/hooks.c b/hooks.c > new file mode 100644 > index 0000000..8fdcf00 > --- /dev/null > +++ b/hooks.c > @@ -0,0 +1,110 @@ > +/* $Id$ */ > + > +/* > + * Copyright (c) 2012 Thomas Adam <tho...@xteddy.org> > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER > + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING > + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#include <sys/types.h> > + > +#include <stdlib.h> > + > +#include <string.h> No blank line between these two. > + > +#include "tmux.h" > + > +RB_GENERATE(hooks_tree, hook, entry, hooks_cmp); > + > +struct hook *hooks_find1(struct hooks *, const char *); > + > +int > +hooks_cmp(struct hook *hook1, struct hook *hook2) > +{ > + return (strcmp(hook1->name, hook2->name)); > +} > + > +void > +hooks_init(struct hooks *hooks, struct hooks *copy) > +{ > + RB_INIT(&hooks->tree); > + hooks->parent = copy; > +} > + > +void > +hooks_free(struct hooks *hooks) > +{ > + struct hook *h, *h2; > + > + RB_FOREACH_SAFE(h, hooks_tree, &hooks->tree, h2) > + hooks_remove(hooks, h); > +} > + > +void > +hooks_add(struct hooks *hooks, const char *name, struct cmd_list *cmdlist) > +{ > + struct hook *h; > + > + if ((h = hooks_find1(hooks, name)) != NULL) > + hooks_remove(hooks, h); > + > + h = xcalloc(1, sizeof *h); > + h->name = xstrdup(name); > + h->cmdlist = cmdlist; > + h->cmdlist->references++; > + > + RB_INSERT(hooks_tree, &hooks->tree, h); > +} > + > +void > +hooks_remove(struct hooks *hooks, struct hook *h) > +{ > + RB_REMOVE(hooks_tree, &hooks->tree, h); > + cmd_list_free(h->cmdlist); > + free(h->name); > + free(h); > +} > + > +struct hook * > +hooks_find1(struct hooks *hooks, const char *name) > +{ > + struct hook h; > + > + h.name = (char *) name; > + return (RB_FIND(hooks_tree, &hooks->tree, &h)); > +} > + > +struct hook * > +hooks_find(struct hooks *hooks, const char *name) > +{ > + struct hook h, *he; > + > + h.name = (char *) name; > + he = RB_FIND(hooks_tree, &hooks->tree, &h); > + while (he == NULL) { > + hooks = hooks->parent; > + if (hooks == NULL) > + break; > + he = RB_FIND(hooks_tree, &hooks->tree, &h); > + } > + return (he); > +} > + > +void > +hooks_run(struct hook *hook, struct cmd_q *cmdq) > +{ > + struct cmd *cmd; > + > + TAILQ_FOREACH(cmd, &hook->cmdlist->list, qentry) > + cmd->entry->exec(cmd, cmdq); > +} > diff --git a/session.c b/session.c > index 74eb06a..b75d459 100644 > --- a/session.c > +++ b/session.c > @@ -104,6 +104,7 @@ session_create(const char *name, const char *cmd, const > char *cwd, > TAILQ_INIT(&s->lastw); > RB_INIT(&s->windows); > > + hooks_init(&s->hooks, &global_hooks); > options_init(&s->options, &global_s_options); > environ_init(&s->environ); > if (env != NULL) > @@ -160,6 +161,7 @@ session_destroy(struct session *s) > session_group_remove(s); > environ_free(&s->environ); > options_free(&s->options); > + hooks_free(&s->hooks); > > while (!TAILQ_EMPTY(&s->lastw)) > winlink_stack_remove(&s->lastw, TAILQ_FIRST(&s->lastw)); > diff --git a/tmux.c b/tmux.c > index e8fd98b..8aa6089 100644 > --- a/tmux.c > +++ b/tmux.c > @@ -39,6 +39,7 @@ struct options global_options; /* server > options */ > struct options global_s_options; /* session options */ > struct options global_w_options; /* window options */ > struct environ global_environ; > +struct hooks global_hooks; > > struct event_base *ev_base; > > @@ -322,6 +323,7 @@ main(int argc, char **argv) > flags |= IDENTIFY_UTF8; > } > > + hooks_init(&global_hooks, NULL); > environ_init(&global_environ); > for (var = environ; *var != NULL; var++) > environ_put(&global_environ, *var); > diff --git a/tmux.h b/tmux.h > index f0b9edf..22d0964 100644 > --- a/tmux.h > +++ b/tmux.h > @@ -1075,6 +1075,18 @@ struct environ_entry { > }; > RB_HEAD(environ, environ_entry); > > +/* Hooks. */ > +struct hook { > + char *name; > + struct cmd_list *cmdlist; > + RB_ENTRY(hook) entry; > +}; > + > +struct hooks { > + RB_HEAD(hooks_tree, hook) tree; > + struct hooks *parent; > +}; > + > /* Client session. */ > struct session_group { > TAILQ_HEAD(, session) sessions; > @@ -1100,6 +1112,7 @@ struct session { > struct winlink_stack lastw; > struct winlinks windows; > > + struct hooks hooks; > struct options options; > > #define SESSION_UNATTACHED 0x1 /* not attached to any clients */ > @@ -1500,6 +1513,7 @@ RB_HEAD(format_tree, format_entry); > #define CMD_BUFFER_USAGE "[-b buffer-index]" > > /* tmux.c */ > +extern struct hooks global_hooks; > extern struct options global_options; > extern struct options global_s_options; > extern struct options global_w_options; > @@ -1547,6 +1561,17 @@ void format_winlink( > void format_window_pane(struct format_tree *, struct window_pane *); > void format_paste_buffer(struct format_tree *, struct paste_buffer > *); > > +/* hooks.c */ > +int hooks_cmp(struct hook *, struct hook *); > +RB_PROTOTYPE(hooks_tree, hook, entry, hooks_cmp); > +void hooks_init(struct hooks *, struct hooks *); > +void hooks_free(struct hooks *); > +void hooks_add(struct hooks *, const char *, struct cmd_list *); > +void hooks_copy(struct hooks *, struct hooks *); > +void hooks_remove(struct hooks *, struct hook *); > +void hooks_run(struct hook *, struct cmd_q *); > +struct hook *hooks_find(struct hooks *, const char *); > + > /* mode-key.c */ > extern const struct mode_key_table mode_key_tables[]; > extern struct mode_key_tree mode_key_tree_vi_edit; > @@ -1820,10 +1845,12 @@ extern const struct cmd_entry cmd_send_prefix_entry; > extern const struct cmd_entry cmd_server_info_entry; > extern const struct cmd_entry cmd_set_buffer_entry; > extern const struct cmd_entry cmd_set_environment_entry; > +extern const struct cmd_entry cmd_set_hook_entry; > extern const struct cmd_entry cmd_set_option_entry; > extern const struct cmd_entry cmd_set_window_option_entry; > extern const struct cmd_entry cmd_show_buffer_entry; > extern const struct cmd_entry cmd_show_environment_entry; > +extern const struct cmd_entry cmd_show_hooks_entry; > extern const struct cmd_entry cmd_show_messages_entry; > extern const struct cmd_entry cmd_show_options_entry; > extern const struct cmd_entry cmd_show_window_options_entry; > -- > 1.7.11.4 > > > ------------------------------------------------------------------------------ > Precog is a next-generation analytics platform capable of advanced > analytics on semi-structured data. The platform includes APIs for building > apps and a phenomenal toolset for data science. Developers can use > our toolset for easy data analysis & visualization. Get a free account! > http://www2.precog.com/precogplatform/slashdotnewsletter > _______________________________________________ > tmux-users mailing list > tmux-users@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/tmux-users ------------------------------------------------------------------------------ Precog is a next-generation analytics platform capable of advanced analytics on semi-structured data. The platform includes APIs for building apps and a phenomenal toolset for data science. Developers can use our toolset for easy data analysis & visualization. Get a free account! http://www2.precog.com/precogplatform/slashdotnewsletter _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users