Thread a parser into reader

Eliminates uses of principal_parser
This commit is contained in:
ridiculousfish 2019-05-26 18:51:26 -07:00
parent 7ed1022cf4
commit d5f2d472d0
6 changed files with 45 additions and 45 deletions

View File

@ -316,7 +316,7 @@ static int builtin_breakpoint(parser_t &parser, io_streams_t &streams, wchar_t *
}
const block_t *bpb = parser.push_block(block_t::breakpoint_block());
reader_read(STDIN_FILENO, streams.io_chain ? *streams.io_chain : io_chain_t());
reader_read(parser, STDIN_FILENO, streams.io_chain ? *streams.io_chain : io_chain_t());
parser.pop_block(bpb);
return parser.get_last_status();
}

View File

@ -205,7 +205,7 @@ static int read_interactive(parser_t &parser, wcstring &buff, int nchars, bool s
const auto &vars = parser.vars();
wcstring read_history_ID = history_session_id(vars);
if (!read_history_ID.empty()) read_history_ID += L"_read";
reader_push(read_history_ID);
reader_push(parser, read_history_ID);
reader_set_left_prompt(prompt);
reader_set_right_prompt(right_prompt);

View File

@ -83,7 +83,7 @@ int builtin_source(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
null_terminated_array_t<wchar_t>::to_list(argv + optind + (argc == optind ? 0 : 1));
parser.vars().set_argv(std::move(argv_list));
retval = reader_read(fd, streams.io_chain ? *streams.io_chain : io_chain_t());
retval = reader_read(parser, fd, streams.io_chain ? *streams.io_chain : io_chain_t());
parser.pop_block(sb);

View File

@ -451,7 +451,7 @@ int main(int argc, char **argv) {
reader_set_end_loop(false);
} else if (my_optind == argc) {
// Implicitly interactive mode.
res = reader_read(STDIN_FILENO, {});
res = reader_read(parser, STDIN_FILENO, {});
} else {
char *file = *(argv + (my_optind++));
int fd = open(file, O_RDONLY);
@ -471,7 +471,7 @@ int main(int argc, char **argv) {
wcstring rel_filename = str2wcstring(file);
scoped_push<const wchar_t *> filename_push{&ld.current_filename,
intern(rel_filename.c_str())};
res = reader_read(fd, {});
res = reader_read(parser, fd, {});
if (res) {
debug(1, _(L"Error while reading file %ls\n"),
ld.current_filename ? ld.current_filename : _(L"Standard input"));

View File

@ -148,7 +148,7 @@ namespace {
/// Test if the given string contains error. Since this is the error detection for general purpose,
/// there are no invalid strings, so this function always returns false.
parser_test_error_bits_t default_test(const wcstring &b) {
parser_test_error_bits_t default_test(parser_t &parser, const wcstring &b) {
UNUSED(b);
return 0;
}
@ -323,6 +323,8 @@ struct readline_loop_state_t;
/// reader_readline() calls are nested. This happens when the 'read' builtin is used.
class reader_data_t : public std::enable_shared_from_this<reader_data_t> {
public:
/// The parser being used.
std::shared_ptr<parser_t> parser_ref;
/// String containing the whole current commandline.
editable_line_t command_line;
/// String containing the autosuggestion.
@ -420,14 +422,14 @@ class reader_data_t : public std::enable_shared_from_this<reader_data_t> {
void repaint_if_needed();
/// Return the variable set used for e.g. command duration.
env_stack_t &vars() { return parser_t::principal_parser().vars(); }
env_stack_t &vars() { return parser_ref->vars(); }
const env_stack_t &vars() const { return parser_ref->vars(); }
/// Hackish access to the parser. TODO: rationalize this.
parser_t &parser() { return parser_t::principal_parser(); }
/// Access the parser.
parser_t &parser() { return *parser_ref; }
const env_stack_t &vars() const { return parser_t::principal_parser().vars(); }
reader_data_t(history_t *hist) : history(hist) {}
reader_data_t(std::shared_ptr<parser_t> parser, history_t *hist)
: parser_ref(std::move(parser)), history(hist) {}
void update_buff_pos(editable_line_t *el, size_t buff_pos);
void repaint();
@ -1238,9 +1240,9 @@ void reader_data_t::completion_insert(const wchar_t *val, complete_flags_t flags
// Returns a function that can be invoked (potentially
// on a background thread) to determine the autosuggestion
static std::function<autosuggestion_result_t(void)> get_autosuggestion_performer(
const wcstring &search_string, size_t cursor_pos, history_t *history) {
parser_t &parser, const wcstring &search_string, size_t cursor_pos, history_t *history) {
const unsigned int generation_count = read_generation_count();
auto vars = parser_t::principal_parser().vars().snapshot();
auto vars = parser.vars().snapshot();
const wcstring working_directory = vars->get_pwd_slash();
// TODO: suspicious use of 'history' here
// This is safe because histories are immortal, but perhaps
@ -1331,7 +1333,7 @@ void reader_data_t::update_autosuggestion() {
autosuggestion.clear();
if (can_autosuggest()) {
const editable_line_t *el = active_edit_line();
auto performer = get_autosuggestion_performer(el->text, el->position, history);
auto performer = get_autosuggestion_performer(parser(), el->text, el->position, history);
auto shared_this = this->shared_from_this();
iothread_perform(performer, [shared_this](autosuggestion_result_t result) {
shared_this->autosuggest_completed(std::move(result));
@ -1943,7 +1945,7 @@ void reader_run_command(parser_t &parser, const wcstring &cmd) {
}
}
parser_test_error_bits_t reader_shell_test(const wcstring &b) {
parser_test_error_bits_t reader_shell_test(parser_t &parser, const wcstring &b) {
wcstring bstr = b;
// Append a newline, to act as a statement terminator.
@ -1955,7 +1957,7 @@ parser_test_error_bits_t reader_shell_test(const wcstring &b) {
if (res & PARSER_TEST_ERROR) {
wcstring error_desc;
parser_t::principal_parser().get_backtrace(bstr, errors, error_desc);
parser.get_backtrace(bstr, errors, error_desc);
// Ensure we end with a newline. Also add an initial newline, because it's likely the user
// just hit enter and so there's junk on the current line.
@ -2001,8 +2003,9 @@ void reader_data_t::highlight_complete(highlight_result_t result) {
// Given text, bracket matching position, and whether IO is allowed,
// return a function that performs highlighting. The function may be invoked on a background thread.
static std::function<highlight_result_t(void)> get_highlight_performer(
const wcstring &text, long match_highlight_pos, highlight_function_t highlight_func) {
auto vars = parser_t::principal_parser().vars().snapshot();
parser_t &parser, const wcstring &text, long match_highlight_pos,
highlight_function_t highlight_func) {
auto vars = parser.vars().snapshot();
unsigned int generation_count = read_generation_count();
return [=]() -> highlight_result_t {
if (text.empty()) return {};
@ -2034,7 +2037,7 @@ void reader_data_t::super_highlight_me_plenty(int match_highlight_pos_adjust, bo
sanity_check();
auto highlight_performer = get_highlight_performer(
el->text, match_highlight_pos, no_io ? highlight_shell_no_io : highlight_func);
parser(), el->text, match_highlight_pos, no_io ? highlight_shell_no_io : highlight_func);
if (no_io) {
// Highlighting without IO, we just do it.
highlight_complete(highlight_performer());
@ -2083,9 +2086,9 @@ void reader_change_history(const wcstring &name) {
}
}
void reader_push(const wcstring &name) {
void reader_push(parser_t &parser, const wcstring &name) {
history_t *hist = &history_t::history_with_name(name);
reader_data_stack.push_back(std::make_shared<reader_data_t>(hist));
reader_data_stack.push_back(std::make_shared<reader_data_t>(parser.shared(), hist));
reader_data_t *data = current_data();
data->command_line_changed(&data->command_line);
if (reader_data_stack.size() == 1) {
@ -2222,9 +2225,8 @@ static relaxed_atomic_t<uint64_t> run_count{0};
uint64_t reader_run_count() { return run_count; }
/// Read interactively. Read input from stdin while providing editing facilities.
static int read_i() {
parser_t &parser = parser_t::principal_parser();
reader_push(history_session_id(parser.vars()));
static int read_i(parser_t &parser) {
reader_push(parser, history_session_id(parser.vars()));
reader_set_complete_function(&complete);
reader_set_highlight_function(&highlight_shell);
reader_set_test_function(&reader_shell_test);
@ -2413,7 +2415,7 @@ maybe_t<char_event_t> reader_data_t::read_normal_chars(readline_loop_state_t &rl
/// Handle a readline command \p c, updating the state \p rls.
void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_state_t &rls) {
const auto &vars = parser_t::principal_parser().vars();
const auto &vars = this->vars();
using rl = readline_cmd_t;
switch (c) {
// Go to beginning of line.
@ -2460,10 +2462,10 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
// may sometimes take a while but when switching the mode all we care about is the
// mode-prompt.
//
// Because some users set `fish_mode_prompt` to an empty function and display the mode elsewhere,
// we detect if the mode output is empty.
// Because some users set `fish_mode_prompt` to an empty function and display the mode
// elsewhere, we detect if the mode output is empty.
exec_mode_prompt();
if(!mode_prompt_buff.empty()) {
if (!mode_prompt_buff.empty()) {
s_reset(&screen, screen_reset_current_line_and_prompt);
screen_reset_needed = false;
repaint();
@ -2547,9 +2549,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
// std::fwprintf(stderr, L"Complete (%ls)\n", buffcpy.c_str());
completion_request_flags_t complete_flags = {completion_request_t::descriptions,
completion_request_t::fuzzy_match};
// TODO: eliminate this principal_parser.
complete_func(buffcpy, &rls.comp, complete_flags, vars,
parser_t::principal_parser().shared());
complete_func(buffcpy, &rls.comp, complete_flags, vars, parser_ref);
// Munge our completions.
completions_sort_and_prioritize(&rls.comp);
@ -2725,7 +2725,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
}
// See if this command is valid.
int command_test_result = test_func(el->text);
int command_test_result = test_func(parser(), el->text);
if (command_test_result == 0 || command_test_result == PARSER_TEST_INCOMPLETE) {
// This command is valid, but an abbreviation may make it invalid. If so, we
// will have to test again.
@ -2733,7 +2733,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
if (abbreviation_expanded) {
// It's our reponsibility to rehighlight and repaint. But everything we do
// below triggers a repaint.
command_test_result = test_func(el->text.c_str());
command_test_result = test_func(parser(), el->text.c_str());
// If the command is OK, then we're going to execute it. We still want to do
// syntax highlighting, but a synchronous variant that performs no I/O, so
@ -3257,7 +3257,8 @@ maybe_t<wcstring> reader_data_t::readline(int nchars_or_0) {
handle_readline_command(readline_cmd, rls);
if (command_ends_history_search(readline_cmd)) {
// "cancel" means to abort the whole thing, other ending commands mean to finish the search.
// "cancel" means to abort the whole thing, other ending commands mean to finish the
// search.
if (history_search.active() && readline_cmd == rl::cancel) {
history_search.go_to_end();
update_command_line_from_history_search();
@ -3449,8 +3450,7 @@ bool reader_get_selection(size_t *start, size_t *len) {
/// Read non-interactively. Read input from stdin without displaying the prompt, using syntax
/// highlighting. This is used for reading scripts and init files.
static int read_ni(int fd, const io_chain_t &io) {
parser_t &parser = parser_t::principal_parser();
static int read_ni(parser_t &parser, int fd, const io_chain_t &io) {
FILE *in_stream;
wchar_t *buff = 0;
std::vector<char> acc;
@ -3524,7 +3524,7 @@ static int read_ni(int fd, const io_chain_t &io) {
return res;
}
int reader_read(int fd, const io_chain_t &io) {
int reader_read(parser_t &parser, int fd, const io_chain_t &io) {
int res;
// If reader_read is called recursively through the '.' builtin, we need to preserve
@ -3546,7 +3546,7 @@ int reader_read(int fd, const io_chain_t &io) {
}
proc_push_interactive(inter);
res = shell_is_interactive() ? read_i() : read_ni(fd, io);
res = shell_is_interactive() ? read_i(parser) : read_ni(parser, fd, io);
// If the exit command was called in a script, only exit the script, not the program.
reader_set_end_loop(false);

View File

@ -47,7 +47,7 @@ class editable_line_t {
};
/// Read commands from \c fd until encountering EOF.
int reader_read(int fd, const io_chain_t &io);
int reader_read(parser_t &parser, int fd, const io_chain_t &io);
/// Tell the shell whether it should exit after the currently running command finishes.
void reader_set_end_loop(bool flag);
@ -140,7 +140,7 @@ bool reader_thread_job_is_stale();
maybe_t<wcstring> reader_readline(int nchars);
/// Push a new reader environment.
void reader_push(const wcstring &name);
void reader_push(parser_t &parser, const wcstring &name);
/// Return to previous reader environment.
void reader_pop();
@ -152,11 +152,11 @@ typedef void (*complete_function_t)(const wcstring &, std::vector<completion_t>
void reader_set_complete_function(complete_function_t);
/// The type of a highlight function.
typedef void (*highlight_function_t)(const wcstring &, std::vector<highlight_spec_t> &, size_t,
wcstring_list_t *, const environment_t &vars);
using highlight_function_t = void (*)(const wcstring &, std::vector<highlight_spec_t> &, size_t,
wcstring_list_t *, const environment_t &vars);
/// Function type for testing if a string is valid for the reader to return.
using test_function_t = parser_test_error_bits_t (*)(const wcstring &);
using test_function_t = parser_test_error_bits_t (*)(parser_t &, const wcstring &);
/// Specify function for syntax highlighting. The function must take these arguments:
///
@ -198,7 +198,7 @@ bool reader_exit_forced();
/// Test if the given shell command contains errors. Uses parser_test for testing. Suitable for
/// reader_set_test_function().
parser_test_error_bits_t reader_shell_test(const wcstring &);
parser_test_error_bits_t reader_shell_test(parser_t &parser, const wcstring &);
/// Test whether the interactive reader is in search mode.
bool reader_is_in_search_mode();