mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-29 21:43:55 +08:00
Implement status -n (line number) with new parser
This commit is contained in:
parent
be33d3f2a4
commit
d232a0f951
|
@ -50,7 +50,7 @@ static wcstring profiling_cmd_name_for_redirectable_block(const parse_node_t &no
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_execution_context_t::parse_execution_context_t(const parse_node_tree_t &t, const wcstring &s, parser_t *p, int initial_eval_level) : tree(t), src(s), parser(p), eval_level(initial_eval_level)
|
parse_execution_context_t::parse_execution_context_t(const parse_node_tree_t &t, const wcstring &s, parser_t *p, int initial_eval_level) : tree(t), src(s), parser(p), eval_level(initial_eval_level), executing_node_idx(NODE_OFFSET_INVALID), cached_lineno_offset(0), cached_lineno_count(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1303,6 +1303,9 @@ parse_execution_result_t parse_execution_context_t::run_1_job(const parse_node_t
|
||||||
/* Increment the eval_level for the duration of this command */
|
/* Increment the eval_level for the duration of this command */
|
||||||
scoped_push<int> saved_eval_level(&eval_level, eval_level + 1);
|
scoped_push<int> saved_eval_level(&eval_level, eval_level + 1);
|
||||||
|
|
||||||
|
/* Save the node index */
|
||||||
|
scoped_push<node_offset_t> saved_node_offset(&executing_node_idx, this->get_offset(job_node));
|
||||||
|
|
||||||
/* Profiling support */
|
/* Profiling support */
|
||||||
long long start_time = 0, parse_time = 0, exec_time = 0;
|
long long start_time = 0, parse_time = 0, exec_time = 0;
|
||||||
profile_item_t *profile_item = this->parser->create_profile_item();
|
profile_item_t *profile_item = this->parser->create_profile_item();
|
||||||
|
@ -1525,3 +1528,58 @@ parse_execution_result_t parse_execution_context_t::eval_node_at_offset(node_off
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int parse_execution_context_t::get_current_line_number()
|
||||||
|
{
|
||||||
|
/* If we're not executing anything, return -1 */
|
||||||
|
if (this->executing_node_idx == NODE_OFFSET_INVALID)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If for some reason we're executing a node without source, return -1 */
|
||||||
|
const parse_node_t &node = tree.at(this->executing_node_idx);
|
||||||
|
if (! node.has_source())
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Count the number of newlines, leveraging our cache */
|
||||||
|
const size_t offset = tree.at(this->executing_node_idx).source_start;
|
||||||
|
assert(offset <= src.size());
|
||||||
|
|
||||||
|
/* Easy hack to handle 0 */
|
||||||
|
if (offset == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We want to return (one plus) the number of newlines at offsets less than the given offset. cached_lineno_count is the number of newlines at indexes less than cached_lineno_offset. */
|
||||||
|
const wchar_t *str = src.c_str();
|
||||||
|
if (offset > cached_lineno_offset)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = cached_lineno_offset; str[i] != L'\0' && i < offset; i++)
|
||||||
|
{
|
||||||
|
/* Add one for every newline we find in the range [cached_lineno_offset, offset) */
|
||||||
|
if (str[i] == L'\n')
|
||||||
|
{
|
||||||
|
cached_lineno_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cached_lineno_offset = i; //note: i, not offset, in case offset is beyond the length of the string
|
||||||
|
}
|
||||||
|
else if (offset < cached_lineno_offset)
|
||||||
|
{
|
||||||
|
/* Subtract one for every newline we find in the range [offset, cached_lineno_offset) */
|
||||||
|
for (size_t i = offset; i < cached_lineno_offset; i++)
|
||||||
|
{
|
||||||
|
if (str[i] == L'\n')
|
||||||
|
{
|
||||||
|
cached_lineno_count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cached_lineno_offset = offset;
|
||||||
|
}
|
||||||
|
return cached_lineno_count + 1;
|
||||||
|
}
|
||||||
|
|
|
@ -40,6 +40,13 @@ private:
|
||||||
|
|
||||||
int eval_level;
|
int eval_level;
|
||||||
|
|
||||||
|
/* The currently executing node index, used to indicate the line number */
|
||||||
|
node_offset_t executing_node_idx;
|
||||||
|
|
||||||
|
/* Cached line number information */
|
||||||
|
size_t cached_lineno_offset;
|
||||||
|
int cached_lineno_count;
|
||||||
|
|
||||||
/* No copying allowed */
|
/* No copying allowed */
|
||||||
parse_execution_context_t(const parse_execution_context_t&);
|
parse_execution_context_t(const parse_execution_context_t&);
|
||||||
parse_execution_context_t& operator=(const parse_execution_context_t&);
|
parse_execution_context_t& operator=(const parse_execution_context_t&);
|
||||||
|
@ -106,6 +113,9 @@ public:
|
||||||
/* Returns the current eval level */
|
/* Returns the current eval level */
|
||||||
int current_eval_level() const { return eval_level; }
|
int current_eval_level() const { return eval_level; }
|
||||||
|
|
||||||
|
/* Returns the current line number. Not const since it touches cached_lineno_offset */
|
||||||
|
int get_current_line_number();
|
||||||
|
|
||||||
/* 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);
|
||||||
|
|
||||||
|
|
10
parser.cpp
10
parser.cpp
|
@ -928,6 +928,16 @@ const wchar_t *parser_t::is_function() const
|
||||||
|
|
||||||
int parser_t::get_lineno() const
|
int parser_t::get_lineno() const
|
||||||
{
|
{
|
||||||
|
if (parser_use_ast())
|
||||||
|
{
|
||||||
|
int lineno = -1;
|
||||||
|
if (! execution_contexts.empty())
|
||||||
|
{
|
||||||
|
lineno = execution_contexts.back()->get_current_line_number();
|
||||||
|
}
|
||||||
|
return lineno;
|
||||||
|
}
|
||||||
|
|
||||||
int lineno;
|
int lineno;
|
||||||
|
|
||||||
if (! current_tokenizer || ! tok_string(current_tokenizer))
|
if (! current_tokenizer || ! tok_string(current_tokenizer))
|
||||||
|
|
|
@ -79,4 +79,9 @@ for $var1 in 1 2 3
|
||||||
end
|
end
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
# Test status -n
|
||||||
|
eval 'status -n
|
||||||
|
status -n
|
||||||
|
status -n'
|
||||||
|
|
||||||
false
|
false
|
||||||
|
|
|
@ -10,3 +10,6 @@ Foop
|
||||||
Doop
|
Doop
|
||||||
Testing for loop
|
Testing for loop
|
||||||
123
|
123
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
|
Loading…
Reference in New Issue
Block a user