Allow simple commands to be fired.

This commit is contained in:
Your Name
2026-06-30 10:03:49 +01:00
parent 5f7a4b0f52
commit fcfa0b6db4
11 changed files with 76 additions and 19 deletions

12
cfg.c
View File

@@ -98,6 +98,7 @@ load_cfg(const char *path, struct cmdq_item *item,
{
FILE *f;
struct cmd_parse_input pi;
struct cmd_invoke_input ci;
struct cmd_parse_tree *tree;
struct cmdq_item *new_item0;
struct cmdq_state *state;
@@ -137,7 +138,10 @@ load_cfg(const char *path, struct cmdq_item *item,
state = cmdq_new_state(NULL, NULL, 0);
cmdq_add_format(state, "current_file", "%s", pi.file);
new_item0 = cmd_invoke_get(tree, state, 0, NULL);
memset(&ci, 0, sizeof ci);
ci.file = pi.file;
ci.flags = flags;
new_item0 = cmd_invoke_get(tree, state, &ci);
if (item != NULL)
new_item0 = cmdq_insert_after(item, new_item0);
else
@@ -156,6 +160,7 @@ load_cfg_from_buffer(const void *buf, size_t len, const char *path,
struct cmdq_item **new_item)
{
struct cmd_parse_input pi;
struct cmd_invoke_input ci;
struct cmd_parse_tree *tree;
struct cmdq_item *new_item0;
struct cmdq_state *state;
@@ -188,7 +193,10 @@ load_cfg_from_buffer(const void *buf, size_t len, const char *path,
state = cmdq_new_state(NULL, NULL, 0);
cmdq_add_format(state, "current_file", "%s", pi.file);
new_item0 = cmd_invoke_get(tree, state, 0, NULL);
memset(&ci, 0, sizeof ci);
ci.file = pi.file;
ci.flags = flags;
new_item0 = cmd_invoke_get(tree, state, &ci);
if (item != NULL)
new_item0 = cmdq_insert_after(item, new_item0);
else

View File

@@ -366,8 +366,8 @@ fail:
/* 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)
cmd_invoke_get(struct cmd_parse_tree *tree, struct cmdq_state *state,
const struct cmd_invoke_input *input)
{
struct cmd_invoke_state *is;
struct cmd_parse_node *root = cmd_parse_root(tree), *first;
@@ -377,14 +377,16 @@ cmd_invoke_get(struct cmd_parse_tree *tree, struct cmdq_state *state, int argc,
is = xcalloc(1, sizeof *is);
is->references = 1;
is->tree = cmd_parse_add_ref(tree);
log_debug("%s: tree %p", __func__, tree);
cmd_parse_log(__func__, 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]);
if (input->file != NULL)
is->file = xstrdup(input->file);
is->parse_flags = input->flags;
is->argc = input->argc;
if (input->argc != 0) {
is->argv = xreallocarray(NULL, input->argc, sizeof *is->argv);
for (i = 0; i < input->argc; i++)
is->argv[i] = xstrdup(input->argv[i]);
}
first = cmd_parse_node_first_child(root);
@@ -472,13 +474,12 @@ cmd_invoke_fire(struct cmdq_item *item, struct cmd_invoke_state *is)
}
break;
case CMD_PARSE_ELIF:
case CMD_PARSE_ELSE:
break;
case CMD_PARSE_COMMAND:
fatalx("XXX: command execution not implemented yet");
cmd = cmd_invoke_build_command(item, is, node);
if (cmd == NULL) {
cmd_invoke_skip_sequence(is);
case CMD_PARSE_ELSE:
break;
case CMD_PARSE_COMMAND:
cmd = cmd_invoke_build_command(item, is, node);
if (cmd == NULL) {
cmd_invoke_skip_sequence(is);
break;
}

View File

@@ -0,0 +1,3 @@
# Command body unsupported checkpoint.
# Expected at this stage: should parse, then fatal/XXX when invocation reaches ARGS_COMMANDS.
bind-key F1 { display-message "parser command body" }

View File

@@ -0,0 +1,2 @@
display-message "HOME=$HOME"
display-message ~

View File

@@ -0,0 +1,5 @@
# Failure scope test.
# Expected with sequence skipping: bad command fails, following command in same sequence is skipped,
# then next top-level sequence still runs.
display-message "parser failure: before bad command" ; no-such-tmux-command ; display-message "parser failure: should be skipped"
display-message "parser failure: next sequence should still run"

View File

@@ -0,0 +1,10 @@
# %if/%elif/%else.
# Expected: elif branch is selected.
%if 0
display-message "parser elif: selected if branch - wrong"
%elif 1
display-message "parser elif: selected elif branch"
%else
display-message "parser elif: selected else branch - wrong"
%endif
display-message "parser elif: after endif"

View File

@@ -0,0 +1,8 @@
# %if true branch.
# Expected: first branch is selected.
%if 1
display-message "parser if true: selected if branch"
%else
display-message "parser if true: selected else branch - wrong"
%endif
display-message "parser if true: after endif"

View File

@@ -0,0 +1,3 @@
# Inline %if form.
# Expected: inline true branch selected, then following command in same sequence is processed.
display-message "parser inline if: before" ; %if 1 display-message "parser inline if: branch" %endif ; display-message "parser inline if: after"

View File

@@ -0,0 +1,3 @@
# Semicolon sequence.
# Expected: one top-level sequence containing three commands.
set -g status on ; set -g message-style fg=yellow ; display-message "parser semicolon sequence"

View File

@@ -0,0 +1,5 @@
# Simple straight-line commands.
# Expected: all commands parse and run in order.
set -g status off
set -g message-style fg=green
display-message "parser simple: status=#{status}"

11
tmux.h
View File

@@ -1977,6 +1977,15 @@ struct cmd_entry {
enum cmd_retval (*exec)(struct cmd *, struct cmdq_item *);
};
/* Command invocation input. */
struct cmd_invoke_input {
const char *file;
int flags;
int argc;
char **argv;
};
/* Status line. */
#define STATUS_LINES_LIMIT 5
struct status_line {
@@ -2988,7 +2997,7 @@ enum cmd_retval cmd_attach_session(struct cmdq_item *, const char *, int, int,
/* cmd-invoke.c */
struct cmdq_item *cmd_invoke_get(struct cmd_parse_tree *, struct cmdq_state *,
int, char **);
const struct cmd_invoke_input *);
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);