Fix initially backgrounded jobs. Fixes #1373

This commit is contained in:
ridiculousfish 2014-03-28 14:39:47 -07:00
parent c1f64ba017
commit 005edf71a8
5 changed files with 25 additions and 8 deletions

View file

@ -960,7 +960,7 @@ public:
void highlighter_t::color_node(const parse_node_t &node, highlight_spec_t color) void highlighter_t::color_node(const parse_node_t &node, highlight_spec_t color)
{ {
// Can only color nodes with valid source ranges // Can only color nodes with valid source ranges
if (! node.has_source()) if (! node.has_source() || node.source_length == 0)
return; return;
// Fill the color array with our color in the corresponding range // Fill the color array with our color in the corresponding range
@ -1356,6 +1356,7 @@ const highlighter_t::color_array_t & highlighter_t::highlight()
case parse_token_type_background: case parse_token_type_background:
case parse_token_type_end: case parse_token_type_end:
case symbol_optional_background:
{ {
this->color_node(node, highlight_spec_statement_terminator); this->color_node(node, highlight_spec_statement_terminator);
} }

View file

@ -1371,7 +1371,7 @@ parse_execution_result_t parse_execution_context_t::run_1_job(const parse_node_t
(job_control_mode==JOB_CONTROL_ALL) || (job_control_mode==JOB_CONTROL_ALL) ||
((job_control_mode == JOB_CONTROL_INTERACTIVE) && (get_is_interactive()))); ((job_control_mode == JOB_CONTROL_INTERACTIVE) && (get_is_interactive())));
job_set_flag(j, JOB_FOREGROUND, 1); job_set_flag(j, JOB_FOREGROUND, ! tree.job_should_be_backgrounded(job_node));
job_set_flag(j, JOB_TERMINAL, job_get_flag(j, JOB_CONTROL) \ job_set_flag(j, JOB_TERMINAL, job_get_flag(j, JOB_CONTROL) \
&& (!is_subshell && !is_event)); && (!is_subshell && !is_event));

View file

@ -82,7 +82,7 @@ RESOLVE(job_list)
PRODUCTIONS(job) = PRODUCTIONS(job) =
{ {
{symbol_statement, symbol_job_continuation} {symbol_statement, symbol_job_continuation, symbol_optional_background}
}; };
RESOLVE_ONLY(job) RESOLVE_ONLY(job)
@ -402,7 +402,7 @@ RESOLVE(decorated_statement)
PRODUCTIONS(plain_statement) = PRODUCTIONS(plain_statement) =
{ {
{parse_token_type_string, symbol_arguments_or_redirections_list, symbol_optional_background} {parse_token_type_string, symbol_arguments_or_redirections_list}
}; };
RESOLVE_ONLY(plain_statement) RESOLVE_ONLY(plain_statement)

View file

@ -1496,6 +1496,19 @@ parse_node_tree_t::parse_node_list_t parse_node_tree_t::specific_statements_for_
return result; return result;
} }
bool parse_node_tree_t::job_should_be_backgrounded(const parse_node_t &job) const
{
assert(job.type == symbol_job);
assert(job.production_idx == 0);
bool result = false;
const parse_node_t *opt_background = get_child(job, 2, symbol_optional_background);
if (opt_background != NULL) {
assert(opt_background->production_idx <= 1);
result = (opt_background->production_idx == 1);
}
return result;
}
const parse_node_t *parse_node_tree_t::next_node_in_node_list(const parse_node_t &node_list, parse_token_type_t entry_type, const parse_node_t **out_list_tail) const const parse_node_t *parse_node_tree_t::next_node_in_node_list(const parse_node_t &node_list, parse_token_type_t entry_type, const parse_node_t **out_list_tail) const
{ {
parse_token_type_t list_type = node_list.type; parse_token_type_t list_type = node_list.type;

View file

@ -184,6 +184,9 @@ public:
/* Given a job, return all of its statements. These are 'specific statements' (e.g. symbol_decorated_statement, not symbol_statement) */ /* Given a job, return all of its statements. These are 'specific statements' (e.g. symbol_decorated_statement, not symbol_statement) */
parse_node_list_t specific_statements_for_job(const parse_node_t &job) const; parse_node_list_t specific_statements_for_job(const parse_node_t &job) const;
/* Given a job, return whether it should be backgrounded, because it has a & specifier */
bool job_should_be_backgrounded(const parse_node_t &job) const;
}; };
@ -198,9 +201,9 @@ bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t flags, parse
job job_list job job_list
<TOK_END> job_list <TOK_END> job_list
# A job is a non-empty list of statements, separated by pipes. (Non-empty is useful for cases like if statements, where we require a command). To represent "non-empty", we require a statement, followed by a possibly empty job_continuation # A job is a non-empty list of statements, separated by pipes. (Non-empty is useful for cases like if statements, where we require a command). To represent "non-empty", we require a statement, followed by a possibly empty job_continuation, and then optionally a background specifier '&'
job = statement job_continuation job = statement job_continuation optional_background
job_continuation = <empty> | job_continuation = <empty> |
<TOK_PIPE> statement job_continuation <TOK_PIPE> statement job_continuation
@ -240,7 +243,7 @@ bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t flags, parse
# A decorated_statement is a command with a list of arguments_or_redirections, possibly with "builtin" or "command" or "exec" # A decorated_statement is a command with a list of arguments_or_redirections, possibly with "builtin" or "command" or "exec"
decorated_statement = plain_statement | COMMAND plain_statement | BUILTIN plain_statement | EXEC plain_statement decorated_statement = plain_statement | COMMAND plain_statement | BUILTIN plain_statement | EXEC plain_statement
plain_statement = <TOK_STRING> arguments_or_redirections_list optional_background plain_statement = <TOK_STRING> arguments_or_redirections_list
argument_list = <empty> | argument argument_list argument_list = <empty> | argument argument_list
@ -255,7 +258,7 @@ bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t flags, parse
end_command = END end_command = END
# A freestanding_argument_list is equivalent to a normal argument list, except it may contain TOK_END (newlines, and even semicolons, for historical reasons: # A freestanding_argument_list is equivalent to a normal argument list, except it may contain TOK_END (newlines, and even semicolons, for historical reasons
freestanding_argument_list = <empty> | freestanding_argument_list = <empty> |
argument freestanding_argument_list | argument freestanding_argument_list |