highlighter: pass the cursor position to the highlighter

This allows the next commit to correct highlighting based on the cursor
position.
This commit is contained in:
Johannes Altmanninger 2022-10-26 09:30:46 +02:00
parent 861ac00a61
commit 6667c9f50c
4 changed files with 24 additions and 14 deletions

View file

@ -5746,7 +5746,7 @@ static void test_highlighting() {
do_test(expected_colors.size() == text.size());
std::vector<highlight_spec_t> colors(text.size());
highlight_shell(text, colors, operation_context_t{vars}, true /* io_ok */);
highlight_shell(text, colors, operation_context_t{vars}, true /* io_ok */, text.size());
if (expected_colors.size() != colors.size()) {
err(L"Color vector has wrong size! Expected %lu, actual %lu", expected_colors.size(),

View file

@ -773,6 +773,8 @@ class highlighter_t {
// The string we're highlighting. Note this is a reference memmber variable (to avoid copying)!
// We must not outlive this!
const wcstring &buff;
// The position of the cursor within the string.
const maybe_t<size_t> cursor;
// The operation context. Again, a reference member variable!
const operation_context_t &ctx;
// Whether it's OK to do I/O.
@ -830,8 +832,10 @@ class highlighter_t {
void visit(const ast::node_t &node) { visit_children(node); }
// Constructor
highlighter_t(const wcstring &str, const operation_context_t &ctx, wcstring wd, bool can_do_io)
highlighter_t(const wcstring &str, maybe_t<size_t> cursor, const operation_context_t &ctx,
wcstring wd, bool can_do_io)
: buff(str),
cursor(cursor),
ctx(ctx),
io_ok(can_do_io),
working_directory(std::move(wd)),
@ -907,8 +911,12 @@ void highlighter_t::color_as_argument(const ast::node_t &node, bool options_allo
this->color_array.at(arg_subcmd_end) = highlight_role_t::operat;
// Highlight it recursively.
highlighter_t cmdsub_highlighter(cmdsub_contents, this->ctx, this->working_directory,
this->io_still_ok());
maybe_t<size_t> arg_cursor;
if (cursor.has_value()) {
arg_cursor = *cursor - arg_subcmd_start;
}
highlighter_t cmdsub_highlighter(cmdsub_contents, arg_cursor, this->ctx,
this->working_directory, this->io_still_ok());
color_array_t subcolors = cmdsub_highlighter.highlight();
// Copy out the subcolors back into our array.
@ -1351,8 +1359,8 @@ std::string colorize(const wcstring &text, const std::vector<highlight_spec_t> &
}
void highlight_shell(const wcstring &buff, std::vector<highlight_spec_t> &color,
const operation_context_t &ctx, bool io_ok) {
const operation_context_t &ctx, bool io_ok, maybe_t<size_t> cursor) {
const wcstring working_directory = ctx.vars.get_pwd_slash();
highlighter_t highlighter(buff, ctx, working_directory, io_ok);
highlighter_t highlighter(buff, cursor, ctx, working_directory, io_ok);
color = highlighter.highlight();
}

View file

@ -105,8 +105,10 @@ std::string colorize(const wcstring &text, const std::vector<highlight_spec_t> &
/// \param ctx The variables and cancellation check for this operation.
/// \param io_ok If set, allow IO which may block. This means that e.g. invalid commands may be
/// detected.
/// \param cursor The position of the cursor in the commandline.
void highlight_shell(const wcstring &buffstr, std::vector<highlight_spec_t> &color,
const operation_context_t &ctx, bool io_ok = false);
const operation_context_t &ctx, bool io_ok = false,
maybe_t<size_t> cursor = {});
/// highlight_color_resolver_t resolves highlight specs (like "a command") to actual RGB colors.
/// It maintains a cache with no invalidation mechanism. The lifetime of these should typically be

View file

@ -2696,16 +2696,16 @@ void reader_data_t::highlight_complete(highlight_result_t result) {
// Given text 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(parser_t &parser,
const wcstring &text,
const editable_line_t &el,
bool io_ok) {
auto vars = parser.vars().snapshot();
uint32_t generation_count = read_generation_count();
return [=]() -> highlight_result_t {
if (text.empty()) return {};
if (el.text().empty()) return {};
operation_context_t ctx = get_bg_context(vars, generation_count);
std::vector<highlight_spec_t> colors(text.size(), highlight_spec_t{});
highlight_shell(text, colors, ctx, io_ok);
return highlight_result_t{std::move(colors), text};
std::vector<highlight_spec_t> colors(el.text().size(), highlight_spec_t{});
highlight_shell(el.text(), colors, ctx, io_ok, el.position());
return highlight_result_t{std::move(colors), el.text()};
};
}
@ -2719,7 +2719,7 @@ void reader_data_t::super_highlight_me_plenty() {
in_flight_highlight_request = el->text();
FLOG(reader_render, L"Highlighting");
auto highlight_performer = get_highlight_performer(parser(), el->text(), true /* io_ok */);
auto highlight_performer = get_highlight_performer(parser(), *el, true /* io_ok */);
auto shared_this = this->shared_from_this();
debounce_highlighting().perform(highlight_performer, [shared_this](highlight_result_t result) {
shared_this->highlight_complete(std::move(result));
@ -2762,7 +2762,7 @@ void reader_data_t::finish_highlighting_before_exec() {
if (!current_highlight_ok) {
// We need to do a quick highlight without I/O.
auto highlight_no_io =
get_highlight_performer(parser(), command_line.text(), false /* io not ok */);
get_highlight_performer(parser(), command_line, false /* io not ok */);
this->highlight_complete(highlight_no_io());
}
}