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

Reply via email to