diff --git a/parser.cpp b/parser.cpp index 49e5a9661..72b46c9f8 100644 --- a/parser.cpp +++ b/parser.cpp @@ -152,7 +152,7 @@ The fish parser. Contains functions for parsing and evaluating code. #define INVALID_END_ERR_MSG _( L"'end' command outside of block") /** - Error message for Posix-style assignment + Error message for Posix-style assignment: foo=bar */ #define COMMAND_ASSIGN_ERR_MSG _( L"Unknown command '%ls'. Did you mean 'set %ls %ls'? See the help section on the set command by typing 'help set'.") @@ -2014,8 +2014,6 @@ int parser_t::parse_job(process_t *p, const wchar_t *cmd = args.at(0).completion.c_str(); - fprintf(stderr, "arg count: %lu\n", args.size()); - /* We couldn't find the specified command. @@ -2034,19 +2032,39 @@ int parser_t::parse_job(process_t *p, and zsh). */ - if (wcschr(cmd, L'=')) + const wchar_t * const equals_ptr = wcschr(cmd, L'='); + if (equals_ptr != NULL) { - wchar_t *cpy = wcsdup(cmd); - wchar_t *valpart = wcschr(cpy, L'='); - *valpart++=0; - - debug(0, - COMMAND_ASSIGN_ERR_MSG, - cmd, - cpy, - valpart); - free(cpy); - + /* Try to figure out if this is a pure variable assignment (foo=bar), or if this appears to be running a command (foo=bar ruby...) */ + + const wcstring name_str = wcstring(cmd, equals_ptr - cmd); //variable name, up to the = + const wcstring val_str = wcstring(equals_ptr + 1); //variable value, past the = + + wcstring next_str; + if (tok_peek_next(tok, &next_str) == TOK_STRING && ! next_str.empty()) + { + wcstring ellipsis_str = wcstring(1, ellipsis_char); + if (ellipsis_str == L"$") + ellipsis_str = L"..."; + + /* Looks like a command */ + debug(0, + _( L"Unknown command '%ls'. Did you mean to run %ls with a modified environment? Try 'env %ls=%ls %ls%ls'. See the help section on the set command by typing 'help set'."), + cmd, + next_str.c_str(), + name_str.c_str(), + val_str.c_str(), + next_str.c_str(), + ellipsis_str.c_str()); + } + else + { + debug(0, + COMMAND_ASSIGN_ERR_MSG, + cmd, + name_str.c_str(), + val_str.c_str()); + } } else if (cmd[0]==L'$' || cmd[0] == VARIABLE_EXPAND || cmd[0] == VARIABLE_EXPAND_SINGLE) { diff --git a/tokenizer.cpp b/tokenizer.cpp index 62094f92c..567b03dcd 100644 --- a/tokenizer.cpp +++ b/tokenizer.cpp @@ -641,6 +641,31 @@ void tok_next(tokenizer_t *tok) } +enum token_type tok_peek_next(tokenizer_t *tok, wcstring *out_next_string) +{ + if (out_next_string != NULL) + { + out_next_string->clear(); + } + + enum token_type result = TOK_END; + if (tok_has_next(tok)) + { + int saved = tok_get_pos(tok); + tok_next(tok); + result = tok_last_type(tok); + + if (out_next_string != NULL) + { + const wchar_t *last = tok_last(tok); + out_next_string->assign(last ? last : L""); + } + + tok_set_pos(tok, saved); + } + return result; +} + const wchar_t *tok_string(tokenizer_t *tok) { return tok?tok->orig_buff:0; diff --git a/tokenizer.h b/tokenizer.h index 42516a1b5..027f2d6d7 100644 --- a/tokenizer.h +++ b/tokenizer.h @@ -145,6 +145,9 @@ int tok_has_next(tokenizer_t *tok); */ int tok_get_pos(tokenizer_t *tok); +/** Returns the token type after the current one, without adjusting the position. Optionally returns the next string by reference. */ +enum token_type tok_peek_next(tokenizer_t *tok, wcstring *out_next_string); + /** Returns the original string to tokenizer */