mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Add && and || support to the conditions of if and while
This updates the "boolean tail" feature of the if and while conditions to know about job_conjunction, thereby respecting && and ||
This commit is contained in:
parent
8e9670ccd5
commit
e1dafeab01
7 changed files with 75 additions and 12 deletions
|
@ -121,7 +121,7 @@ static void prettify_node_recursive(const wcstring &source, const parse_node_tre
|
|||
const bool is_root_case_list =
|
||||
node_type == symbol_case_item_list && parent_type != symbol_case_item_list;
|
||||
const bool is_if_while_header =
|
||||
(node_type == symbol_job || node_type == symbol_andor_job_list) &&
|
||||
(node_type == symbol_job_conjunction || node_type == symbol_andor_job_list) &&
|
||||
(parent_type == symbol_if_clause || parent_type == symbol_while_header);
|
||||
|
||||
if (is_root_job_list || is_root_case_list || is_if_while_header) {
|
||||
|
|
|
@ -244,12 +244,12 @@ parse_execution_result_t parse_execution_context_t::run_if_statement(
|
|||
}
|
||||
|
||||
// An if condition has a job and a "tail" of andor jobs, e.g. "foo ; and bar; or baz".
|
||||
tnode_t<g::job> condition_head = if_clause.child<1>();
|
||||
tnode_t<g::job_conjunction> condition_head = if_clause.child<1>();
|
||||
tnode_t<g::andor_job_list> condition_boolean_tail = if_clause.child<3>();
|
||||
|
||||
// Check the condition and the tail. We treat parse_execution_errored here as failure, in
|
||||
// accordance with historic behavior.
|
||||
parse_execution_result_t cond_ret = run_1_job(condition_head, ib);
|
||||
parse_execution_result_t cond_ret = run_job_conjunction(condition_head, ib);
|
||||
if (cond_ret == parse_execution_success) {
|
||||
cond_ret = run_job_list(condition_boolean_tail, ib);
|
||||
}
|
||||
|
@ -527,13 +527,13 @@ parse_execution_result_t parse_execution_context_t::run_while_statement(
|
|||
parse_execution_result_t ret = parse_execution_success;
|
||||
|
||||
// The conditions of the while loop.
|
||||
tnode_t<g::job> condition_head = header.child<1>();
|
||||
tnode_t<g::job_conjunction> condition_head = header.child<1>();
|
||||
tnode_t<g::andor_job_list> condition_boolean_tail = header.child<3>();
|
||||
|
||||
// Run while the condition is true.
|
||||
for (;;) {
|
||||
// Check the condition.
|
||||
parse_execution_result_t cond_ret = this->run_1_job(condition_head, wb);
|
||||
parse_execution_result_t cond_ret = this->run_job_conjunction(condition_head, wb);
|
||||
if (cond_ret == parse_execution_success) {
|
||||
cond_ret = run_job_list(condition_boolean_tail, wb);
|
||||
}
|
||||
|
|
|
@ -245,7 +245,7 @@ produces_sequence<if_clause, else_clause, end_command, arguments_or_redirections
|
|||
BODY(if_statement)};
|
||||
|
||||
DEF(if_clause)
|
||||
produces_sequence<keyword<parse_keyword_if>, job, tok_end, andor_job_list, job_list>{
|
||||
produces_sequence<keyword<parse_keyword_if>, job_conjunction, tok_end, andor_job_list, job_list>{
|
||||
BODY(if_clause)};
|
||||
|
||||
DEF_ALT(else_clause) {
|
||||
|
@ -294,7 +294,8 @@ produces_sequence<keyword<parse_keyword_for>, tok_string, keyword<parse_keyword_
|
|||
};
|
||||
|
||||
DEF(while_header)
|
||||
produces_sequence<keyword<parse_keyword_while>, job, tok_end, andor_job_list>{BODY(while_header)};
|
||||
produces_sequence<keyword<parse_keyword_while>, job_conjunction, tok_end, andor_job_list>{
|
||||
BODY(while_header)};
|
||||
|
||||
DEF(begin_header) produces_single<keyword<parse_keyword_begin>>{BODY(begin_header)};
|
||||
|
||||
|
|
|
@ -1057,14 +1057,14 @@ static bool detect_errors_in_backgrounded_job(tnode_t<grammar::job> job,
|
|||
// foo & ; or bar
|
||||
// if foo & ; end
|
||||
// while foo & ; end
|
||||
if (job.try_get_parent<g::if_clause>()) {
|
||||
auto job_conj = job.try_get_parent<g::job_conjunction>();
|
||||
if (job_conj.try_get_parent<g::if_clause>()) {
|
||||
errored = append_syntax_error(parse_errors, source_range->start,
|
||||
BACKGROUND_IN_CONDITIONAL_ERROR_MSG);
|
||||
} else if (job.try_get_parent<g::while_header>()) {
|
||||
} else if (job_conj.try_get_parent<g::while_header>()) {
|
||||
errored = append_syntax_error(parse_errors, source_range->start,
|
||||
BACKGROUND_IN_CONDITIONAL_ERROR_MSG);
|
||||
} else if (auto jlist =
|
||||
job.try_get_parent<g::job_conjunction>().try_get_parent<g::job_list>()) {
|
||||
} else if (auto jlist = job_conj.try_get_parent<g::job_list>()) {
|
||||
// This isn't very complete, e.g. we don't catch 'foo & ; not and bar'.
|
||||
// Fetch the job list and then advance it by one.
|
||||
auto first_jconj = jlist.next_in_list<g::job_conjunction>();
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
####################
|
||||
# Basic && and || support
|
||||
|
||||
####################
|
||||
# && and || in if statements
|
||||
|
||||
####################
|
||||
# && and || in while statements
|
||||
|
||||
####################
|
||||
# Complex scenarios
|
|
@ -1,7 +1,33 @@
|
|||
# Test && and || support
|
||||
logmsg "Basic && and || support"
|
||||
|
||||
echo first && echo second
|
||||
echo third || echo fourth
|
||||
true && false ; echo "true && false: $status"
|
||||
true || false ; echo "true || false: $status"
|
||||
true && false || true ; echo "true && false || true: $status"
|
||||
|
||||
logmsg "&& and || in if statements"
|
||||
|
||||
if true || false ; echo "if test 1 ok" ; end
|
||||
if true && false ; else; echo "if test 2 ok" ; end
|
||||
if true && false ; or true ; echo "if test 3 ok" ; end
|
||||
if [ 0 = 1 ] || [ 5 -ge 3 ] ; echo "if test 4 ok"; end
|
||||
|
||||
logmsg "&& and || in while statements"
|
||||
|
||||
set alpha 0
|
||||
set beta 0
|
||||
set gamma 0
|
||||
set delta 0
|
||||
while [ $alpha -lt 2 ] && [ $beta -lt 3 ]
|
||||
and [ $gamma -lt 4 ] || [ $delta -lt 5 ]
|
||||
echo $alpha $beta $gamma
|
||||
set alpha ( math $alpha + 1 )
|
||||
set beta ( math $beta + 1 )
|
||||
set gamma ( math $gamma + 1 )
|
||||
set delta ( math $delta + 1 )
|
||||
end
|
||||
|
||||
logmsg "Complex scenarios"
|
||||
|
||||
begin; echo 1 ; false ; end || begin ; echo 2 && echo 3 ; end
|
||||
|
|
|
@ -1,6 +1,30 @@
|
|||
|
||||
####################
|
||||
# Basic && and || support
|
||||
first
|
||||
second
|
||||
third
|
||||
true && false: 1
|
||||
true || false: 0
|
||||
true && false || true: 0
|
||||
|
||||
####################
|
||||
# && and || in if statements
|
||||
if test 1 ok
|
||||
if test 2 ok
|
||||
if test 3 ok
|
||||
if test 4 ok
|
||||
|
||||
####################
|
||||
# && and || in while statements
|
||||
0 0 0
|
||||
1 1 1
|
||||
2 2 2
|
||||
3 3 3
|
||||
4 4 4
|
||||
|
||||
####################
|
||||
# Complex scenarios
|
||||
1
|
||||
2
|
||||
3
|
||||
|
|
Loading…
Reference in a new issue