diff --git a/parse_execution.cpp b/parse_execution.cpp index 738e39730..f2eaae251 100644 --- a/parse_execution.cpp +++ b/parse_execution.cpp @@ -691,7 +691,7 @@ parse_execution_result_t parse_execution_context_t::report_error(const parse_nod const parse_error_list_t error_list = parse_error_list_t(1, error); parser->get_backtrace(src, error_list, &backtrace_and_desc); - fprintf(stderr, "<%ls>", backtrace_and_desc.c_str()); + fprintf(stderr, "%ls", backtrace_and_desc.c_str()); } return parse_execution_errored; diff --git a/parse_tree.cpp b/parse_tree.cpp index 41ef9cf02..484b79687 100644 --- a/parse_tree.cpp +++ b/parse_tree.cpp @@ -14,7 +14,7 @@ static bool production_is_empty(const production_t *production) } /** Returns a string description of this parse error */ -wcstring parse_error_t::describe(const wcstring &src, bool skip_caret) const +wcstring parse_error_t::describe_with_prefix(const wcstring &src, const wcstring &prefix, bool skip_caret) const { wcstring result = text; if (! skip_caret && source_start < src.size() && source_start + source_length <= src.size()) @@ -53,15 +53,16 @@ wcstring parse_error_t::describe(const wcstring &src, bool skip_caret) const { result.push_back(L'\n'); } + result.append(prefix); result.append(src, line_start, line_end - line_start); - // Append the caret line. The input source may include tabs; for that reason we construct a "caret line" that has tabs in corresponding positions + const wcstring line_to_measure = prefix + wcstring(src, line_start, source_start - line_start); wcstring caret_space_line; caret_space_line.reserve(source_start - line_start); - for (size_t i=line_start; i < source_start; i++) + for (size_t i=0; i < line_to_measure.size(); i++) { - wchar_t wc = src.at(i); + wchar_t wc = line_to_measure.at(i); if (wc == L'\t') { caret_space_line.push_back(L'\t'); @@ -88,6 +89,11 @@ wcstring parse_error_t::describe(const wcstring &src, bool skip_caret) const return result; } +wcstring parse_error_t::describe(const wcstring &src) const +{ + return this->describe_with_prefix(src, wcstring(), false); +} + wcstring parse_errors_description(const parse_error_list_t &errors, const wcstring &src, const wchar_t *prefix) { wcstring target; diff --git a/parse_tree.h b/parse_tree.h index 77b29fc8a..1835183df 100644 --- a/parse_tree.h +++ b/parse_tree.h @@ -34,7 +34,10 @@ struct parse_error_t size_t source_length; /** Return a string describing the error, suitable for presentation to the user. If skip_caret is false, the offending line with a caret is printed as well */ - wcstring describe(const wcstring &src, bool skip_caret = false) const; + wcstring describe(const wcstring &src) const; + + /** Return a string describing the error, suitable for presentation to the user, with the given prefix. If skip_caret is false, the offending line with a caret is printed as well */ + wcstring describe_with_prefix(const wcstring &src, const wcstring &prefix, bool skip_caret) const; }; typedef std::vector parse_error_list_t; diff --git a/parser.cpp b/parser.cpp index 7a75911bd..4f4a050e5 100644 --- a/parser.cpp +++ b/parser.cpp @@ -3002,20 +3002,24 @@ void parser_t::get_backtrace(const wcstring &src, const parse_error_list_t &erro assert(err.source_start <= src.size()); size_t which_line = 1 + std::count(src.begin(), src.begin() + err.source_start, L'\n'); + // Don't include the caret if we're interactive, this is the first line of text, and our source is at its beginning, because then it's obvious + bool skip_caret = (get_is_interactive() && which_line == 1 && err.source_start == 0); + + wcstring prefix; + const wchar_t *filename = this->current_filename(); if (filename) { - append_format(*output, _(L"fish: line %lu of %ls:\n"), which_line, user_presentable_path(filename).c_str()); + prefix = format_string(_(L"%ls (line %lu): "), user_presentable_path(filename).c_str(), which_line); + //append_format(*output, _(L"%ls (line %lu):\n"), user_presentable_path(filename).c_str(), which_line); } else { - output->append(L"fish: "); + prefix = L"fish: "; + //output->append(L"fish: "); } - // Don't include the caret if we're interactive, this is the first line of text, and our source is at its beginning, because then it's obvious - bool skip_caret = (get_is_interactive() && which_line == 1 && err.source_start == 0); - - output->append(err.describe(src, skip_caret)); + output->append(err.describe_with_prefix(src, prefix, skip_caret)); output->push_back(L'\n'); this->stack_trace(0, *output);