diff --git a/src/parse_util.cpp b/src/parse_util.cpp index a0a41f350..870b081e6 100644 --- a/src/parse_util.cpp +++ b/src/parse_util.cpp @@ -1124,6 +1124,16 @@ static bool detect_errors_in_decorated_statement(const wcstring &buff_src, } } + // $status specifically is invalid as a command, + // to avoid people trying `if $status`. + // We see this surprisingly regularly. + const wcstring &com = dst.command.source(buff_src, storage); + if (com == L"$status") { + parse_error_offset_source_start(parse_errors, source_start); + errored = append_syntax_error(parse_errors, source_start, + _(L"$status is not valid as a command. See `help conditions`")); + } + const wcstring &unexp_command = dst.command.source(buff_src, storage); if (!unexp_command.empty()) { wcstring command; diff --git a/tests/checks/vars_as_commands.fish b/tests/checks/vars_as_commands.fish index 55c8bb178..405472e13 100644 --- a/tests/checks/vars_as_commands.fish +++ b/tests/checks/vars_as_commands.fish @@ -1,4 +1,4 @@ -#RUN: %fish %s +#RUN: %fish -C 'set -g fish (builtin realpath %fish)' %s # Test that using variables as command names work correctly. $EMPTY_VARIABLE @@ -27,4 +27,24 @@ set CMD3 /usr/bin $CMD3 && echo $PWD #CHECK: /usr/bin +# $status specifically is not valid, to avoid a common error +# with `if $status` +echo 'if $status; echo foo; end' | $fish --no-config +#CHECKERR: fish: $status is not valid as a command. See `help conditions` +#CHECKERR: if $status; echo foo; end +#CHECKERR: ^ +echo 'not $status' | $fish --no-config +#CHECKERR: fish: $status is not valid as a command. See `help conditions` +#CHECKERR: not $status +#CHECKERR: ^ + +# Script doesn't run at all. +echo 'echo foo; and $status' | $fish --no-config +#CHECKERR: fish: $status is not valid as a command. See `help conditions` +#CHECKERR: echo foo; and $status +#CHECKERR: ^ + +echo 'set -l status_cmd true; if $status_cmd; echo Heck yes this is true; end' | $fish --no-config +#CHECK: Heck yes this is true + exit 0