On Mon, Apr 08, 2013 at 09:48:04AM +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. > --- > hooks.c | 114 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > session.c | 2 ++ > tmux.c | 2 ++ > tmux.h | 23 +++++++++++++ > 4 files changed, 141 insertions(+) > create mode 100644 hooks.c > > diff --git a/hooks.c b/hooks.c > new file mode 100644 > index 0000000..dfc4088 > --- /dev/null > +++ b/hooks.c > @@ -0,0 +1,114 @@ > +/* $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>
I don't think we need ctype.h in this file? > +#include <stdlib.h> > + Stray blank line here. > +#include <string.h> > + > +#include "tmux.h" > + > +RB_GENERATE(hooks, hook, entry, hooks_cmp); > + > +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); > + > + if (copy != NULL) > + hooks_copy(copy, hooks); I don't think this should copy - it should work like options and keep a reference to the parent struct hooks and search both (child first). This means changes to the global hooks are reflected in all sessions not just new ones. > +} > + > +void > +hooks_copy(struct hooks *src, struct hooks *dst) > +{ > + struct hook *h; > + > + RB_FOREACH(h, hooks, src) > + hooks_add(dst, h->name, h->cmdlist); > +} > + > +void > +hooks_free(struct hooks *hooks) > +{ > + struct hook *h, *h2; > + > + RB_FOREACH_SAFE(h, hooks, hooks, h2) > + hooks_remove(hooks, h); > +} > + > +void > +hooks_add(struct hooks *hooks, const char *name, struct cmd_list *cmdlist) > +{ > + struct hook *h; > + > + if ((h = hooks_find(hooks, (char *)name)) != NULL) > + hooks_remove(hooks, h); > + > + h = xcalloc(1, sizeof *h); > + h->name = xstrdup(name); > + h->cmdlist = cmdlist; > + h->cmdlist->references++; > + > + RB_INSERT(hooks, hooks, h); > +} > + > +void > +hooks_remove(struct hooks *hooks, struct hook *h) > +{ > + if (h == NULL) > + return; Is this guard necessary? > + > + RB_REMOVE(hooks, hooks, h); > + cmd_list_free(h->cmdlist); > + free(h->name); > + free(h); > +} > + > +struct hook * > +hooks_find(struct hooks *hooks, const char *name) > +{ > + struct hook h; > + > + if (name == NULL) > + return (NULL); And this? > + > + h.name = (char *)name; > + > + return (RB_FIND(hooks, hooks, &h)); > +} > + > +void > +hooks_run(struct hook *hook, struct cmd_q *cmdq) > +{ > + struct cmd *cmd; > + > + if (hook == NULL) > + return; Likewise. I tend to think this kind of guard is better outside in the places the hook could be NULL. > + > + 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 8ea91eb..662867d 100644 > --- a/tmux.c > +++ b/tmux.c > @@ -37,6 +37,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; > > @@ -321,6 +322,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 9c91d6a..096b8ce 100644 > --- a/tmux.h > +++ b/tmux.h > @@ -1075,6 +1075,14 @@ struct environ_entry { > }; > RB_HEAD(environ, environ_entry); > > +/* Hooks. */ > +struct hook { > + char *name; > + struct cmd_list *cmdlist; > + RB_ENTRY(hook) entry; > +}; > +RB_HEAD(hooks, hook); > + > /* Client session. */ > struct session_group { > TAILQ_HEAD(, session) sessions; > @@ -1100,6 +1108,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 */ > @@ -1501,6 +1510,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; > @@ -1548,6 +1558,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, 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; > @@ -1821,10 +1842,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.10.4 > > > ------------------------------------------------------------------------------ > Minimize network downtime and maximize team effectiveness. > Reduce network management and security costs.Learn how to hire > the most talented Cisco Certified professionals. Visit the > Employer Resources Portal > http://www.cisco.com/web/learning/employer_resources/index.html > _______________________________________________ > 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