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 <[email protected]>
> + *
> + * 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/tmux-users