Should prepare actually do validation be able to return
CMD_RETURN_ERROR? Or would we want to run hooks even when we know the
command is going to fail?

I think struct cmd_ctx would be better than cmd_context, it matches all
the others.

Could struct cmd_q just contain a cmd_ctx rather than a pointer?
Particularly since it appears to be leaked :-).

Also I would be inclined to declare it as:

struct cmd_ctx {
        struct client           *c;
        struct window           *w;
        struct window           *w2;
        struct window_pane      *wp;
        struct window_pane      *wp2;
        ...
}

Some other stuff, mostly minor apart from cmd-queue.c. Trimmed out a lot
of context hope it is clear enough:

> +void
> +cmd_bind_key_prepare(unused struct cmd *self, unused struct cmd_q *cmdq)
> +{
> +     return;
> +}

This return is unnecessary.

> +void
> +cmd_break_pane_prepare(struct cmd *self, struct cmd_q *cmdq)
> +{
> +     struct args             *args = self->args;
> +     struct cmd_context      *cmd_ctx = cmdq->cmd_ctx;
> +
> +     cmd_ctx->wl = cmd_find_pane(cmdq, args_get(args, 't'),
> +                     &cmd_ctx->session, &cmd_ctx->wp);

Spacing looks funny.

> +void
> +cmd_display_message_prepare(struct cmd *self, struct cmd_q *cmdq)
> +{
> +     struct args             *args = self->args;
> +     struct cmd_context      *cmd_ctx = cmdq->cmd_ctx;
> +
> +     if (args_has(args, 't'))
> +             cmd_ctx->wl = cmd_find_pane(cmdq, args_get(args, 't'),
> +                             &cmd_ctx->session, &cmd_ctx->wp);

Please {}s around multiline compound statements.

> +     else
> +             cmd_ctx->wl = cmd_find_pane(cmdq, NULL, &cmd_ctx->session,
> +                             &cmd_ctx->wp);

In cmdq.c:

> +                     /*
> +                      * If we set no session via this---or the prepare() 
> function
> +                      * wasn't defined, then use the global hooks, otherwise 
> used
> +                      * the intended session's hooks when running the 
> command.
> +                      */
> +                     hooks = (cmdq->cmd_ctx->session != NULL) ?
> +                             &cmdq->cmd_ctx->session->hooks : &global_hooks;

This would be much easier to read as an if () not a ?:.

> +
> +                     /*
> +                      * For the given command in this list, look to see if
> +                      * this has any hooks.
> +                      */
> +                     xasprintf(&hook_before_name, "before-%s", 
> cmdq->cmd->entry->name);
> +                     xasprintf(&hook_after_name, "after-%s", 
> cmdq->cmd->entry->name);
> +                     hook_before = hooks_find(hooks, hook_before_name);
> +                     hook_after = hooks_find(hooks, hook_after_name);
> +
> +                     free(hook_before_name);
> +                     free(hook_after_name);

I think I would add a helper something like:

void
cmdq_run_hook(struct hooks *hooks, const char *prefix, struct cmd *cmd,
    struct cmdq *cmdq)
{
        struct hook     *h;
        char            *s;

        xasprintf(&s, "%s-%s", prefix, cmd->entry->name);
        if ((h = hooks_find(hooks, s)) != NULL)
                hooks_run(h, cmdq);
        free(s);
}

Then the changes to cmdq_continue could be much smaller.

> +
>                       cmd_print(cmdq->cmd, s, sizeof s);
>                       log_debug("cmdq %p: %s (client %d)", cmdq, s,
> -                         cmdq->client != NULL ? cmdq->client->ibuf.fd : -1);
> +                                     cmdq->client != NULL ? 
> cmdq->client->ibuf.fd : -1);
>  
>                       cmdq->time = time(NULL);
>                       cmdq->number++;
>  
>                       guard = cmdq_guard(cmdq, "begin");
> +
> +                     /* Run hooks before the command, the command itself,
> +                      * and then any hooks after it.  At the moment, hooks
> +                      * do not incur return value checking, and hence do
> +                      * not invalidate the actual command from running
> +                      * should a hook fail to do so.
> +                      */
> +                     hooks_run(hook_before, cmdq);

Eg this would just become cmdq_run_hook(hooks, "before", cmdq->cmd, cmdq).

>                       retval = cmdq->cmd->entry->exec(cmdq->cmd, cmdq);
> +                     hooks_run(hook_after, cmdq);
> +
>                       if (guard) {
>                               if (retval == CMD_RETURN_ERROR)
>                                   cmdq_guard(cmdq, "error");

> +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_ent;
> +     struct hook     *hook;
> +     char            *cause;
> +     const char      *hook_name, *hook_cmd;
> +
> +     if (args_has(args, 't'))
> +             if ((s = cmdq->cmd_ctx->session) == 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.");

Errors should not have a leading capital letter and no period.

> +             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);
> +             hooks_remove(hooks_ent, hook);
> +             return (CMD_RETURN_NORMAL);
> +     }
> +
> +     if (args->argc == 0) {
> +             cmdq_error(cmdq, "No command for hook '%s' given.", hook_name);

Here too.

> +             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) {
> +                     log_debug("Hook error: (%s)", cause);
> +                     cmdq_error(cmdq, "Hook error: (%s)", cause);

And here. Also can this log go away now?

> +                     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..c27f6d7
> --- /dev/null
> +++ b/cmd-show-hooks.c
> @@ -0,0 +1,72 @@
> +/* $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;
> +     struct cmd_context      *cmd_ctx = cmdq->cmd_ctx;
> +
> +     cmd_ctx->session = 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 hook     *hook;
> +     struct hooks    *hooks_ent;

Why not just hooks?

> +     char             tmp[BUFSIZ];
> +     size_t           used;
> +
> +     if ((s = cmdq->cmd_ctx->session) == 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);
> +             cmdq_print(cmdq, "%s", tmp);
> +     }
> +     return (CMD_RETURN_NORMAL);
> +}

------------------------------------------------------------------------------
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