aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--parse_execution.cpp14
-rw-r--r--parse_execution.h6
-rw-r--r--parser.cpp143
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);
diff --git a/parser.cpp b/parser.cpp
index 25f2619e..b361fe49 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -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;
}