mirror of
https://github.com/tmux/tmux.git
synced 2026-07-03 10:12:31 +00:00
Add invoke API.
This commit is contained in:
@@ -103,6 +103,7 @@ dist_tmux_SOURCES = \
|
||||
cmd-find-window.c \
|
||||
cmd-find.c \
|
||||
cmd-if-shell.c \
|
||||
cmd-invoke.c \
|
||||
cmd-join-pane.c \
|
||||
cmd-kill-pane.c \
|
||||
cmd-kill-server.c \
|
||||
|
||||
488
cmd-invoke.c
Normal file
488
cmd-invoke.c
Normal file
@@ -0,0 +1,488 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2026 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
*
|
||||
* 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 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 <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
#include "tmux-parser.h"
|
||||
|
||||
/* One frame in the parse tree stack. */
|
||||
struct cmd_invoke_frame {
|
||||
struct cmd_parse_node *node;
|
||||
struct cmd_parse_node *next;
|
||||
struct cmd_parse_node *end;
|
||||
};
|
||||
|
||||
/* Shared state for a parsed command tree invocation. */
|
||||
struct cmd_invoke_state {
|
||||
u_int references;
|
||||
struct cmd_parse_tree *tree;
|
||||
|
||||
struct cmd_invoke_frame *stack;
|
||||
u_int nstack;
|
||||
|
||||
enum cmd_retval last;
|
||||
int have_last;
|
||||
|
||||
int argc;
|
||||
char **argv;
|
||||
int parse_flags;
|
||||
char *file;
|
||||
};
|
||||
|
||||
static void cmd_invoke_push(struct cmd_invoke_state *,
|
||||
struct cmd_parse_node *, struct cmd_parse_node *,
|
||||
struct cmd_parse_node *);
|
||||
static struct cmd_parse_node *cmd_invoke_next(struct cmd_invoke_state *);
|
||||
static void cmd_invoke_skip_sequence(struct cmd_invoke_state *);
|
||||
static int cmd_invoke_expand_string(struct cmdq_item *,
|
||||
struct cmd_invoke_state *, struct cmd_parse_node *,
|
||||
char **);
|
||||
static int cmd_invoke_assignment(struct cmdq_item *,
|
||||
struct cmd_invoke_state *, struct cmd_parse_node *);
|
||||
static int cmd_invoke_if(struct cmdq_item *, struct cmd_invoke_state *,
|
||||
struct cmd_parse_node *);
|
||||
static struct cmd *cmd_invoke_build_command(struct cmdq_item *,
|
||||
struct cmd_invoke_state *, struct cmd_parse_node *);
|
||||
|
||||
/* Push a node's child range onto the traversal stack. */
|
||||
static void
|
||||
cmd_invoke_push(struct cmd_invoke_state *is, struct cmd_parse_node *node,
|
||||
struct cmd_parse_node *first, struct cmd_parse_node *end)
|
||||
{
|
||||
u_int n = is->nstack + 1;
|
||||
|
||||
is->stack = xreallocarray(is->stack, n, sizeof *is->stack);
|
||||
is->stack[is->nstack].node = node;
|
||||
is->stack[is->nstack].next = first;
|
||||
is->stack[is->nstack].end = end;
|
||||
is->nstack = n;
|
||||
}
|
||||
|
||||
/* Return the next node to execute from the traversal stack. */
|
||||
static struct cmd_parse_node *
|
||||
cmd_invoke_next(struct cmd_invoke_state *is)
|
||||
{
|
||||
struct cmd_invoke_frame *frame;
|
||||
struct cmd_parse_node *node;
|
||||
|
||||
for (;;) {
|
||||
if (is->nstack == 0)
|
||||
return (NULL);
|
||||
frame = &is->stack[is->nstack - 1];
|
||||
if (frame->next != NULL && frame->next != frame->end)
|
||||
break;
|
||||
is->nstack--;
|
||||
}
|
||||
|
||||
node = frame->next;
|
||||
frame->next = cmd_parse_node_next(node);
|
||||
return (node);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip the rest of the active sequence after a command failure. Failure scope
|
||||
* is the active CMD_PARSE_SEQUENCE. Discard nested frames and advance only as
|
||||
* far as the end of that sequence.
|
||||
*/
|
||||
static void
|
||||
cmd_invoke_skip_sequence(struct cmd_invoke_state *is)
|
||||
{
|
||||
enum cmd_parse_node_type type;
|
||||
u_int i;
|
||||
|
||||
for (i = is->nstack; i > 0; i--) {
|
||||
type = cmd_parse_node_type(is->stack[i - 1].node);
|
||||
if (type == CMD_PARSE_SEQUENCE) {
|
||||
is->stack[i - 1].next = is->stack[i - 1].end;
|
||||
is->nstack = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
is->have_last = 0;
|
||||
}
|
||||
|
||||
/* Append a string to a dynamically allocated buffer. */
|
||||
static void
|
||||
cmd_invoke_append(char **buf, size_t *len, const char *s)
|
||||
{
|
||||
size_t slen;
|
||||
|
||||
if (s != NULL) {
|
||||
slen = strlen(s);
|
||||
*buf = xrealloc(*buf, *len + slen + 1);
|
||||
memcpy(*buf + *len, s, slen + 1);
|
||||
*len += slen;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look up an environment variable. */
|
||||
static const char *
|
||||
cmd_invoke_getenv(struct cmdq_item *item, const char *name)
|
||||
{
|
||||
struct client *c = cmdq_get_client(item);
|
||||
struct environ_entry *envent;
|
||||
|
||||
if (c != NULL && c->environ != NULL) {
|
||||
envent = environ_find(c->environ, name);
|
||||
if (envent != NULL && envent->value != NULL)
|
||||
return (envent->value);
|
||||
}
|
||||
envent = environ_find(global_environ, name);
|
||||
if (envent != NULL && envent->value != NULL)
|
||||
return (envent->value);
|
||||
return ("");
|
||||
}
|
||||
|
||||
/* Resolve a tilde expansion to a home directory. */
|
||||
static const char *
|
||||
cmd_invoke_tilde(const char *name)
|
||||
{
|
||||
struct passwd *pw;
|
||||
|
||||
if (name == NULL || *name == '\0')
|
||||
return (find_home());
|
||||
if ((pw = getpwnam(name)) == NULL)
|
||||
return ("");
|
||||
return (pw->pw_dir);
|
||||
}
|
||||
|
||||
/* Expand a parsed string node into an argv string. */
|
||||
static int
|
||||
cmd_invoke_expand_string(struct cmdq_item *item, struct cmd_invoke_state *is,
|
||||
struct cmd_parse_node *node, char **out)
|
||||
{
|
||||
struct cmd_parse_node *child;
|
||||
const char *s, *value;
|
||||
char *buf = NULL, *new;
|
||||
size_t len = 0;
|
||||
int i;
|
||||
|
||||
child = cmd_parse_node_first_child(node);
|
||||
while (child != NULL) {
|
||||
value = cmd_parse_node_value(child);
|
||||
switch (cmd_parse_node_type(child)) {
|
||||
case CMD_PARSE_TEXT:
|
||||
s = value;
|
||||
break;
|
||||
case CMD_PARSE_ENVIRONMENT:
|
||||
s = cmd_invoke_getenv(item, value);
|
||||
break;
|
||||
case CMD_PARSE_TILDE:
|
||||
s = cmd_invoke_tilde(value);
|
||||
break;
|
||||
default:
|
||||
fatalx("unexpected node type in string");
|
||||
}
|
||||
cmd_invoke_append(&buf, &len, s);
|
||||
child = cmd_parse_node_next(child);
|
||||
}
|
||||
if (buf == NULL)
|
||||
buf = xstrdup("");
|
||||
for (i = 0; i < is->argc; i++) {
|
||||
new = cmd_template_replace(buf, is->argv[i], i + 1);
|
||||
free(buf);
|
||||
buf = new;
|
||||
}
|
||||
*out = buf;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Execute an assignment node by updating the environment. */
|
||||
static int
|
||||
cmd_invoke_assignment(struct cmdq_item *item, struct cmd_invoke_state *is,
|
||||
struct cmd_parse_node *node)
|
||||
{
|
||||
struct cmd_parse_node *value;
|
||||
const char *name;
|
||||
char *expanded;
|
||||
int flags = 0;
|
||||
|
||||
value = cmd_parse_node_first_child(node);
|
||||
if (value == NULL)
|
||||
return (-1);
|
||||
if (cmd_invoke_expand_string(item, is, value, &expanded) != 0)
|
||||
return (-1);
|
||||
|
||||
name = cmd_parse_node_value(node);
|
||||
if (cmd_parse_node_type(node) == CMD_PARSE_HIDDEN_ASSIGN)
|
||||
flags |= ENVIRON_HIDDEN;
|
||||
environ_set(global_environ, name, flags, "%s", expanded);
|
||||
free(expanded);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Expand and evaluate a conditional expression. */
|
||||
static int
|
||||
cmd_invoke_is_true(struct cmdq_item *item,
|
||||
struct cmd_invoke_state *is, struct cmd_parse_node *node, int *result)
|
||||
{
|
||||
struct format_tree *ft;
|
||||
char *s, *expanded;
|
||||
|
||||
if (cmd_invoke_expand_string(item, is, node, &s) != 0)
|
||||
return (-1);
|
||||
ft = format_create_from_target(item);
|
||||
|
||||
expanded = format_expand(ft, s);
|
||||
*result = format_true(expanded);
|
||||
free(expanded);
|
||||
|
||||
format_free(ft);
|
||||
free(s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Push the selected conditional branch onto the traversal stack. */
|
||||
static void
|
||||
cmd_invoke_push_branch(struct cmd_invoke_state *is,
|
||||
struct cmd_parse_node *node, struct cmd_parse_node *first)
|
||||
{
|
||||
cmd_invoke_push(is, node, first, NULL);
|
||||
}
|
||||
|
||||
/* Select and queue the branch for a conditional node. */
|
||||
static int
|
||||
cmd_invoke_if(struct cmdq_item *item, struct cmd_invoke_state *is,
|
||||
struct cmd_parse_node *node)
|
||||
{
|
||||
struct cmd_parse_node *child, *first, *next;
|
||||
int r;
|
||||
|
||||
next = cmd_parse_node_first_child(node);
|
||||
if (next == NULL)
|
||||
return (0);
|
||||
first = cmd_parse_node_next(next);
|
||||
if (cmd_invoke_is_true(item, is, next, &r) != 0)
|
||||
return (-1);
|
||||
if (r) {
|
||||
cmd_invoke_push_branch(is, node, first);
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (child = first; child != NULL; child = cmd_parse_node_next(child)) {
|
||||
switch (cmd_parse_node_type(child)) {
|
||||
case CMD_PARSE_ELIF:
|
||||
next = cmd_parse_node_first_child(child);
|
||||
if (next == NULL)
|
||||
break;
|
||||
if (cmd_invoke_is_true(item, is, next, &r) != 0)
|
||||
return (-1);
|
||||
if (r) {
|
||||
cmd_invoke_push_branch(is, child, next);
|
||||
return (0);
|
||||
}
|
||||
break;
|
||||
case CMD_PARSE_ELSE:
|
||||
next = cmd_parse_node_first_child(child);
|
||||
cmd_invoke_push_branch(is, child, next);
|
||||
return (0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Build one command from a parsed command node. */
|
||||
static struct cmd *
|
||||
cmd_invoke_build_command(struct cmdq_item *item, struct cmd_invoke_state *is,
|
||||
struct cmd_parse_node *node)
|
||||
{
|
||||
struct cmd_parse_node *child;
|
||||
struct args_value *values = NULL;
|
||||
struct cmd *cmd;
|
||||
char *cause = NULL;
|
||||
u_int count = 0, i;
|
||||
|
||||
child = cmd_parse_node_first_child(node);
|
||||
while (child != NULL) {
|
||||
values = xreallocarray(values, count + 1, sizeof *values);
|
||||
memset(&values[count], 0, sizeof values[count]);
|
||||
switch (cmd_parse_node_type(child)) {
|
||||
case CMD_PARSE_STRING:
|
||||
values[count].type = ARGS_STRING;
|
||||
if (cmd_invoke_expand_string(item, is, child,
|
||||
&values[count].string) != 0)
|
||||
goto fail;
|
||||
break;
|
||||
case CMD_PARSE_COMMANDS:
|
||||
values[count].type = ARGS_COMMANDS;
|
||||
values[count].cmdparse = child;
|
||||
break;
|
||||
default:
|
||||
fatalx("unexpected node type in command");
|
||||
}
|
||||
count++;
|
||||
child = cmd_parse_node_next(child);
|
||||
}
|
||||
|
||||
cmd = cmd_parse(values, count, is->file, cmd_parse_node_line(node),
|
||||
is->parse_flags, &cause);
|
||||
if (cmd == NULL) {
|
||||
cmdq_error(item, "%s", cause);
|
||||
free(cause);
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; i < count; i++) {
|
||||
if (values[i].type == ARGS_STRING)
|
||||
free(values[i].string);
|
||||
}
|
||||
free(values);
|
||||
return (cmd);
|
||||
|
||||
fail:
|
||||
for (i = 0; i < count; i++) {
|
||||
if (values[i].type == ARGS_STRING)
|
||||
free(values[i].string);
|
||||
}
|
||||
free(values);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Create the first invoke queue item for a parsed tree. */
|
||||
struct cmdq_item *
|
||||
cmd_invoke_get(struct cmd_parse_tree *tree, struct cmdq_state *state, int argc,
|
||||
char **argv)
|
||||
{
|
||||
struct cmd_invoke_state *is;
|
||||
struct cmd_parse_node *root = cmd_parse_root(tree), *first;
|
||||
struct cmdq_item *item;
|
||||
int i;
|
||||
|
||||
is = xcalloc(1, sizeof *is);
|
||||
is->references = 1;
|
||||
is->tree = cmd_parse_add_ref(tree);
|
||||
|
||||
is->argc = argc;
|
||||
if (argc != 0) {
|
||||
is->argv = xreallocarray(NULL, argc, sizeof *is->argv);
|
||||
for (i = 0; i < argc; i++)
|
||||
is->argv[i] = xstrdup(argv[i]);
|
||||
}
|
||||
|
||||
first = cmd_parse_node_first_child(root);
|
||||
cmd_invoke_push(is, root, first, NULL);
|
||||
|
||||
item = cmdq_get_invoke(is, state);
|
||||
cmd_invoke_state_free(is);
|
||||
return (item);
|
||||
}
|
||||
|
||||
/* Add a reference to shared invoke state. */
|
||||
struct cmd_invoke_state *
|
||||
cmd_invoke_state_add_ref(struct cmd_invoke_state *is)
|
||||
{
|
||||
is->references++;
|
||||
return (is);
|
||||
}
|
||||
|
||||
/* Release a reference to shared invoke state. */
|
||||
void
|
||||
cmd_invoke_state_free(struct cmd_invoke_state *is)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (is == NULL)
|
||||
return;
|
||||
if (--is->references != 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < is->argc; i++)
|
||||
free(is->argv[i]);
|
||||
free(is->argv);
|
||||
|
||||
cmd_parse_free(is->tree);
|
||||
free(is->file);
|
||||
free(is->stack);
|
||||
free(is);
|
||||
}
|
||||
|
||||
/* Record the result from the last command item. */
|
||||
void
|
||||
cmd_invoke_result(struct cmd_invoke_state *is, enum cmd_retval retval)
|
||||
{
|
||||
is->last = retval;
|
||||
is->have_last = 1;
|
||||
}
|
||||
|
||||
/* Fire an invoke item and queue the next command plus continuation. */
|
||||
enum cmd_retval
|
||||
cmd_invoke_fire(struct cmdq_item *item, struct cmd_invoke_state *is)
|
||||
{
|
||||
struct cmd_parse_node *node;
|
||||
struct cmdq_item *new_item, *next;
|
||||
struct cmdq_state *state;
|
||||
struct cmd *cmd;
|
||||
|
||||
if (is->have_last && is->last == CMD_RETURN_ERROR)
|
||||
cmd_invoke_skip_sequence(is);
|
||||
else
|
||||
is->have_last = 0;
|
||||
|
||||
for (;;) {
|
||||
node = cmd_invoke_next(is);
|
||||
if (node == NULL)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
switch (cmd_parse_node_type(node)) {
|
||||
case CMD_PARSE_ROOT:
|
||||
case CMD_PARSE_SEQUENCE:
|
||||
cmd_invoke_push(is, node,
|
||||
cmd_parse_node_first_child(node), NULL);
|
||||
break;
|
||||
case CMD_PARSE_ASSIGN:
|
||||
case CMD_PARSE_HIDDEN_ASSIGN:
|
||||
if (cmd_invoke_assignment(item, is, node) != 0)
|
||||
return (CMD_RETURN_ERROR);
|
||||
break;
|
||||
case CMD_PARSE_IF:
|
||||
if (cmd_invoke_if(item, is, node) != 0)
|
||||
return (CMD_RETURN_ERROR);
|
||||
break;
|
||||
case CMD_PARSE_ELIF:
|
||||
case CMD_PARSE_ELSE:
|
||||
break;
|
||||
case CMD_PARSE_COMMAND:
|
||||
cmd = cmd_invoke_build_command(item, is, node);
|
||||
if (cmd == NULL)
|
||||
return (CMD_RETURN_ERROR);
|
||||
|
||||
/*
|
||||
* Queue one command followed by this walker. WAIT and
|
||||
* command-inserted items therefore run before resume.
|
||||
*/
|
||||
state = cmdq_get_state(item);
|
||||
new_item = cmdq_get_one_command(cmd, state, is);
|
||||
next = cmdq_get_invoke(is, state);
|
||||
cmdq_insert_after(item, next);
|
||||
cmdq_insert_after(item, new_item);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
case CMD_PARSE_STRING:
|
||||
case CMD_PARSE_COMMANDS:
|
||||
case CMD_PARSE_TEXT:
|
||||
case CMD_PARSE_ENVIRONMENT:
|
||||
case CMD_PARSE_TILDE:
|
||||
fatalx("unexpected node type");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -675,7 +675,7 @@ cmd_parse_from_string(const char *s, struct cmd_parse_input *pi, char **cause)
|
||||
}
|
||||
|
||||
struct cmd_parse_tree *
|
||||
cmd_parse_addref(struct cmd_parse_tree *tree)
|
||||
cmd_parse_add_ref(struct cmd_parse_tree *tree)
|
||||
{
|
||||
tree->references++;
|
||||
return (tree);
|
||||
|
||||
44
cmd-queue.c
44
cmd-queue.c
@@ -35,6 +35,7 @@
|
||||
enum cmdq_type {
|
||||
CMDQ_COMMAND,
|
||||
CMDQ_CALLBACK,
|
||||
CMDQ_INVOKE,
|
||||
};
|
||||
|
||||
/* Command queue item. */
|
||||
@@ -60,6 +61,7 @@ struct cmdq_item {
|
||||
|
||||
struct cmd_list *cmdlist;
|
||||
struct cmd *cmd;
|
||||
struct cmd_invoke_state *invoke_state;
|
||||
|
||||
cmdq_cb cb;
|
||||
void *data;
|
||||
@@ -457,6 +459,8 @@ cmdq_remove(struct cmdq_item *item)
|
||||
server_client_unref(item->client);
|
||||
if (item->cmdlist != NULL)
|
||||
cmd_list_free(item->cmdlist);
|
||||
if (item->invoke_state != NULL)
|
||||
cmd_invoke_state_free(item->invoke_state);
|
||||
cmdq_free_state(item->state);
|
||||
|
||||
TAILQ_REMOVE(&item->queue->list, item, entry);
|
||||
@@ -536,6 +540,41 @@ cmdq_get_command(struct cmd_list *cmdlist, struct cmdq_state *state)
|
||||
return (first);
|
||||
}
|
||||
|
||||
/* Get a single command for command queue with invoke state. */
|
||||
struct cmdq_item *
|
||||
cmdq_get_one_command(struct cmd *cmd, struct cmdq_state *state,
|
||||
struct cmd_invoke_state *invoke_state)
|
||||
{
|
||||
struct cmd_list *cmdlist;
|
||||
struct cmdq_item *item;
|
||||
|
||||
cmdlist = cmd_list_new();
|
||||
cmd_list_append(cmdlist, cmd);
|
||||
|
||||
item = cmdq_get_command(cmdlist, state);
|
||||
cmd_list_free(cmdlist);
|
||||
item->invoke_state = cmd_invoke_state_add_ref(invoke_state);
|
||||
return (item);
|
||||
}
|
||||
|
||||
/* Get an invoke continuation for command queue. */
|
||||
struct cmdq_item *
|
||||
cmdq_get_invoke(struct cmd_invoke_state *invoke_state, struct cmdq_state *state)
|
||||
{
|
||||
struct cmdq_item *item;
|
||||
|
||||
item = xcalloc(1, sizeof *item);
|
||||
xasprintf(&item->name, "[invoke/%p]", item);
|
||||
item->type = CMDQ_INVOKE;
|
||||
item->group = 0;
|
||||
if (state == NULL)
|
||||
item->state = cmdq_new_state(NULL, NULL, 0);
|
||||
else
|
||||
item->state = cmdq_link_state(state);
|
||||
item->invoke_state = cmd_invoke_state_add_ref(invoke_state);
|
||||
return (item);
|
||||
}
|
||||
|
||||
/* Fill in flag for a command. */
|
||||
static enum cmd_retval
|
||||
cmdq_find_flag(struct cmdq_item *item, struct cmd_find_state *fs,
|
||||
@@ -772,6 +811,8 @@ cmdq_next(struct client *c)
|
||||
switch (item->type) {
|
||||
case CMDQ_COMMAND:
|
||||
retval = cmdq_fire_command(item);
|
||||
if (item->invoke_state != NULL)
|
||||
cmd_invoke_result(item->invoke_state, retval);
|
||||
|
||||
/*
|
||||
* If a command returns an error, remove any
|
||||
@@ -783,6 +824,9 @@ cmdq_next(struct client *c)
|
||||
case CMDQ_CALLBACK:
|
||||
retval = cmdq_fire_callback(item);
|
||||
break;
|
||||
case CMDQ_INVOKE:
|
||||
retval = cmd_invoke_fire(item, item->invoke_state);
|
||||
break;
|
||||
default:
|
||||
retval = CMD_RETURN_ERROR;
|
||||
break;
|
||||
|
||||
@@ -63,10 +63,10 @@ enum cmd_parse_node_type {
|
||||
struct cmd_parse_tree *cmd_parse_from_file(FILE *, struct cmd_parse_input *,
|
||||
char **);
|
||||
struct cmd_parse_tree *cmd_parse_from_buffer(const void *, size_t,
|
||||
struct cmd_parse_input *, char **);
|
||||
struct cmd_parse_input *, char **);
|
||||
struct cmd_parse_tree *cmd_parse_from_string(const char *,
|
||||
struct cmd_parse_input *, char **);
|
||||
struct cmd_parse_tree *cmd_parse_addref(struct cmd_parse_tree *);
|
||||
struct cmd_parse_input *, char **);
|
||||
struct cmd_parse_tree *cmd_parse_add_ref(struct cmd_parse_tree *);
|
||||
void cmd_parse_free(struct cmd_parse_tree *);
|
||||
struct cmd_parse_node *cmd_parse_root(struct cmd_parse_tree *);
|
||||
char *cmd_parse_print(const struct cmd_parse_tree *);
|
||||
|
||||
15
tmux.h
15
tmux.h
@@ -43,6 +43,9 @@ struct args_command_state;
|
||||
struct client;
|
||||
struct cmd;
|
||||
struct cmd_find_state;
|
||||
struct cmd_invoke_state;
|
||||
struct cmd_parse_node;
|
||||
struct cmd_parse_tree;
|
||||
struct cmdq_item;
|
||||
struct cmdq_list;
|
||||
struct cmdq_state;
|
||||
@@ -3023,6 +3026,14 @@ struct cmd_parse_result *cmd_parse_from_buffer(const void *, size_t,
|
||||
struct cmd_parse_result *cmd_parse_from_arguments(struct args_value *, u_int,
|
||||
struct cmd_parse_input *);
|
||||
|
||||
/* cmd-invoke.c */
|
||||
struct cmdq_item *cmd_invoke_get(struct cmd_parse_tree *, struct cmdq_state *,
|
||||
int, char **);
|
||||
struct cmd_invoke_state *cmd_invoke_state_add_ref(struct cmd_invoke_state *);
|
||||
void cmd_invoke_state_free(struct cmd_invoke_state *);
|
||||
void cmd_invoke_result(struct cmd_invoke_state *, enum cmd_retval);
|
||||
enum cmd_retval cmd_invoke_fire(struct cmdq_item *, struct cmd_invoke_state *);
|
||||
|
||||
/* cmd-queue.c */
|
||||
struct cmdq_state *cmdq_new_state(struct cmd_find_state *, struct key_event *,
|
||||
int);
|
||||
@@ -3046,6 +3057,10 @@ struct key_event *cmdq_get_event(struct cmdq_item *);
|
||||
struct cmd_find_state *cmdq_get_current(struct cmdq_item *);
|
||||
int cmdq_get_flags(struct cmdq_item *);
|
||||
struct cmdq_item *cmdq_get_command(struct cmd_list *, struct cmdq_state *);
|
||||
struct cmdq_item *cmdq_get_one_command(struct cmd *, struct cmdq_state *,
|
||||
struct cmd_invoke_state *);
|
||||
struct cmdq_item *cmdq_get_invoke(struct cmd_invoke_state *,
|
||||
struct cmdq_state *);
|
||||
#define cmdq_get_callback(cb, data) cmdq_get_callback1(#cb, cb, data)
|
||||
struct cmdq_item *cmdq_get_callback1(const char *, cmdq_cb, void *);
|
||||
struct cmdq_item *cmdq_get_error(const char *);
|
||||
|
||||
Reference in New Issue
Block a user