version 1.117, 2015/12/13 21:53:57 |
version 1.118, 2015/12/14 00:31:54 |
|
|
NULL |
NULL |
}; |
}; |
|
|
static void cmd_clear_state(struct cmd_state *); |
|
static struct client *cmd_get_state_client(struct cmd_q *, int); |
|
static int cmd_set_state_flag(struct cmd *, struct cmd_q *, char); |
|
|
|
int |
int |
cmd_pack_argv(int argc, char **argv, char *buf, size_t len) |
cmd_pack_argv(int argc, char **argv, char *buf, size_t len) |
{ |
{ |
|
|
} |
} |
|
|
static int |
static int |
cmd_set_state_flag(struct cmd *cmd, struct cmd_q *cmdq, char c) |
cmd_prepare_state_flag(struct cmd_find_state *fs, enum cmd_entry_flag flag, |
|
const char *target, struct cmd_q *cmdq) |
{ |
{ |
struct cmd_state *state = &cmdq->state; |
int targetflags, error; |
struct cmd_find_state *fsf = NULL; |
|
const char *flag; |
|
int flags = cmd->entry->flags, everything = 0; |
|
int allflags = 0, targetflags, error; |
|
struct session *s; |
|
struct window *w; |
|
struct winlink *wl; |
|
struct window_pane *wp; |
|
|
|
/* Set up state for either -t or -s. */ |
if (flag == CMD_SESSION_WITHPANE) { |
if (c == 't') { |
if (target != NULL && target[strcspn(target, ":.")] != '\0') |
fsf = &cmdq->state.tflag; |
flag = CMD_PANE; |
allflags = CMD_ALL_T; |
else |
} else if (c == 's') { |
flag = CMD_SESSION; |
fsf = &cmdq->state.sflag; |
|
allflags = CMD_ALL_S; |
|
} |
} |
|
|
/* |
switch (flag) { |
* If the command wants something and no argument is present, use the |
case CMD_NONE: |
* base command instead. |
case CMD_CLIENT: |
*/ |
case CMD_CLIENT_CANFAIL: |
flag = args_get(cmd->args, c); |
return (0); |
if (flag == NULL) { |
case CMD_SESSION: |
if ((flags & allflags) == 0) |
case CMD_SESSION_CANFAIL: |
return (0); /* doesn't care about flag */ |
case CMD_SESSION_PREFERUNATTACHED: |
cmd = cmdq->cmd; |
case CMD_SESSION_WITHPANE: |
everything = 1; |
|
flag = args_get(cmd->args, c); |
|
} |
|
|
|
/* |
|
* If no flag and the current command is allowed to fail, just skip to |
|
* fill in as much we can, otherwise continue and fail later if needed. |
|
*/ |
|
if (flag == NULL && (flags & CMD_CANFAIL)) |
|
goto complete_everything; |
|
|
|
/* Fill in state using command (current or base) flags. */ |
|
if (flags & CMD_PREFERUNATTACHED) |
|
targetflags = CMD_FIND_PREFER_UNATTACHED; |
|
else |
|
targetflags = 0; |
targetflags = 0; |
switch (cmd->entry->flags & allflags) { |
if (flag == CMD_SESSION_CANFAIL) |
case 0: |
targetflags |= CMD_FIND_QUIET; |
break; |
if (flag == CMD_SESSION_PREFERUNATTACHED) |
case CMD_SESSION_T|CMD_PANE_T: |
targetflags |= CMD_FIND_PREFER_UNATTACHED; |
case CMD_SESSION_S|CMD_PANE_S: |
|
if (flag != NULL && flag[strcspn(flag, ":.")] != '\0') { |
|
error = cmd_find_target(fsf, cmdq, flag, CMD_FIND_PANE, |
|
targetflags); |
|
if (error != 0) |
|
return (-1); |
|
} else { |
|
error = cmd_find_target(fsf, cmdq, flag, |
|
CMD_FIND_SESSION, targetflags); |
|
if (error != 0) |
|
return (-1); |
|
|
|
if (flag == NULL) { |
error = cmd_find_target(fs, cmdq, target, CMD_FIND_SESSION, |
fsf->wl = fsf->s->curw; |
|
fsf->wp = fsf->s->curw->window->active; |
|
} else { |
|
s = fsf->s; |
|
if ((w = window_find_by_id_str(flag)) != NULL) |
|
wp = w->active; |
|
else { |
|
wp = window_pane_find_by_id_str(flag); |
|
if (wp != NULL) |
|
w = wp->window; |
|
} |
|
wl = winlink_find_by_window(&s->windows, w); |
|
if (wl != NULL) { |
|
fsf->wl = wl; |
|
fsf->wp = wp; |
|
} |
|
} |
|
} |
|
break; |
|
case CMD_MOVEW_R|CMD_INDEX_T: |
|
case CMD_MOVEW_R|CMD_INDEX_S: |
|
error = cmd_find_target(fsf, cmdq, flag, CMD_FIND_SESSION, |
|
targetflags|CMD_FIND_QUIET); |
|
if (error != 0) { |
|
error = cmd_find_target(fsf, cmdq, flag, |
|
CMD_FIND_WINDOW, CMD_FIND_WINDOW_INDEX); |
|
if (error != 0) |
|
return (-1); |
|
} |
|
break; |
|
case CMD_SESSION_T: |
|
case CMD_SESSION_S: |
|
error = cmd_find_target(fsf, cmdq, flag, CMD_FIND_SESSION, |
|
targetflags); |
targetflags); |
if (error != 0) |
if (error != 0 && flag != CMD_SESSION_CANFAIL) |
return (-1); |
return (-1); |
break; |
break; |
case CMD_WINDOW_MARKED_T: |
case CMD_MOVEW_R: |
case CMD_WINDOW_MARKED_S: |
error = cmd_find_target(fs, cmdq, target, CMD_FIND_SESSION, |
targetflags |= CMD_FIND_DEFAULT_MARKED; |
CMD_FIND_QUIET); |
|
if (error == 0) |
|
break; |
|
flag = CMD_WINDOW_INDEX; |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
case CMD_WINDOW_T: |
case CMD_WINDOW: |
case CMD_WINDOW_S: |
case CMD_WINDOW_CANFAIL: |
error = cmd_find_target(fsf, cmdq, flag, CMD_FIND_WINDOW, |
case CMD_WINDOW_MARKED: |
|
case CMD_WINDOW_INDEX: |
|
targetflags = 0; |
|
if (flag == CMD_WINDOW_CANFAIL) |
|
targetflags |= CMD_FIND_QUIET; |
|
if (flag == CMD_WINDOW_MARKED) |
|
targetflags |= CMD_FIND_DEFAULT_MARKED; |
|
if (flag == CMD_WINDOW_INDEX) |
|
targetflags |= CMD_FIND_WINDOW_INDEX; |
|
|
|
error = cmd_find_target(fs, cmdq, target, CMD_FIND_WINDOW, |
targetflags); |
targetflags); |
if (error != 0) |
if (error != 0 && flag != CMD_WINDOW_CANFAIL) |
return (-1); |
return (-1); |
break; |
break; |
case CMD_PANE_MARKED_T: |
case CMD_PANE: |
case CMD_PANE_MARKED_S: |
case CMD_PANE_CANFAIL: |
targetflags |= CMD_FIND_DEFAULT_MARKED; |
case CMD_PANE_MARKED: |
/* FALLTHROUGH */ |
targetflags = 0; |
case CMD_PANE_T: |
if (flag == CMD_PANE_CANFAIL) |
case CMD_PANE_S: |
targetflags |= CMD_FIND_QUIET; |
error = cmd_find_target(fsf, cmdq, flag, CMD_FIND_PANE, |
if (flag == CMD_PANE_MARKED) |
|
targetflags |= CMD_FIND_DEFAULT_MARKED; |
|
|
|
error = cmd_find_target(fs, cmdq, target, CMD_FIND_PANE, |
targetflags); |
targetflags); |
if (error != 0) |
if (error != 0 && flag != CMD_PANE_CANFAIL) |
return (-1); |
return (-1); |
break; |
break; |
case CMD_INDEX_T: |
|
case CMD_INDEX_S: |
|
error = cmd_find_target(fsf, cmdq, flag, CMD_FIND_WINDOW, |
|
CMD_FIND_WINDOW_INDEX); |
|
if (error != 0) |
|
return (-1); |
|
break; |
|
default: |
|
fatalx("too many -%c for %s", c, cmd->entry->name); |
|
} |
} |
|
|
/* |
|
* If this is still the current command, it wants what it asked for and |
|
* nothing more. If it's the base command, fill in as much as possible |
|
* because the current command may have different flags. |
|
*/ |
|
if (!everything) |
|
return (0); |
|
|
|
complete_everything: |
|
if (fsf->s == NULL) { |
|
if (state->c != NULL) |
|
fsf->s = state->c->session; |
|
if (fsf->s == NULL) { |
|
error = cmd_find_target(fsf, cmdq, NULL, |
|
CMD_FIND_SESSION, CMD_FIND_QUIET); |
|
if (error != 0) |
|
fsf->s = NULL; |
|
} |
|
if (fsf->s == NULL) { |
|
if (flags & CMD_CANFAIL) |
|
return (0); |
|
cmdq_error(cmdq, "no current session"); |
|
return (-1); |
|
} |
|
} |
|
if (fsf->wl == NULL) { |
|
error = cmd_find_target(fsf, cmdq, flag, CMD_FIND_WINDOW, 0); |
|
if (error != 0) |
|
return (-1); |
|
} |
|
if (fsf->wp == NULL) { |
|
error = cmd_find_target(fsf, cmdq, flag, CMD_FIND_PANE, 0); |
|
if (error != 0) |
|
return (-1); |
|
} |
|
return (0); |
return (0); |
} |
} |
|
|
static struct client * |
|
cmd_get_state_client(struct cmd_q *cmdq, int quiet) |
|
{ |
|
struct cmd *cmd = cmdq->cmd; |
|
struct args *args = cmd->args; |
|
|
|
switch (cmd->entry->flags & (CMD_CLIENT_C|CMD_CLIENT_T)) { |
|
case 0: |
|
return (cmd_find_client(cmdq, NULL, 1)); |
|
case CMD_CLIENT_C: |
|
return (cmd_find_client(cmdq, args_get(args, 'c'), quiet)); |
|
case CMD_CLIENT_T: |
|
return (cmd_find_client(cmdq, args_get(args, 't'), quiet)); |
|
default: |
|
fatalx("both -t and -c for %s", cmd->entry->name); |
|
} |
|
} |
|
|
|
int |
int |
cmd_prepare_state(struct cmd *cmd, struct cmd_q *cmdq) |
cmd_prepare_state(struct cmd *cmd, struct cmd_q *cmdq) |
{ |
{ |
struct cmd_state *state = &cmdq->state; |
const struct cmd_entry *entry = cmd->entry; |
struct args *args = cmd->args; |
struct cmd_state *state = &cmdq->state; |
const char *cflag, *tflag; |
char *tmp; |
char *tmp; |
enum cmd_entry_flag flag; |
int error, quiet; |
const char *s; |
|
int error; |
|
|
tmp = cmd_print(cmd); |
tmp = cmd_print(cmd); |
log_debug("preparing state for: %s (client %p)", tmp, cmdq->client); |
log_debug("preparing state for %s (client %p)", tmp, cmdq->client); |
free(tmp); |
free(tmp); |
|
|
/* Start with an empty state. */ |
|
cmd_clear_state(state); |
cmd_clear_state(state); |
|
|
/* No error messages if can fail. */ |
flag = cmd->entry->cflag; |
quiet = 0; |
if (flag == CMD_NONE) { |
if (cmd->entry->flags & CMD_CLIENT_CANFAIL) |
flag = cmd->entry->tflag; |
quiet = 1; |
if (flag == CMD_CLIENT || flag == CMD_CLIENT_CANFAIL) |
|
s = args_get(cmd->args, 't'); |
/* |
|
* If the command wants a client and provides -c or -t, use it. If not, |
|
* try the base command instead via cmd_get_state_client. No client is |
|
* allowed if no flags, otherwise it must be available. |
|
*/ |
|
switch (cmd->entry->flags & (CMD_CLIENT_C|CMD_CLIENT_T)) { |
|
case 0: |
|
state->c = cmd_get_state_client(cmdq, 1); |
|
break; |
|
case CMD_CLIENT_C: |
|
cflag = args_get(args, 'c'); |
|
if (cflag == NULL) |
|
state->c = cmd_get_state_client(cmdq, quiet); |
|
else |
else |
state->c = cmd_find_client(cmdq, cflag, quiet); |
s = NULL; |
if (!quiet && state->c == NULL) |
} else |
|
s = args_get(cmd->args, 'c'); |
|
switch (flag) { |
|
case CMD_CLIENT: |
|
state->c = cmd_find_client(cmdq, s, 0); |
|
if (state->c == NULL) |
return (-1); |
return (-1); |
break; |
break; |
case CMD_CLIENT_T: |
|
tflag = args_get(args, 't'); |
|
if (tflag == NULL) |
|
state->c = cmd_get_state_client(cmdq, 0); |
|
else |
|
state->c = cmd_find_client(cmdq, tflag, 0); |
|
state->c = cmd_find_client(cmdq, args_get(args, 't'), quiet); |
|
if (!quiet && state->c == NULL) |
|
return (-1); |
|
break; |
|
default: |
default: |
fatalx("both -c and -t for %s", cmd->entry->name); |
state->c = cmd_find_client(cmdq, s, 1); |
|
break; |
} |
} |
|
|
error = cmd_set_state_flag(cmd, cmdq, 't'); |
s = args_get(cmd->args, 't'); |
if (error == 0) |
log_debug("preparing -t state: target %s", s == NULL ? "none" : s); |
error = cmd_set_state_flag(cmd, cmdq, 's'); |
|
return (error); |
error = cmd_prepare_state_flag(&state->tflag, entry->tflag, s, cmdq); |
|
if (error != 0) |
|
return (error); |
|
|
|
s = args_get(cmd->args, 's'); |
|
log_debug("preparing -s state: target %s", s == NULL ? "none" : s); |
|
|
|
error = cmd_prepare_state_flag(&state->sflag, entry->sflag, s, cmdq); |
|
if (error != 0) |
|
return (error); |
|
|
|
return (0); |
} |
} |
|
|
char * |
char * |