#pragma once #include "../libs/tree-sitter/lib/include/tree_sitter/api.h" #include "./rope.h" #include "./ui.h" #include "./utils.h" #include #include #include struct Highlight { uint32_t fg; uint32_t bg; uint32_t flags; uint8_t priority; }; struct Span { uint32_t start; uint32_t end; Highlight *hl; bool operator<(const Span &other) const { return start < other.start; } }; struct SpanCursor { const std::vector &spans; size_t index = 0; std::vector active; SpanCursor(const std::vector &s) : spans(s) {} Highlight *get_highlight(uint32_t byte_offset) { for (int i = active.size() - 1; i >= 0; i--) if (active[i]->end <= byte_offset) active.erase(active.begin() + i); while (index < spans.size() && spans[index].start <= byte_offset) { if (spans[index].end > byte_offset) active.push_back(const_cast(&spans[index])); index++; } Highlight *best = nullptr; int max_prio = -1; for (auto *s : active) { if (s->hl->priority > max_prio) { max_prio = s->hl->priority; best = s->hl; } } return best; } void sync(uint32_t byte_offset) { active.clear(); size_t left = 0, right = spans.size(); while (left < right) { size_t mid = (left + right) / 2; if (spans[mid].start <= byte_offset) left = mid + 1; else right = mid; } index = left; while (left > 0) { left--; if (spans[left].end > byte_offset) active.push_back(const_cast(&spans[left])); else if (byte_offset - spans[left].end > 1000) break; } } }; struct Editor { const char *filename; // Filename of the editor Knot *root; // A rope std::shared_mutex knot_mtx; // A mutex std::shared_mutex span_mtx; // A mutex Coord cursor; // position of the cursor uint32_t cursor_preffered; // preffered visual column Coord selection; // position of the selection bool selection_active; // true if there is a selection Coord position; // Position of the editor Coord size; // Size of the editor Coord scroll; // Position of the scroll TSTree *tree; // Tree-sitter tree TSParser *parser; // Tree-sitter parser TSQuery *query; // Tree-sitter query const TSLanguage *language; // Tree-sitter language Queue edit_queue; // Tree-sitter edit queue std::vector query_map; // Tree-sitter query map int *folded; // folded lines indexed by line number - cached form of // folded_node std::vector spans; std::map folded_node; // maps content hash to fold state // - built by tree-sitter }; typedef struct TSLoad { Editor *editor; char *prev = nullptr; } TSLoad; Editor *new_editor(const char *filename, Coord position, Coord size); void free_editor(Editor *editor); void render_editor(Editor *editor); void fold(Editor *editor, uint32_t start_line, uint32_t end_line); void scroll_up(Editor *editor, uint32_t lines); void scroll_down(Editor *editor, uint32_t lines); void cursor_up(Editor *editor, uint32_t number); void cursor_down(Editor *editor, uint32_t number); void cursor_left(Editor *editor, uint32_t number); void cursor_right(Editor *editor, uint32_t number); void ensure_scroll(Editor *editor);