Eliminate the global list of scoped transient commandlines

Store this in a parser's libdata instead.
This commit is contained in:
ridiculousfish 2019-06-09 14:11:25 -07:00
parent 421cf92380
commit 1baa479bbf
5 changed files with 20 additions and 55 deletions

View file

@ -85,24 +85,6 @@ wcstring_list_t builtin_get_names();
void builtin_get_names(std::vector<completion_t> *list); void builtin_get_names(std::vector<completion_t> *list);
const wchar_t *builtin_get_desc(const wcstring &b); const wchar_t *builtin_get_desc(const wcstring &b);
/// Support for setting and removing transient command lines. This is used by
/// 'complete -C' in order to make the commandline builtin operate on the string
/// to complete instead of operating on whatever is to be completed. It's also
/// used by completion wrappers, to allow a command to appear as the command
/// being wrapped for the purposes of completion.
///
/// Instantiating an instance of builtin_commandline_scoped_transient_t pushes
/// the command as the new transient commandline. The destructor removes it. It
/// will assert if construction/destruction does not happen in a stack-like
/// (LIFO) order.
class builtin_commandline_scoped_transient_t {
size_t token;
public:
explicit builtin_commandline_scoped_transient_t(const wcstring &cmd);
~builtin_commandline_scoped_transient_t();
};
wcstring builtin_help_get(parser_t &parser, const wchar_t *cmd); wcstring builtin_help_get(parser_t &parser, const wchar_t *cmd);
void builtin_print_help(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, void builtin_print_help(parser_t &parser, io_streams_t &streams, const wchar_t *cmd,

View file

@ -12,6 +12,7 @@
#include "input.h" #include "input.h"
#include "io.h" #include "io.h"
#include "parse_util.h" #include "parse_util.h"
#include "parser.h"
#include "proc.h" #include "proc.h"
#include "reader.h" #include "reader.h"
#include "tokenizer.h" #include "tokenizer.h"
@ -35,36 +36,6 @@ enum {
APPEND_MODE // insert at end of current token/command/buffer APPEND_MODE // insert at end of current token/command/buffer
}; };
static owning_lock<wcstring_list_t> &get_transient_stack() {
ASSERT_IS_MAIN_THREAD();
static owning_lock<wcstring_list_t> s_transient_stack;
return s_transient_stack;
}
static bool get_top_transient(wcstring *out_result) {
auto stack = get_transient_stack().acquire();
if (stack->empty()) {
return false;
}
out_result->assign(stack->back());
return true;
}
builtin_commandline_scoped_transient_t::builtin_commandline_scoped_transient_t(
const wcstring &cmd) {
ASSERT_IS_MAIN_THREAD();
auto stack = get_transient_stack().acquire();
stack->push_back(cmd);
this->token = stack->size();
}
builtin_commandline_scoped_transient_t::~builtin_commandline_scoped_transient_t() {
ASSERT_IS_MAIN_THREAD();
auto stack = get_transient_stack().acquire();
assert(this->token == stack->size());
stack->pop_back();
}
/// Replace/append/insert the selection with/at/after the specified string. /// Replace/append/insert the selection with/at/after the specified string.
/// ///
/// \param begin beginning of selection /// \param begin beginning of selection
@ -178,8 +149,10 @@ int builtin_commandline(parser_t &parser, io_streams_t &streams, wchar_t **argv)
int paging_mode = 0; int paging_mode = 0;
const wchar_t *begin = NULL, *end = NULL; const wchar_t *begin = NULL, *end = NULL;
const auto &ld = parser.libdata();
wcstring transient_commandline; wcstring transient_commandline;
if (get_top_transient(&transient_commandline)) { if (!ld.transient_commandlines.empty()) {
transient_commandline = ld.transient_commandlines.back();
current_buffer = transient_commandline.c_str(); current_buffer = transient_commandline.c_str();
current_cursor_pos = transient_commandline.size(); current_cursor_pos = transient_commandline.size();
} else { } else {

View file

@ -329,9 +329,10 @@ int builtin_complete(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
parse_util_token_extent(do_complete_param.c_str(), do_complete_param.size(), &token, 0, 0, parse_util_token_extent(do_complete_param.c_str(), do_complete_param.size(), &token, 0, 0,
0); 0);
// Create a scoped transient command line, so that bulitin_commandline will see our // Create a scoped transient command line, so that builtin_commandline will see our
// argument, not the reader buffer. // argument, not the reader buffer.
builtin_commandline_scoped_transient_t temp_buffer(do_complete_param); parser.libdata().transient_commandlines.push_back(do_complete_param);
cleanup_t remove_transient([&] { parser.libdata().transient_commandlines.pop_back(); });
if (parser.libdata().builtin_complete_recursion_level < 1) { if (parser.libdata().builtin_complete_recursion_level < 1) {
parser.libdata().builtin_complete_recursion_level++; parser.libdata().builtin_complete_recursion_level++;

View file

@ -1557,15 +1557,19 @@ void completer_t::perform() {
// Perhaps set a transient commandline so that custom completions // Perhaps set a transient commandline so that custom completions
// buitin_commandline will refer to the wrapped command. But not if // buitin_commandline will refer to the wrapped command. But not if
// we're doing autosuggestions. // we're doing autosuggestions.
std::unique_ptr<builtin_commandline_scoped_transient_t> bcst; bool wants_transient =
if (depth > 0 && !(flags & completion_request_t::autosuggestion)) { depth > 0 && !(flags & completion_request_t::autosuggestion);
bcst = make_unique<builtin_commandline_scoped_transient_t>(cmdline); if (wants_transient) {
parser->libdata().transient_commandlines.push_back(cmdline);
} }
// Now invoke any custom completions for this command. // Now invoke any custom completions for this command.
if (!complete_param(cmd, previous_argument_unescape, if (!complete_param(cmd, previous_argument_unescape,
current_argument_unescape, !had_ddash)) { current_argument_unescape, !had_ddash)) {
do_file = false; do_file = false;
} }
if (wants_transient) {
parser->libdata().transient_commandlines.pop_back();
}
}; };
walk_wrap_chain(cmd, *cmd_node.source_range(), receiver); walk_wrap_chain(cmd, *cmd_node.source_range(), receiver);
} }

View file

@ -163,7 +163,12 @@ struct library_data_t {
const wchar_t *current_filename{}; const wchar_t *current_filename{};
/// List of events that have been sent but have not yet been delivered because they are blocked. /// List of events that have been sent but have not yet been delivered because they are blocked.
std::vector<shared_ptr<event_t>> blocked_events; std::vector<shared_ptr<event_t>> blocked_events{};
/// A stack of fake values to be returned by builtin_commandline. This is used by the completion
/// machinery when wrapping: e.g. if `tig` wraps `git` then git completions need to see git on
/// the command line.
wcstring_list_t transient_commandlines{};
}; };
class parser_t : public std::enable_shared_from_this<parser_t> { class parser_t : public std::enable_shared_from_this<parser_t> {