diff options
-rw-r--r-- | parse_execution.cpp | 14 | ||||
-rw-r--r-- | parse_execution.h | 6 | ||||
-rw-r--r-- | parser.cpp | 143 |
3 files changed, 46 insertions, 117 deletions
diff --git a/parse_execution.cpp b/parse_execution.cpp index 0dfb85a0..127309a8 100644 --- a/parse_execution.cpp +++ b/parse_execution.cpp @@ -1590,3 +1590,17 @@ int parse_execution_context_t::get_current_line_number() } return line_number; } + +int parse_execution_context_t::get_current_source_offset() const +{ + int result = -1; + if (executing_node_idx != NODE_OFFSET_INVALID) + { + const parse_node_t &node = tree.at(executing_node_idx); + if (node.has_source()) + { + result = static_cast<int>(node.source_start); + } + } + return result; +} diff --git a/parse_execution.h b/parse_execution.h index be04c1b6..cb2ff65f 100644 --- a/parse_execution.h +++ b/parse_execution.h @@ -119,6 +119,12 @@ public: /* Returns the current line number, indexed from 1. Not const since it touches cached_lineno_offset */ int get_current_line_number(); + /* Returns the source offset, or -1 */ + int get_current_source_offset() const; + + /* Returns the source string */ + const wcstring &get_source() const { return src; } + /* Start executing at the given node offset. Returns 0 if there was no error, 1 if there was an error */ parse_execution_result_t eval_node_at_offset(node_offset_t offset, const block_t *associated_block, const io_chain_t &io); @@ -823,149 +823,58 @@ const wchar_t *parser_t::current_filename() const return NULL; } -/** - Calculates the on-screen width of the specified substring of the - specified string. This function takes into account the width and - alignment of the tab character, but other wise behaves like - repeatedly calling wcwidth. -*/ -static int printed_width(const wchar_t *str, int len) -{ - int res=0; - int i; - - CHECK(str, 0); - - for (i=0; str[i] && i<len; i++) - { - if (str[i] == L'\t') - { - res=(res+8)&~7; - } - else - { - res += fish_wcwidth(str[i]); - } - } - return res; -} - - wcstring parser_t::current_line() { - wcstring lineinfo; - - int lineno=1; - - const wchar_t *file; - const wchar_t *whole_str; - const wchar_t *line; - const wchar_t *line_end; - int i; - int offset; - int current_line_width; - const wchar_t *function_name=0; - int current_line_start=0; - - if (!current_tokenizer) + if (execution_contexts.empty()) { - return L""; + return wcstring(); } + const parse_execution_context_t *context = execution_contexts.back(); + assert(context != NULL); - file = parser_t::current_filename(); - whole_str = tok_string(current_tokenizer); - line = whole_str; - - if (!line) - return L""; - - - /* - Calculate line number, line offset, etc. - */ - for (i=0; i<current_tokenizer_pos && whole_str[i]; i++) + int source_offset = context->get_current_source_offset(); + if (source_offset < 0) { - if (whole_str[i] == L'\n') - { - lineno++; - current_line_start=i+1; - line = &whole_str[i+1]; - } - } - -// lineno = current_tokenizer_pos; - - - current_line_width=printed_width(whole_str+current_line_start, - current_tokenizer_pos-current_line_start); - - if ((function_name = is_function())) - { - lineno += function_get_definition_offset(function_name); + return wcstring(); } - /* - Copy current line from whole string - */ - line_end = wcschr(line, L'\n'); - if (!line_end) - line_end = line+wcslen(line); + const int lineno = this->get_lineno(); + const wchar_t *file = this->current_filename(); - line = wcsndup(line, line_end-line); + wcstring prefix; - /** - If we are not going to print a stack trace, at least print the line number and filename - */ + /* If we are not going to print a stack trace, at least print the line number and filename */ if (!get_is_interactive() || is_function()) { - int prev_width = my_wcswidth(lineinfo.c_str()); if (file) { - append_format(lineinfo, _(L"%ls (line %d): "), file, lineno); + append_format(prefix, _(L"%ls (line %d): "), user_presentable_path(file).c_str(), lineno); } else if (is_within_fish_initialization) { - append_format(lineinfo, L"%ls: ", _(L"Startup"), lineno); + append_format(prefix, L"%ls: ", _(L"Startup"), lineno); } else { - append_format(lineinfo, L"%ls: ", _(L"Standard input"), lineno); + append_format(prefix, L"%ls: ", _(L"Standard input"), lineno); } - offset = my_wcswidth(lineinfo.c_str()) - prev_width; - } - else - { - offset=0; } -// debug( 1, L"Current pos %d, line pos %d, file_length %d, is_interactive %d, offset %d\n", current_tokenizer_pos, current_line_pos, wcslen(whole_str), is_interactive, offset); - /* - Skip printing character position if we are in interactive mode - and the error was on the first character of the line. - */ - if (!get_is_interactive() || is_function() || (current_line_width!=0)) + bool skip_caret = get_is_interactive() && ! is_function(); + + /* Use an error with empty text */ + assert(source_offset >= 0); + parse_error_t empty_error = {}; + empty_error.source_start = source_offset; + + wcstring line_info = empty_error.describe_with_prefix(context->get_source(), prefix, skip_caret); + if (! line_info.empty()) { - // Workaround since it seems impossible to print 0 copies of a character using %*lc - if (offset+current_line_width) - { - append_format(lineinfo, - L"%ls\n%*lc^\n", - line, - offset+current_line_width, - L' '); - } - else - { - append_format(lineinfo, - L"%ls\n^\n", - line); - } + line_info.push_back(L'\n'); } - free((void *)line); - parser_t::stack_trace(0, lineinfo); - - return lineinfo; + parser_t::stack_trace(0, line_info); + return line_info; } |