diff --git a/share/completions/do.fish b/share/completions/do.fish deleted file mode 100644 index 8b4769aab..000000000 --- a/share/completions/do.fish +++ /dev/null @@ -1 +0,0 @@ -complete -c do -xa '(__fish_complete_subcommand)' diff --git a/share/completions/then.fish b/share/completions/then.fish deleted file mode 100644 index 4a39a2fc5..000000000 --- a/share/completions/then.fish +++ /dev/null @@ -1 +0,0 @@ -complete -c then -xa '(__fish_complete_subcommand)' diff --git a/src/ast.rs b/src/ast.rs index 0136f3762..9b4825940 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -79,10 +79,8 @@ fn visit_decorated_statement_decorator( _node: &mut Option, ); fn visit_job_conjunction_decorator(&mut self, _node: &mut Option); - fn visit_do(&mut self, _node: &mut Option); fn visit_else_clause(&mut self, _node: &mut Option); fn visit_semi_nl(&mut self, _node: &mut Option); - fn visit_then(&mut self, _node: &mut Option); fn visit_time(&mut self, _node: &mut Option); fn visit_token_background(&mut self, _node: &mut Option); } @@ -979,12 +977,6 @@ macro_rules! visit_optional_field_mut { (KeywordTime, $field:expr, $visitor:ident) => { $visitor.visit_time(&mut $field); }; - (KeywordDo, $field:expr, $visitor:ident) => { - $visitor.visit_do(&mut $field); - }; - (KeywordThen, $field:expr, $visitor:ident) => { - $visitor.visit_then(&mut $field); - }; (TokenBackground, $field:expr, $visitor:ident) => { $visitor.visit_token_background(&mut $field); }; @@ -1323,11 +1315,7 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool { || (token.typ == ParseTokenType::string && !matches!( token.keyword, - ParseKeyword::kw_case - | ParseKeyword::kw_done - | ParseKeyword::kw_else - | ParseKeyword::kw_end - | ParseKeyword::kw_fi + ParseKeyword::kw_case | ParseKeyword::kw_end | ParseKeyword::kw_else )) } } @@ -1345,8 +1333,6 @@ pub struct ForHeader { pub args: ArgumentList, /// newline or semicolon pub semi_nl: SemiNl, - // Optional "do" for compatibility with POSIX. - pub kw_do: Option, } implement_node!(ForHeader, branch, for_header); implement_acceptor_for_branch!( @@ -1356,7 +1342,6 @@ pub struct ForHeader { (kw_in: (KeywordIn)), (args: (ArgumentList)), (semi_nl: (SemiNl)), - (kw_do: (Option)), ); impl ConcreteNode for ForHeader { fn as_for_header(&self) -> Option<&ForHeader> { @@ -1376,8 +1361,6 @@ pub struct WhileHeader { pub kw_while: KeywordWhile, pub condition: JobConjunction, pub andor_tail: AndorJobList, - // Optional "do" for compatibility with POSIX. - pub kw_do: Option, } implement_node!(WhileHeader, branch, while_header); implement_acceptor_for_branch!( @@ -1385,7 +1368,6 @@ pub struct WhileHeader { (kw_while: (KeywordWhile)), (condition: (JobConjunction)), (andor_tail: (AndorJobList)), - (kw_do: (Option)), ); impl ConcreteNode for WhileHeader { fn as_while_header(&self) -> Option<&WhileHeader> { @@ -1459,7 +1441,7 @@ pub struct BlockStatement { /// List of jobs in this block. pub jobs: JobList, /// The 'end' node. - pub end: KeywordEndOrDone, + pub end: KeywordEnd, /// Arguments and redirections associated with the block. pub args_or_redirs: ArgumentOrRedirectionList, } @@ -1468,7 +1450,7 @@ pub struct BlockStatement { BlockStatement, (header: (variant)), (jobs: (JobList)), - (end: (KeywordEndOrDone)), + (end: (KeywordEnd)), (args_or_redirs: (ArgumentOrRedirectionList)), ); impl ConcreteNode for BlockStatement { @@ -1522,10 +1504,6 @@ pub struct IfClause { pub condition: JobConjunction, /// 'and/or' tail. pub andor_tail: AndorJobList, - // Semi - pub semi_nl: SemiNl, - // Optional "then" for compatibility with POSIX. - pub kw_then: Option, /// The body to execute if the condition is true. pub body: JobList, } @@ -1535,7 +1513,6 @@ pub struct IfClause { (kw_if: (KeywordIf)), (condition: (JobConjunction)), (andor_tail: (AndorJobList)), - (kw_then: (Option)), (body: (JobList)), ); impl ConcreteNode for IfClause { @@ -1633,7 +1610,7 @@ pub struct IfStatement { /// else part pub else_clause: Option, /// literal end - pub end: KeywordEndOrFi, + pub end: KeywordEnd, /// block args / redirs pub args_or_redirs: ArgumentOrRedirectionList, } @@ -1643,7 +1620,7 @@ pub struct IfStatement { (if_clause: (IfClause)), (elseif_clauses: (ElseifClauseList)), (else_clause: (Option)), - (end: (KeywordEndOrFi)), + (end: (KeywordEnd)), (args_or_redirs: (ArgumentOrRedirectionList)), ); impl ConcreteNode for IfStatement { @@ -2096,18 +2073,14 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool { define_keyword_node!(JobConjunctionDecorator, kw_and, kw_or); define_keyword_node!(KeywordBegin, kw_begin); define_keyword_node!(KeywordCase, kw_case); -define_keyword_node!(KeywordDo, kw_do); define_keyword_node!(KeywordElse, kw_else); define_keyword_node!(KeywordEnd, kw_end); -define_keyword_node!(KeywordEndOrDone, kw_end, kw_done); -define_keyword_node!(KeywordEndOrFi, kw_end, kw_fi); define_keyword_node!(KeywordFor, kw_for); define_keyword_node!(KeywordFunction, kw_function); define_keyword_node!(KeywordIf, kw_if); define_keyword_node!(KeywordIn, kw_in); define_keyword_node!(KeywordNot, kw_not, kw_exclam); define_keyword_node!(KeywordSwitch, kw_switch); -define_keyword_node!(KeywordThen, kw_then); define_keyword_node!(KeywordTime, kw_time); define_keyword_node!(KeywordWhile, kw_while); @@ -2152,26 +2125,6 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool { } } -impl CheckParse for KeywordDo { - fn can_be_parsed(pop: &mut Populator<'_>) -> bool { - let keyword = pop.peek_token(0).keyword; - if !matches!(keyword, ParseKeyword::kw_do) { - return false; - } - !pop.peek_token(1).is_dash_prefix_string() - } -} - -impl CheckParse for KeywordThen { - fn can_be_parsed(pop: &mut Populator<'_>) -> bool { - let keyword = pop.peek_token(0).keyword; - if !matches!(keyword, ParseKeyword::kw_then) { - return false; - } - !pop.peek_token(1).is_dash_prefix_string() - } -} - impl DecoratedStatement { /// Return the decoration for this statement. pub fn decoration(&self) -> StatementDecoration { @@ -3208,10 +3161,7 @@ fn did_visit_fields_of<'a>(&'a mut self, node: &'a dyn NodeMut, flow: VisitResul if next_token.typ == ParseTokenType::string && matches!( next_token.keyword, - ParseKeyword::kw_case - | ParseKeyword::kw_else - | ParseKeyword::kw_end - | ParseKeyword::kw_fi + ParseKeyword::kw_case | ParseKeyword::kw_else | ParseKeyword::kw_end ) { self.consume_excess_token_generating_error(); @@ -3295,12 +3245,6 @@ fn visit_semi_nl(&mut self, node: &mut Option) { fn visit_time(&mut self, node: &mut Option) { *node = self.try_parse::().map(|b| *b); } - fn visit_do(&mut self, node: &mut Option) { - *node = self.try_parse::().map(|b| *b); - } - fn visit_then(&mut self, node: &mut Option) { - *node = self.try_parse::().map(|b| *b); - } fn visit_token_background(&mut self, node: &mut Option) { *node = self.try_parse::().map(|b| *b); } @@ -3602,14 +3546,6 @@ fn consume_excess_token_generating_error(&mut self) { "'case' builtin not inside of switch block" ); } - ParseKeyword::kw_done => { - parse_error!( - self, - tok, - ParseErrorCode::unbalancing_case, - "'done' outside of a block" - ); - } ParseKeyword::kw_end => { parse_error!( self, @@ -3626,14 +3562,6 @@ fn consume_excess_token_generating_error(&mut self) { "'else' builtin not inside of if block" ); } - ParseKeyword::kw_fi => { - parse_error!( - self, - tok, - ParseErrorCode::unbalancing_end, - "'fi' outside of a block" - ); - } _ => { internal_error!( self, @@ -3891,11 +3819,9 @@ fn new_decorated_statement(slf: &mut Populator<'_>) -> StatementVariant { // looks like an option (starts with a dash), then parse it as a decorated statement. let help_only_kws = [ ParseKeyword::kw_begin, - ParseKeyword::kw_do, ParseKeyword::kw_function, ParseKeyword::kw_if, ParseKeyword::kw_switch, - ParseKeyword::kw_then, ParseKeyword::kw_while, ]; if if help_only_kws.contains(&self.peek_token(0).keyword) { @@ -3908,13 +3834,8 @@ fn new_decorated_statement(slf: &mut Populator<'_>) -> StatementVariant { // Likewise if the next token doesn't look like an argument at all. This corresponds to // e.g. a "naked if". - let naked_invocation_invokes_help = ![ - ParseKeyword::kw_begin, - ParseKeyword::kw_done, - ParseKeyword::kw_end, - ParseKeyword::kw_fi, - ] - .contains(&self.peek_token(0).keyword); + let naked_invocation_invokes_help = ![ParseKeyword::kw_begin, ParseKeyword::kw_end] + .contains(&self.peek_token(0).keyword); if naked_invocation_invokes_help && [ParseTokenType::end, ParseTokenType::terminate] .contains(&self.peek_token(1).typ) @@ -3943,7 +3864,7 @@ fn new_decorated_statement(slf: &mut Populator<'_>) -> StatementVariant { let embedded = self.allocate_visit::(); StatementVariant::SwitchStatement(embedded) } - ParseKeyword::kw_done | ParseKeyword::kw_end | ParseKeyword::kw_fi => { + ParseKeyword::kw_end => { // 'end' is forbidden as a command. // For example, `if end` or `while end` will produce this error. // We still have to descend into the decorated statement because @@ -4115,7 +4036,7 @@ fn visit_keyword(&mut self, keyword: &mut dyn Keyword) -> VisitResult { // Special error reporting for keyword_t. let allowed_keywords = keyword.allowed_keywords(); - if allowed_keywords.contains(&ParseKeyword::kw_end) { + if keyword.allowed_keywords() == [ParseKeyword::kw_end] { return VisitResult::Break(MissingEndError { allowed_keywords, token: *self.peek_token(0), diff --git a/src/builtins/shared.rs b/src/builtins/shared.rs index 54628c799..400939772 100644 --- a/src/builtins/shared.rs +++ b/src/builtins/shared.rs @@ -209,14 +209,6 @@ struct BuiltinData { name: L!("disown"), func: disown::disown, }, - BuiltinData { - name: L!("do"), - func: builtin_generic, - }, - BuiltinData { - name: L!("done"), - func: builtin_generic, - }, BuiltinData { name: L!("echo"), func: echo::echo, @@ -253,10 +245,6 @@ struct BuiltinData { name: L!("fg"), func: fg::fg, }, - BuiltinData { - name: L!("fi"), - func: builtin_generic, - }, BuiltinData { name: L!("fish_indent"), func: fish_indent::fish_indent, @@ -357,10 +345,6 @@ struct BuiltinData { name: L!("test"), func: test::test, }, - BuiltinData { - name: L!("then"), - func: builtin_generic, - }, BuiltinData { name: L!("time"), func: builtin_generic, @@ -520,8 +504,6 @@ pub fn builtin_get_desc(name: &wstr) -> Option<&'static wstr> { _ if name == "continue" => wgettext!("Skip over remaining innermost loop"), _ if name == "count" => wgettext!("Count the number of arguments"), _ if name == "disown" => wgettext!("Remove job from job list"), - _ if name == "do" => wgettext!("Optional after a loop header"), - _ if name == "done" => wgettext!("Alternative to 'end', to end a block of commands"), _ if name == "echo" => wgettext!("Print arguments"), _ if name == "else" => wgettext!("Evaluate block if condition is false"), _ if name == "emit" => wgettext!("Emit an event"), @@ -531,7 +513,6 @@ pub fn builtin_get_desc(name: &wstr) -> Option<&'static wstr> { _ if name == "exit" => wgettext!("Exit the shell"), _ if name == "false" => wgettext!("Return an unsuccessful result"), _ if name == "fg" => wgettext!("Send job to foreground"), - _ if name == "fi" => wgettext!("Alternative to 'end', to end a block of commands"), _ if name == "fish_key_reader" => wgettext!("explore what characters keyboard keys send"), _ if name == "for" => wgettext!("Perform a set of commands multiple times"), _ if name == "function" => wgettext!("Define a new function"), @@ -550,7 +531,6 @@ pub fn builtin_get_desc(name: &wstr) -> Option<&'static wstr> { _ if name == "realpath" => wgettext!("Show absolute path sans symlinks"), _ if name == "return" => wgettext!("Stop the currently evaluated function"), _ if name == "set" => wgettext!("Handle environment variables"), - _ if name == "then" => wgettext!("Optional after the condition of an if-statement"), _ if name == "set_color" => wgettext!("Set the terminal color"), _ if name == "source" => wgettext!("Evaluate contents of file"), _ if name == "status" => wgettext!("Return status information about fish"), diff --git a/src/highlight/highlight.rs b/src/highlight/highlight.rs index 16a738b00..8356f245b 100644 --- a/src/highlight/highlight.rs +++ b/src/highlight/highlight.rs @@ -846,18 +846,14 @@ fn visit_keyword(&mut self, node: &dyn Keyword) { | ParseKeyword::kw_builtin | ParseKeyword::kw_case | ParseKeyword::kw_command - | ParseKeyword::kw_do - | ParseKeyword::kw_done | ParseKeyword::kw_else | ParseKeyword::kw_end | ParseKeyword::kw_exec - | ParseKeyword::kw_fi | ParseKeyword::kw_for | ParseKeyword::kw_function | ParseKeyword::kw_if | ParseKeyword::kw_in | ParseKeyword::kw_switch - | ParseKeyword::kw_then | ParseKeyword::kw_while => role = HighlightRole::keyword, ParseKeyword::kw_and | ParseKeyword::kw_or diff --git a/src/parse_constants.rs b/src/parse_constants.rs index 7e5888d57..4ad84fe9c 100644 --- a/src/parse_constants.rs +++ b/src/parse_constants.rs @@ -92,13 +92,10 @@ pub enum ParseKeyword { kw_builtin, kw_case, kw_command, - kw_do, - kw_done, kw_else, kw_end, kw_exclam, kw_exec, - kw_fi, kw_for, kw_function, kw_if, @@ -106,7 +103,6 @@ pub enum ParseKeyword { kw_not, kw_or, kw_switch, - kw_then, kw_time, kw_while, } @@ -241,13 +237,10 @@ pub fn to_wstr(self) -> &'static wstr { ParseKeyword::kw_builtin => L!("builtin"), ParseKeyword::kw_case => L!("case"), ParseKeyword::kw_command => L!("command"), - ParseKeyword::kw_do => L!("do"), - ParseKeyword::kw_done => L!("done"), ParseKeyword::kw_else => L!("else"), ParseKeyword::kw_end => L!("end"), ParseKeyword::kw_exclam => L!("!"), ParseKeyword::kw_exec => L!("exec"), - ParseKeyword::kw_fi => L!("fi"), ParseKeyword::kw_for => L!("for"), ParseKeyword::kw_function => L!("function"), ParseKeyword::kw_if => L!("if"), @@ -255,7 +248,6 @@ pub fn to_wstr(self) -> &'static wstr { ParseKeyword::kw_not => L!("not"), ParseKeyword::kw_or => L!("or"), ParseKeyword::kw_switch => L!("switch"), - ParseKeyword::kw_then => L!("then"), ParseKeyword::kw_time => L!("time"), ParseKeyword::kw_while => L!("while"), _ => L!("unknown_keyword"), @@ -278,13 +270,10 @@ fn from(s: &wstr) -> Self { _ if s == "builtin" => ParseKeyword::kw_builtin, _ if s == "case" => ParseKeyword::kw_case, _ if s == "command" => ParseKeyword::kw_command, - _ if s == "do" => ParseKeyword::kw_do, - _ if s == "done" => ParseKeyword::kw_done, _ if s == "else" => ParseKeyword::kw_else, _ if s == "end" => ParseKeyword::kw_end, _ if s == "exec" => ParseKeyword::kw_exec, _ if s == "for" => ParseKeyword::kw_for, - _ if s == "fi" => ParseKeyword::kw_fi, _ if s == "function" => ParseKeyword::kw_function, _ if s == "if" => ParseKeyword::kw_if, _ if s == "in" => ParseKeyword::kw_in, @@ -292,7 +281,6 @@ fn from(s: &wstr) -> Self { _ if s == "or" => ParseKeyword::kw_or, _ if s == "switch" => ParseKeyword::kw_switch, _ if s == "time" => ParseKeyword::kw_time, - _ if s == "then" => ParseKeyword::kw_then, _ if s == "while" => ParseKeyword::kw_while, _ => ParseKeyword::none, } diff --git a/src/parse_tree.rs b/src/parse_tree.rs index 6922b5402..eb940eba6 100644 --- a/src/parse_tree.rs +++ b/src/parse_tree.rs @@ -15,7 +15,7 @@ use crate::wcstringutil::count_newlines; /// A struct representing the token type that we use internally. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy)] pub struct ParseToken { /// The type of the token as represented by the parser pub typ: ParseTokenType, diff --git a/src/parser_keywords.rs b/src/parser_keywords.rs index f56e36fc1..3cb110b2f 100644 --- a/src/parser_keywords.rs +++ b/src/parser_keywords.rs @@ -50,13 +50,10 @@ macro_rules! reserved_words { ("case"), ("command", [subcommand]), ("continue"), - ("do", [subcommand]), - ("done"), ("else", [subcommand]), ("end"), ("eval"), ("exec", [subcommand]), - ("fi"), ("for"), ("function"), ("if", [subcommand]), @@ -68,7 +65,6 @@ macro_rules! reserved_words { ("status"), ("string"), ("switch"), - ("then"), ("test"), ("time", [subcommand]), ("while", [subcommand]), diff --git a/tests/checks/indent.fish b/tests/checks/indent.fish index 89ca9d4f9..911d92187 100644 --- a/tests/checks/indent.fish +++ b/tests/checks/indent.fish @@ -614,12 +614,3 @@ echo 'echo "foo" "bar"' > $tmpdir/indent_test.fish $fish_indent --write $tmpdir/indent_test.fish cat $tmpdir/indent_test.fish # CHECK: echo foo bar - -# TODO: We should not force the line break. -echo 'if true; then - echo body -fi' | $fish_indent -# CHECK: if true -# CHECK: then -# CHECK: {{ }}echo body -# CHECK: fi