#include "carry_lex.hpp" #include #include #include "systems/carry_system.hpp" #include "text/text.hpp" #include "text/token.hpp" namespace Nimbin { // Re-lex the entire carried line as ONE source string, then assign each word a // context colour by mapping highlight spans onto its byte range. Mirrors // Handler::apply_Highlight, but synchronous and scoped to a single joined line. void CarryLex::lex_CarriedLine(CarriedLine& carry) { // 1) Build the joined source + per-token byte spans, in reading order. // NOTE: nodes() is front->back. If the carried line reads right-to-left // on screen (get_SlotPosition lays out from `last` with decreasing // offset), switch this to reverse_nodes() so "int x" lexes as "int x" // and not "x int". Verify against the on-screen order once. std::string src; DynArray toks; for (CarriedWordNode* n : carry.nodes()) { if (!n->word) continue; Text::Token::Data* t = n->word.get(); if (!src.empty()) src += ' '; t->byte_begin = src.size(); src += t->text; t->byte_end = src.size(); toks.push_back(t); } if (toks.empty()) return; // 2) Classify the whole line as one context. DynArray spans = Text::CppHighlight::classify(src); // 3) Map spans -> tokens by maximum byte overlap. for (Text::Token::Data* t : toks) { size_t best = 0; Text::Token::Type type = Text::Token::Type::Identifier; bool found = false; for (const Text::HiSpan& s : spans) { size_t lo = (t->byte_begin > s.byte_begin) ? t->byte_begin : s.byte_begin; size_t hi = (t->byte_end < s.byte_end) ? t->byte_end : s.byte_end; if (lo < hi) { size_t ov = hi - lo; if (ov > best) { best = ov; type = s.type; found = true; } } } t->set_ColorSource(Text::ColorSource::Lexed); // carried line is a context if (found) t->set_Context(Text::Token::get_Color(type)); else t->clear_Context(); // no span -> single fallback } } // A word that leaves the carried line is no longer in a context: drop the // context flag and select its lone (single) colour, the same colour it shows on // the floor or as a projectile. void CarryLex::revert_ToSingle(Text::Token::Data* word) { if (!word) return; word->clear_Context(); word->set_ColorSource(Text::ColorSource::Lint); } } // namespace Nimbin