mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Rewrite parser_t::current_line() to respect new parser
This commit is contained in:
parent
2c19ca0dbf
commit
1305c02579
3 changed files with 50 additions and 121 deletions
|
@ -1590,3 +1590,17 @@ int parse_execution_context_t::get_current_line_number()
|
||||||
}
|
}
|
||||||
return 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;
|
||||||
|
}
|
||||||
|
|
|
@ -119,6 +119,12 @@ public:
|
||||||
/* Returns the current line number, indexed from 1. Not const since it touches cached_lineno_offset */
|
/* Returns the current line number, indexed from 1. Not const since it touches cached_lineno_offset */
|
||||||
int get_current_line_number();
|
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 */
|
/* 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);
|
parse_execution_result_t eval_node_at_offset(node_offset_t offset, const block_t *associated_block, const io_chain_t &io);
|
||||||
|
|
||||||
|
|
151
parser.cpp
151
parser.cpp
|
@ -823,149 +823,58 @@ const wchar_t *parser_t::current_filename() const
|
||||||
return NULL;
|
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 parser_t::current_line()
|
||||||
{
|
{
|
||||||
wcstring lineinfo;
|
if (execution_contexts.empty())
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
return L"";
|
return wcstring();
|
||||||
|
}
|
||||||
|
const parse_execution_context_t *context = execution_contexts.back();
|
||||||
|
assert(context != NULL);
|
||||||
|
|
||||||
|
int source_offset = context->get_current_source_offset();
|
||||||
|
if (source_offset < 0)
|
||||||
|
{
|
||||||
|
return wcstring();
|
||||||
}
|
}
|
||||||
|
|
||||||
file = parser_t::current_filename();
|
const int lineno = this->get_lineno();
|
||||||
whole_str = tok_string(current_tokenizer);
|
const wchar_t *file = this->current_filename();
|
||||||
line = whole_str;
|
|
||||||
|
|
||||||
if (!line)
|
wcstring prefix;
|
||||||
return L"";
|
|
||||||
|
|
||||||
|
/* If we are not going to print a stack trace, at least print the line number and filename */
|
||||||
/*
|
|
||||||
Calculate line number, line offset, etc.
|
|
||||||
*/
|
|
||||||
for (i=0; i<current_tokenizer_pos && whole_str[i]; i++)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copy current line from whole string
|
|
||||||
*/
|
|
||||||
line_end = wcschr(line, L'\n');
|
|
||||||
if (!line_end)
|
|
||||||
line_end = line+wcslen(line);
|
|
||||||
|
|
||||||
line = wcsndup(line, line_end-line);
|
|
||||||
|
|
||||||
/**
|
|
||||||
If we are not going to print a stack trace, at least print the line number and filename
|
|
||||||
*/
|
|
||||||
if (!get_is_interactive() || is_function())
|
if (!get_is_interactive() || is_function())
|
||||||
{
|
{
|
||||||
int prev_width = my_wcswidth(lineinfo.c_str());
|
|
||||||
if (file)
|
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)
|
else if (is_within_fish_initialization)
|
||||||
{
|
{
|
||||||
append_format(lineinfo, L"%ls: ", _(L"Startup"), lineno);
|
append_format(prefix, L"%ls: ", _(L"Startup"), lineno);
|
||||||
}
|
}
|
||||||
else
|
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
|
|
||||||
|
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())
|
||||||
{
|
{
|
||||||
offset=0;
|
line_info.push_back(L'\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
parser_t::stack_trace(0, line_info);
|
||||||
/*
|
return line_info;
|
||||||
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))
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free((void *)line);
|
|
||||||
parser_t::stack_trace(0, lineinfo);
|
|
||||||
|
|
||||||
return lineinfo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue