mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 04:43:10 +00:00
Add support for ! as an analog to 'not'
! and not are effectively interchangeable now. Mark them both as operators for syntax highlighting.
This commit is contained in:
parent
f83742d579
commit
c7f16439bf
10 changed files with 70 additions and 16 deletions
|
@ -3961,6 +3961,11 @@ static void test_highlighting() {
|
||||||
{L"||", highlight_spec_operator},
|
{L"||", highlight_spec_operator},
|
||||||
{L"true", highlight_spec_command},
|
{L"true", highlight_spec_command},
|
||||||
{L";", highlight_spec_statement_terminator},
|
{L";", highlight_spec_statement_terminator},
|
||||||
|
{L"and", highlight_spec_operator},
|
||||||
|
{L"not", highlight_spec_operator},
|
||||||
|
{L"!", highlight_spec_operator},
|
||||||
|
{L"true", highlight_spec_command},
|
||||||
|
{L";", highlight_spec_statement_terminator},
|
||||||
{L"end", highlight_spec_command},
|
{L"end", highlight_spec_command},
|
||||||
{NULL, -1}};
|
{NULL, -1}};
|
||||||
|
|
||||||
|
|
|
@ -1033,7 +1033,6 @@ const highlighter_t::color_array_t &highlighter_t::highlight() {
|
||||||
case symbol_if_clause:
|
case symbol_if_clause:
|
||||||
case symbol_else_clause:
|
case symbol_else_clause:
|
||||||
case symbol_case_item:
|
case symbol_case_item:
|
||||||
case symbol_not_statement:
|
|
||||||
case symbol_decorated_statement:
|
case symbol_decorated_statement:
|
||||||
case symbol_if_statement: {
|
case symbol_if_statement: {
|
||||||
this->color_children(node, parse_token_type_string, highlight_spec_command);
|
this->color_children(node, parse_token_type_string, highlight_spec_command);
|
||||||
|
@ -1065,6 +1064,10 @@ const highlighter_t::color_array_t &highlighter_t::highlight() {
|
||||||
this->color_node(node, highlight_spec_operator);
|
this->color_node(node, highlight_spec_operator);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case symbol_not_statement:
|
||||||
|
this->color_children(node, parse_token_type_string, highlight_spec_operator);
|
||||||
|
break;
|
||||||
|
|
||||||
case symbol_job_decorator:
|
case symbol_job_decorator:
|
||||||
this->color_node(node, highlight_spec_operator);
|
this->color_node(node, highlight_spec_operator);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -111,21 +111,30 @@ enum parse_keyword_t {
|
||||||
parse_keyword_if,
|
parse_keyword_if,
|
||||||
parse_keyword_in,
|
parse_keyword_in,
|
||||||
parse_keyword_not,
|
parse_keyword_not,
|
||||||
|
parse_keyword_exclam,
|
||||||
parse_keyword_or,
|
parse_keyword_or,
|
||||||
parse_keyword_switch,
|
parse_keyword_switch,
|
||||||
parse_keyword_while,
|
parse_keyword_while,
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
const enum_map<parse_keyword_t> keyword_enum_map[] = {
|
const enum_map<parse_keyword_t> keyword_enum_map[] = {{parse_keyword_exclam, L"!"},
|
||||||
{parse_keyword_and, L"and"}, {parse_keyword_begin, L"begin"},
|
{parse_keyword_and, L"and"},
|
||||||
{parse_keyword_builtin, L"builtin"}, {parse_keyword_case, L"case"},
|
{parse_keyword_begin, L"begin"},
|
||||||
{parse_keyword_command, L"command"}, {parse_keyword_else, L"else"},
|
{parse_keyword_builtin, L"builtin"},
|
||||||
{parse_keyword_end, L"end"}, {parse_keyword_exec, L"exec"},
|
{parse_keyword_case, L"case"},
|
||||||
{parse_keyword_for, L"for"}, {parse_keyword_function, L"function"},
|
{parse_keyword_command, L"command"},
|
||||||
{parse_keyword_if, L"if"}, {parse_keyword_in, L"in"},
|
{parse_keyword_else, L"else"},
|
||||||
{parse_keyword_not, L"not"}, {parse_keyword_or, L"or"},
|
{parse_keyword_end, L"end"},
|
||||||
{parse_keyword_switch, L"switch"}, {parse_keyword_while, L"while"},
|
{parse_keyword_exec, L"exec"},
|
||||||
{parse_keyword_none, NULL}};
|
{parse_keyword_for, L"for"},
|
||||||
|
{parse_keyword_function, L"function"},
|
||||||
|
{parse_keyword_if, L"if"},
|
||||||
|
{parse_keyword_in, L"in"},
|
||||||
|
{parse_keyword_not, L"not"},
|
||||||
|
{parse_keyword_or, L"or"},
|
||||||
|
{parse_keyword_switch, L"switch"},
|
||||||
|
{parse_keyword_while, L"while"},
|
||||||
|
{parse_keyword_none, NULL}};
|
||||||
#define keyword_enum_map_len (sizeof keyword_enum_map / sizeof *keyword_enum_map)
|
#define keyword_enum_map_len (sizeof keyword_enum_map / sizeof *keyword_enum_map)
|
||||||
|
|
||||||
// Node tag values.
|
// Node tag values.
|
||||||
|
|
|
@ -924,7 +924,8 @@ bool parse_execution_context_t::determine_io_chain(tnode_t<g::arguments_or_redir
|
||||||
parse_execution_result_t parse_execution_context_t::populate_not_process(
|
parse_execution_result_t parse_execution_context_t::populate_not_process(
|
||||||
job_t *job, process_t *proc, tnode_t<g::not_statement> not_statement) {
|
job_t *job, process_t *proc, tnode_t<g::not_statement> not_statement) {
|
||||||
job->set_flag(JOB_NEGATE, !job->get_flag(JOB_NEGATE));
|
job->set_flag(JOB_NEGATE, !job->get_flag(JOB_NEGATE));
|
||||||
return this->populate_job_process(job, proc, not_statement.child<1>());
|
return this->populate_job_process(job, proc,
|
||||||
|
not_statement.require_get_child<g::statement, 1>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
|
|
|
@ -312,8 +312,10 @@ DEF(function_header)
|
||||||
produces_sequence<keyword<parse_keyword_function>, argument, argument_list, tok_end>{
|
produces_sequence<keyword<parse_keyword_function>, argument, argument_list, tok_end>{
|
||||||
BODY(function_header)};
|
BODY(function_header)};
|
||||||
|
|
||||||
DEF(not_statement) produces_sequence<keyword<parse_keyword_not>, statement> {
|
DEF_ALT(not_statement) {
|
||||||
BODY(not_statement);
|
using nots = seq<keyword<parse_keyword_not>, statement>;
|
||||||
|
using exclams = seq<keyword<parse_keyword_exclam>, statement>;
|
||||||
|
ALT_BODY(not_statement, nots, exclams);
|
||||||
};
|
};
|
||||||
|
|
||||||
// An andor_job_list is zero or more job lists, where each starts with an `and` or `or` boolean
|
// An andor_job_list is zero or more job lists, where each starts with an `and` or `or` boolean
|
||||||
|
|
|
@ -143,7 +143,8 @@ RESOLVE(statement) {
|
||||||
switch (token1.type) {
|
switch (token1.type) {
|
||||||
case parse_token_type_string: {
|
case parse_token_type_string: {
|
||||||
switch (token1.keyword) {
|
switch (token1.keyword) {
|
||||||
case parse_keyword_not: {
|
case parse_keyword_not:
|
||||||
|
case parse_keyword_exclam: {
|
||||||
return production_for<nots>();
|
return production_for<nots>();
|
||||||
}
|
}
|
||||||
case parse_keyword_for:
|
case parse_keyword_for:
|
||||||
|
@ -215,6 +216,19 @@ RESOLVE(case_item_list) {
|
||||||
return production_for<empty>();
|
return production_for<empty>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RESOLVE(not_statement) {
|
||||||
|
UNUSED(token2);
|
||||||
|
UNUSED(out_tag);
|
||||||
|
switch (token1.keyword) {
|
||||||
|
case parse_keyword_not:
|
||||||
|
return production_for<nots>();
|
||||||
|
case parse_keyword_exclam:
|
||||||
|
return production_for<exclams>();
|
||||||
|
default:
|
||||||
|
return NO_PRODUCTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RESOLVE(andor_job_list) {
|
RESOLVE(andor_job_list) {
|
||||||
UNUSED(out_tag);
|
UNUSED(out_tag);
|
||||||
|
|
||||||
|
|
|
@ -960,7 +960,7 @@ static inline parse_keyword_t keyword_with_name(const wchar_t *name) {
|
||||||
|
|
||||||
static bool is_keyword_char(wchar_t c) {
|
static bool is_keyword_char(wchar_t c) {
|
||||||
return (c >= L'a' && c <= L'z') || (c >= L'A' && c <= L'Z') || (c >= L'0' && c <= L'9') ||
|
return (c >= L'a' && c <= L'z') || (c >= L'A' && c <= L'Z') || (c >= L'0' && c <= L'9') ||
|
||||||
c == L'\'' || c == L'"' || c == L'\\' || c == '\n';
|
c == L'\'' || c == L'"' || c == L'\\' || c == '\n' || c == L'!';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a token, returns the keyword it matches, or parse_keyword_none.
|
/// Given a token, returns the keyword it matches, or parse_keyword_none.
|
||||||
|
|
|
@ -8,5 +8,8 @@
|
||||||
####################
|
####################
|
||||||
# && and || in while statements
|
# && and || in while statements
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Nots
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# Complex scenarios
|
# Complex scenarios
|
||||||
|
|
|
@ -28,6 +28,14 @@ while [ $alpha -lt 2 ] && [ $beta -lt 3 ]
|
||||||
set delta ( math $delta + 1 )
|
set delta ( math $delta + 1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
logmsg "Nots"
|
||||||
|
|
||||||
|
true && ! false ; echo $status
|
||||||
|
not true && ! false ; echo $status
|
||||||
|
not not not true ; echo $status
|
||||||
|
not ! ! not true ; echo $status
|
||||||
|
not ! echo not ! ; echo $status
|
||||||
|
|
||||||
logmsg "Complex scenarios"
|
logmsg "Complex scenarios"
|
||||||
|
|
||||||
begin; echo 1 ; false ; end || begin ; echo 2 && echo 3 ; end
|
begin; echo 1 ; false ; end || begin ; echo 2 && echo 3 ; end
|
||||||
|
|
|
@ -23,6 +23,15 @@ if test 4 ok
|
||||||
3 3 3
|
3 3 3
|
||||||
4 4 4
|
4 4 4
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Nots
|
||||||
|
0
|
||||||
|
1
|
||||||
|
1
|
||||||
|
0
|
||||||
|
not !
|
||||||
|
0
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# Complex scenarios
|
# Complex scenarios
|
||||||
1
|
1
|
||||||
|
|
Loading…
Reference in a new issue