I am looking forward to checking this out i was thinking of using something like this to have callbacks into ython code from other commands and this solves it! :)
On 4 November 2012 01:22, Thomas Adam <tho...@xteddy.org> wrote: > Suggested patch on how to implement before/after hook support. > --- > Makefile.am | 3 ++ > cmd-set-hook.c | 90 +++++++++++++++++++++++++++++++++++++++++++ > cmd-show-hooks.c | 62 ++++++++++++++++++++++++++++++ > cmd.c | 70 +++++++++++++++++++++++++++++++++- > hooks.c | 114 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > session.c | 2 + > tmux.c | 2 + > tmux.h | 23 +++++++++++ > 8 files changed, 365 insertions(+), 1 deletion(-) > 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 672208b..8341d9b 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -118,9 +118,11 @@ 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-buffer.c \ > cmd-show-environment.c \ > + cmd-show-hooks.c \ > cmd-show-messages.c \ > cmd-show-options.c \ > cmd-source-file.c \ > @@ -142,6 +144,7 @@ dist_tmux_SOURCES = \ > grid-utf8.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..d42ead7 > --- /dev/null > +++ b/cmd-set-hook.c > @@ -0,0 +1,90 @@ > +/* $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_ctx *); > + > +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 > +}; > + > +enum cmd_retval > +cmd_set_hook_exec(struct cmd *self, struct cmd_ctx *ctx) > +{ > + struct args *args = self->args; > + struct session *s; > + struct cmd_list *cmdlist; > + struct hooks *hooks_ent; > + struct hook *hook; > + char *cause; > + const char *hook_name, *hook_cmd; > + > + if (args_has(args, 't')) > + if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == > NULL) > + return (CMD_RETURN_ERROR); > + > + if (s == NULL && ctx->curclient != NULL) > + s = ctx->curclient->session; > + > + if ((hook_name = args_get(args, 'n')) == NULL) { > + ctx->error(ctx, "No hook name given."); > + return (CMD_RETURN_ERROR); > + } > + > + hooks_ent = args_has(args, 'g') ? &global_hooks : &s->hooks; > + > + if (s != NULL && args_has(args, 'u')) { > + hook = hooks_find(hooks_ent, (char *)hook_name); > + hook_remove(hooks_ent, hook); > + return (CMD_RETURN_NORMAL); > + } > + > + if (args->argc == 0) { > + ctx->error(ctx, "No command for hook '%s' given.", hook_name); > + return (CMD_RETURN_ERROR); > + } > + hook_cmd = args->argv[0]; > + > + if (cmd_string_parse(hook_cmd, &cmdlist, &cause) != 0) { > + if (cmdlist == NULL || cause != NULL) { > + log_debug("Hook error: (%s)", cause); > + ctx->error(ctx, "Hook error: (%s)", cause); > + return (CMD_RETURN_ERROR); > + } > + } > + > + if (cmdlist == NULL) > + return (CMD_RETURN_ERROR); > + > + hooks_add(hooks_ent, 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..08e646e > --- /dev/null > +++ b/cmd-show-hooks.c > @@ -0,0 +1,62 @@ > +/* $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_ctx *); > + > +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 > +}; > + > +enum cmd_retval > +cmd_show_hooks_exec(struct cmd *self, struct cmd_ctx *ctx) > +{ > + struct args *args = self->args; > + struct session *s; > + struct hook *hook; > + struct hooks *hooks_ent; > + struct cmd *cmd; > + char tmp[BUFSIZ]; > + size_t used; > + > + if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL) > + return (CMD_RETURN_ERROR); > + > + hooks_ent = args_has(args, 'g') ? &global_hooks : &s->hooks; > + > + RB_FOREACH(hook, hooks, hooks_ent) { > + used = xsnprintf(tmp, sizeof tmp, "%s -> ", hook->name); > + cmd_list_print(hook->cmdlist, tmp + used, (sizeof tmp) - > used); > + ctx->print(ctx, "%s", tmp); > + } > + return (CMD_RETURN_NORMAL); > +} > diff --git a/cmd.c b/cmd.c > index 4a17ddc..f88c071 100644 > --- a/cmd.c > +++ b/cmd.c > @@ -96,10 +96,12 @@ const struct cmd_entry *cmd_table[] = { > &cmd_server_info_entry, > &cmd_set_buffer_entry, > &cmd_set_environment_entry, > + &cmd_set_hook_entry, > &cmd_set_option_entry, > &cmd_set_window_option_entry, > &cmd_show_buffer_entry, > &cmd_show_environment_entry, > + &cmd_show_hooks_entry, > &cmd_show_messages_entry, > &cmd_show_options_entry, > &cmd_show_window_options_entry, > @@ -130,6 +132,10 @@ struct session *cmd_window_session(struct cmd_ctx *, > struct winlink *cmd_find_window_offset(const char *, struct session *, int > *); > int cmd_find_index_offset(const char *, struct session *, int *); > struct window_pane *cmd_find_pane_offset(const char *, struct winlink *); > +enum cmd_retval run_hook_before(struct hooks *, struct cmd *, > + struct cmd_ctx *); > +enum cmd_retval run_hook_after(struct hooks *, struct cmd *, > + struct cmd_ctx *); > > int > cmd_pack_argv(int argc, char **argv, char *buf, size_t len) > @@ -281,9 +287,71 @@ usage: > } > > enum cmd_retval > +run_hook_before(struct hooks *hooks, struct cmd *cmd, struct cmd_ctx *ctx) > +{ > + struct cmd_ctx hook_ctx; > + char *hook_name; > + enum cmd_retval retval; > + > + memcpy(&hook_ctx, ctx, sizeof hook_ctx); > + hook_ctx.cmdclient = NULL; > + xasprintf(&hook_name, "before-%s", cmd->entry->name); > + > + retval = hooks_call(hooks, hook_name, &hook_ctx); > + if (retval == CMD_RETURN_ERROR) > + log_debug("Failed to run cmd hook (before) <<%s>>", > hook_name); > + > + free (hook_name); > + return (retval); > +} > + > +enum cmd_retval > +run_hook_after(struct hooks *hooks, struct cmd *cmd, struct cmd_ctx *ctx) > +{ > + struct cmd_ctx hook_ctx; > + char *hook_name; > + enum cmd_retval retval; > + > + memcpy(&hook_ctx, ctx, sizeof hook_ctx); > + hook_ctx.cmdclient = NULL; > + xasprintf(&hook_name, "after-%s", cmd->entry->name); > + > + retval = hooks_call(hooks, hook_name, &hook_ctx); > + if (retval == CMD_RETURN_ERROR) > + log_debug("Failed to run cmd hook (after) <<%s>>", hook_name); > + > + free (hook_name); > + return (retval); > +} > + > +enum cmd_retval > cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx) > { > - return (cmd->entry->exec(cmd, ctx)); > + struct session *s = NULL; > + struct hooks *hooks; > + enum cmd_retval retval, hooks_retval; > + > + if (ctx->curclient != NULL) > + s = ctx->curclient->session; > + > + hooks = (s == NULL) ? &global_hooks : &s->hooks; > + > + /* Call any hooks set to run before the intended command. */ > + hooks_retval = run_hook_before(hooks, cmd, ctx); > + if (hooks_retval == CMD_RETURN_ERROR) > + return (hooks_retval); > + > + /* Call the intended command. */ > + if ((retval = cmd->entry->exec(cmd, ctx)) == CMD_RETURN_ERROR) > + return (retval); > + > + /* Call any hooks set to run after the intended command. */ > + hooks_retval = run_hook_after(hooks, cmd, ctx); > + if (hooks_retval == CMD_RETURN_ERROR) > + return (hooks_retval); > + > + /* Return the result of the intended command. */ > + return (retval); > } > > void > diff --git a/hooks.c b/hooks.c > new file mode 100644 > index 0000000..e4f791c > --- /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> > +#include <stdlib.h> > + > +#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); > +} > + > +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) > + hook_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) > + hook_remove(hooks, h); > + > + h = xmalloc(sizeof *h); > + h->name = xstrdup(name); > + h->cmdlist = cmdlist; > + > + RB_INSERT(hooks, hooks, h); > +} > + > +void > +hook_remove(struct hooks *hooks, struct hook *h) > +{ > + if (h == NULL) > + return; > + > + 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); > + > + h.name = (char *)name; > + > + return (RB_FIND(hooks, hooks, &h)); > +} > + > +enum cmd_retval > +hooks_call(struct hooks *hooks, const char *name, struct cmd_ctx *ctx) > +{ > + struct hook *hook; > + > + if ((hook = hooks_find(hooks, name)) != NULL) { > + log_debug("Running hook '%s'", hook->name); > + > + return (cmd_list_exec(hook->cmdlist, ctx)); > + } > + return (CMD_RETURN_NORMAL); > +} > diff --git a/session.c b/session.c > index 1f4fb30..09b44c9 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 5a773f6..23ab8f7 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; > > @@ -318,6 +319,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 c37a024..34f9616 100644 > --- a/tmux.h > +++ b/tmux.h > @@ -1074,6 +1074,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; > @@ -1098,6 +1106,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 */ > @@ -1488,6 +1497,7 @@ ARRAY_DECL(causelist, char *); > #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; > @@ -1532,6 +1542,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 hook_remove(struct hooks *, struct hook *); > +struct hook *hooks_find(struct hooks *, const char *); > +enum cmd_retval hooks_call(struct hooks *, const char *, struct > cmd_ctx *); > + > /* mode-key.c */ > extern const struct mode_key_table mode_key_tables[]; > extern struct mode_key_tree mode_key_tree_vi_edit; > @@ -1804,10 +1825,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 > > > ------------------------------------------------------------------------------ > LogMeIn Central: Instant, anywhere, Remote PC access and management. > Stay in control, update software, and manage PCs from one command center > Diagnose problems and improve visibility into emerging IT issues > Automate, monitor and manage. Do more in less time with Central > http://p.sf.net/sfu/logmein12331_d2d > _______________________________________________ > tmux-users mailing list > tmux-users@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/tmux-users ------------------------------------------------------------------------------ LogMeIn Central: Instant, anywhere, Remote PC access and management. Stay in control, update software, and manage PCs from one command center Diagnose problems and improve visibility into emerging IT issues Automate, monitor and manage. Do more in less time with Central http://p.sf.net/sfu/logmein12331_d2d _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users