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>
+
+#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;
+
+       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.");
+               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);
+               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>
+
+#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;
+
+       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>
+
+#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

Reply via email to