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()); do_test(expected_colors.size() == text.size());
std::vector<highlight_spec_t> colors(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()) { if (expected_colors.size() != colors.size()) {
err(L"Color vector has wrong size! Expected %lu, actual %lu", expected_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)! // The string we're highlighting. Note this is a reference memmber variable (to avoid copying)!
// We must not outlive this! // We must not outlive this!
const wcstring &buff; 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! // The operation context. Again, a reference member variable!
const operation_context_t &ctx; const operation_context_t &ctx;
// Whether it's OK to do I/O. // 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); } void visit(const ast::node_t &node) { visit_children(node); }
// Constructor // 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), : buff(str),
cursor(cursor),
ctx(ctx), ctx(ctx),
io_ok(can_do_io), io_ok(can_do_io),
working_directory(std::move(wd)), 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; this->color_array.at(arg_subcmd_end) = highlight_role_t::operat;
// Highlight it recursively. // Highlight it recursively.
highlighter_t cmdsub_highlighter(cmdsub_contents, this->ctx, this->working_directory, maybe_t<size_t> arg_cursor;
this->io_still_ok()); 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(); color_array_t subcolors = cmdsub_highlighter.highlight();
// Copy out the subcolors back into our array. // 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, 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(); 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(); 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 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 /// \param io_ok If set, allow IO which may block. This means that e.g. invalid commands may be
/// detected. /// detected.
/// \param cursor The position of the cursor in the commandline.
void highlight_shell(const wcstring &buffstr, std::vector<highlight_spec_t> &color, 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. /// 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 /// 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 // Given text and whether IO is allowed, return a function that performs highlighting. The function
// may be invoked on a background thread. // may be invoked on a background thread.
static std::function<highlight_result_t(void)> get_highlight_performer(parser_t &parser, static std::function<highlight_result_t(void)> get_highlight_performer(parser_t &parser,
const wcstring &text, const editable_line_t &el,
bool io_ok) { bool io_ok) {
auto vars = parser.vars().snapshot(); auto vars = parser.vars().snapshot();
uint32_t generation_count = read_generation_count(); uint32_t generation_count = read_generation_count();
return [=]() -> highlight_result_t { return [=]() -> highlight_result_t {
if (text.empty()) return {}; if (el.text().empty()) return {};
operation_context_t ctx = get_bg_context(vars, generation_count); operation_context_t ctx = get_bg_context(vars, generation_count);
std::vector<highlight_spec_t> colors(text.size(), highlight_spec_t{}); std::vector<highlight_spec_t> colors(el.text().size(), highlight_spec_t{});
highlight_shell(text, colors, ctx, io_ok); highlight_shell(el.text(), colors, ctx, io_ok, el.position());
return highlight_result_t{std::move(colors), text}; 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(); in_flight_highlight_request = el->text();
FLOG(reader_render, L"Highlighting"); 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(); auto shared_this = this->shared_from_this();
debounce_highlighting().perform(highlight_performer, [shared_this](highlight_result_t result) { debounce_highlighting().perform(highlight_performer, [shared_this](highlight_result_t result) {
shared_this->highlight_complete(std::move(result)); shared_this->highlight_complete(std::move(result));
@ -2762,7 +2762,7 @@ void reader_data_t::finish_highlighting_before_exec() {
if (!current_highlight_ok) { if (!current_highlight_ok) {
// We need to do a quick highlight without I/O. // We need to do a quick highlight without I/O.
auto highlight_no_io = 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()); this->highlight_complete(highlight_no_io());
} }
} }