Add custom syntax highlighter and optimize

This commit is contained in:
2026-01-16 21:47:05 +00:00
parent 04cce25bf2
commit 1fda5bf246
77 changed files with 1487 additions and 1673 deletions

View File

@@ -1,13 +1,10 @@
#include "editor/editor.h"
#include "editor/folds.h"
void ensure_cursor(Editor *editor) {
std::shared_lock knot_lock(editor->knot_mtx);
if (editor->cursor < editor->scroll) {
uint32_t line_idx = next_unfolded_row(editor, editor->scroll.row);
editor->cursor.row = line_idx;
editor->cursor.col =
line_idx == editor->scroll.row ? editor->scroll.col : 0;
editor->cursor.row = editor->scroll.row;
editor->cursor.col = editor->scroll.col;
editor->cursor_preffered = UINT32_MAX;
return;
}
@@ -24,20 +21,6 @@ void ensure_cursor(Editor *editor) {
while (true) {
if (visual_rows >= editor->size.row)
break;
const Fold *fold = fold_for_line(editor->folds, line_index);
if (fold) {
Coord c = {fold->start, 0};
last_visible = c;
visual_rows++;
uint32_t skip_until = fold->end;
while (line_index <= skip_until) {
char *line = next_line(it, nullptr);
if (!line)
break;
line_index++;
}
continue;
}
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)
@@ -81,14 +64,8 @@ void ensure_cursor(Editor *editor) {
}
line_index++;
}
uint32_t last_real_row = last_visible.row;
const Fold *last_fold = fold_for_line(editor->folds, last_visible.row);
if (last_fold) {
last_visible.row = last_fold->start == 0 ? 0 : last_fold->start - 1;
last_visible.col = 0;
}
editor->cursor.row = last_visible.row;
editor->cursor.col = last_visible.row == last_real_row ? last_visible.col : 0;
editor->cursor.col = last_visible.col;
editor->cursor_preffered = UINT32_MAX;
free(it->buffer);
free(it);
@@ -112,7 +89,6 @@ void ensure_scroll(Editor *editor) {
}
if (len > 0 && line[len - 1] == '\n')
--len;
uint32_t rows = 1;
uint32_t cols = 0;
uint32_t offset = 0;
uint32_t old_offset = 0;
@@ -121,7 +97,6 @@ void ensure_scroll(Editor *editor) {
grapheme_next_character_break_utf8(line + offset, len - offset);
int width = display_width(line + offset, inc);
if (cols + width > render_width) {
rows++;
cols = 0;
if (editor->cursor.col > old_offset && editor->cursor.col <= offset) {
editor->scroll.row = editor->cursor.row;
@@ -139,7 +114,7 @@ void ensure_scroll(Editor *editor) {
free(it);
editor->scroll.row = editor->cursor.row;
editor->scroll.col = (editor->cursor.col == 0) ? 0 : old_offset;
} else {
} else if (editor->cursor.row - editor->scroll.row < editor->size.row * 2) {
uint32_t line_index = editor->scroll.row;
LineIterator *it = begin_l_iter(editor->root, line_index);
if (!it)
@@ -150,30 +125,6 @@ void ensure_scroll(Editor *editor) {
uint32_t q_size = 0;
bool first_visual_line = true;
while (true) {
const Fold *fold = fold_for_line(editor->folds, line_index);
if (fold) {
Coord fold_coord = {fold->start, 0};
if (q_size < max_visual_lines) {
scroll_queue[(q_head + q_size) % max_visual_lines] = fold_coord;
q_size++;
} else {
scroll_queue[q_head] = fold_coord;
q_head = (q_head + 1) % max_visual_lines;
}
if (fold->start <= editor->cursor.row &&
editor->cursor.row <= fold->end) {
editor->scroll = scroll_queue[q_head];
break;
}
uint32_t skip_until = fold->end;
while (line_index <= skip_until) {
char *line = next_line(it, nullptr);
if (!line)
break;
line_index++;
}
continue;
}
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)
@@ -234,5 +185,11 @@ void ensure_scroll(Editor *editor) {
free(scroll_queue);
free(it->buffer);
free(it);
} else {
editor->scroll.row = (editor->cursor.row > editor->size.row * 1.5)
? editor->cursor.row - editor->size.row * 1.5
: 0;
editor->scroll.col = 0;
ensure_scroll(editor);
}
}

View File

@@ -1,5 +1,4 @@
#include "editor/editor.h"
#include "editor/folds.h"
#include "main.h"
Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y) {
@@ -7,7 +6,6 @@ Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y) {
x++;
uint32_t numlen =
EXTRA_META + static_cast<int>(std::log10(editor->root->line_count + 1));
bool is_gutter_click = (x < numlen);
uint32_t render_width = editor->size.col - numlen;
x = MAX(x, numlen) - numlen;
uint32_t target_visual_row = y;
@@ -21,28 +19,6 @@ Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y) {
if (!it)
return editor->scroll;
while (visual_row <= target_visual_row) {
const Fold *fold = fold_for_line(editor->folds, line_index);
if (fold) {
if (visual_row == target_visual_row) {
free(it->buffer);
free(it);
if (is_gutter_click) {
remove_fold(editor, fold->start);
return {UINT32_MAX, UINT32_MAX};
}
return {fold->start > 0 ? fold->start - 1 : 0, 0};
}
visual_row++;
while (line_index <= fold->end) {
char *l = next_line(it, nullptr);
if (!l)
break;
line_index++;
}
last_line_index = fold->end;
last_col = 0;
continue;
}
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)

View File

@@ -1,8 +1,7 @@
#include "editor/editor.h"
#include "editor/folds.h"
#include "utils/utils.h"
Coord move_right_pure(Editor *editor, Coord cursor, uint32_t number) {
Coord move_right(Editor *editor, Coord cursor, uint32_t number) {
Coord result = cursor;
if (!editor || !editor->root || number == 0)
return result;
@@ -50,7 +49,7 @@ Coord move_right_pure(Editor *editor, Coord cursor, uint32_t number) {
return result;
}
Coord move_left_pure(Editor *editor, Coord cursor, uint32_t number) {
Coord move_left(Editor *editor, Coord cursor, uint32_t number) {
Coord result = cursor;
if (!editor || !editor->root || number == 0)
return result;
@@ -103,170 +102,38 @@ Coord move_left_pure(Editor *editor, Coord cursor, uint32_t number) {
return result;
}
Coord move_right(Editor *editor, Coord cursor, uint32_t number) {
Coord result = cursor;
void cursor_down(Editor *editor, uint32_t number) {
if (!editor || !editor->root || number == 0)
return result;
uint32_t row = result.row;
uint32_t col = result.col;
uint32_t line_len = 0;
LineIterator *it = begin_l_iter(editor->root, row);
if (!it)
return result;
uint32_t target_row = next_unfolded_row(editor, row);
while (row < target_row) {
if (!next_line(it, &line_len)) {
return;
uint32_t visual_col = editor->cursor_preffered;
if (visual_col == UINT32_MAX) {
uint32_t len;
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
char *line = next_line(it, &len);
if (!line) {
free(it->buffer);
free(it);
return result;
return;
}
++row;
}
char *line = next_line(it, &line_len);
if (!line) {
editor->cursor_preffered =
get_visual_col_from_bytes(line, len, editor->cursor.col);
visual_col = editor->cursor_preffered;
free(it->buffer);
free(it);
return result;
}
if (line_len > 0 && line[line_len - 1] == '\n')
--line_len;
while (number > 0) {
if (col >= line_len) {
uint32_t next_row = next_unfolded_row(editor, row + 1);
if (next_row >= editor->root->line_count) {
col = line_len;
break;
}
while (row < next_row) {
line = next_line(it, &line_len);
if (!line) {
free(it->buffer);
free(it);
result.row = row;
result.col = col;
return result;
}
++row;
}
if (line_len > 0 && line[line_len - 1] == '\n')
--line_len;
col = 0;
--number;
continue;
} else {
uint32_t inc =
grapheme_next_character_break_utf8(line + col, line_len - col);
if (inc == 0)
break;
col += inc;
--number;
}
}
free(it->buffer);
free(it);
result.row = row;
result.col = col;
return result;
}
Coord move_left(Editor *editor, Coord cursor, uint32_t number) {
Coord result = cursor;
if (!editor || !editor->root || number == 0)
return result;
uint32_t row = result.row;
uint32_t col = result.col;
uint32_t len = 0;
LineIterator *it = begin_l_iter(editor->root, row);
editor->cursor.row =
MIN(editor->cursor.row + number, editor->root->line_count - 1);
uint32_t len;
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
char *line = next_line(it, &len);
if (!line) {
free(it->buffer);
free(it);
return result;
return;
}
if (len > 0 && line[len - 1] == '\n')
--len;
bool iterator_ahead = true;
while (number > 0) {
if (col == 0) {
if (row == 0)
break;
if (iterator_ahead) {
prev_line(it, nullptr);
iterator_ahead = false;
}
line = nullptr;
while (row > 0) {
row--;
line = prev_line(it, &len);
if (!line)
break;
const Fold *fold = fold_for_line(editor->folds, row);
if (fold) {
while (line && row > fold->start) {
line = prev_line(it, &len);
row--;
}
line = nullptr;
continue;
}
break;
}
if (!line)
break;
if (len > 0 && line[len - 1] == '\n')
--len;
col = len;
} else {
uint32_t new_col = 0;
while (new_col < col) {
uint32_t inc =
grapheme_next_character_break_utf8(line + new_col, len - new_col);
if (new_col + inc >= col)
break;
new_col += inc;
}
col = new_col;
}
number--;
}
free(it->buffer);
free(it);
result.row = row;
result.col = col;
return result;
}
void cursor_down(Editor *editor, uint32_t number) {
if (!editor || !editor->root || number == 0)
return;
uint32_t len;
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
char *line_content = next_line(it, &len);
if (line_content == nullptr)
return;
if (editor->cursor_preffered == UINT32_MAX)
editor->cursor_preffered =
get_visual_col_from_bytes(line_content, len, editor->cursor.col);
uint32_t visual_col = editor->cursor_preffered;
free(it->buffer);
free(it);
uint32_t target_row = editor->cursor.row;
while (number > 0 && target_row < editor->root->line_count - 1) {
target_row = next_unfolded_row(editor, target_row + 1);
if (target_row >= editor->root->line_count) {
target_row = editor->root->line_count - 1;
break;
}
number--;
}
it = begin_l_iter(editor->root, target_row);
line_content = next_line(it, &len);
if (!line_content)
return;
if (len > 0 && line_content[len - 1] == '\n')
--len;
editor->cursor.row = target_row;
editor->cursor.col = get_bytes_from_visual_col(line_content, len, visual_col);
editor->cursor.col = get_bytes_from_visual_col(line, len, visual_col);
free(it->buffer);
free(it);
}
@@ -287,7 +154,7 @@ void cursor_up(Editor *editor, uint32_t number) {
free(it);
uint32_t target_row = editor->cursor.row;
while (number > 0 && target_row > 0) {
target_row = prev_unfolded_row(editor, target_row - 1);
target_row--;
if (target_row == 0) {
number--;
break;

View File

@@ -1,7 +1,7 @@
#include "editor/editor.h"
#include "editor/folds.h"
#include "lsp/lsp.h"
#include "utils/utils.h"
#include <cstdint>
void edit_erase(Editor *editor, Coord pos, int64_t len) {
if (len == 0)
@@ -11,9 +11,8 @@ void edit_erase(Editor *editor, Coord pos, int64_t len) {
uint32_t cursor_original =
line_to_byte(editor->root, editor->cursor.row, nullptr) +
editor->cursor.col;
TSPoint old_point = {pos.row, pos.col};
uint32_t byte_pos = line_to_byte(editor->root, pos.row, nullptr) + pos.col;
Coord point = move_left_pure(editor, pos, -len);
Coord point = move_left(editor, pos, -len);
json lsp_range;
bool do_lsp = (editor->lsp != nullptr);
if (do_lsp) {
@@ -48,30 +47,12 @@ void edit_erase(Editor *editor, Coord pos, int64_t len) {
lock_1.unlock();
uint32_t start_row = point.row;
uint32_t end_row = pos.row;
apply_line_deletion(editor, start_row + 1, end_row);
apply_hook_deletion(editor, start_row + 1, end_row);
std::unique_lock lock_2(editor->knot_mtx);
editor->root = erase(editor->root, start, byte_pos - start);
if (editor->ts.tree) {
TSInputEdit edit = {
.start_byte = start,
.old_end_byte = byte_pos,
.new_end_byte = start,
.start_point = {point.row, point.col},
.old_end_point = old_point,
.new_end_point = {point.row, point.col},
};
editor->edit_queue.push(edit);
}
std::unique_lock lock_3(editor->spans.mtx);
apply_edit(editor->spans.spans, start, start - byte_pos);
if (editor->spans.mid_parse)
editor->spans.edits.push({start, start - byte_pos});
lock_3.unlock();
lock_2.unlock();
std::unique_lock lock_4(editor->hex_color_spans.mtx);
apply_edit(editor->hex_color_spans.spans, byte_pos, start - byte_pos);
lock_4.unlock();
if (editor->parser)
editor->parser->edit(editor->root, start_row, end_row, start_row);
if (do_lsp) {
if (editor->lsp->incremental_sync) {
json message = {
@@ -102,9 +83,8 @@ void edit_erase(Editor *editor, Coord pos, int64_t len) {
uint32_t cursor_original =
line_to_byte(editor->root, editor->cursor.row, nullptr) +
editor->cursor.col;
TSPoint old_point = {pos.row, pos.col};
uint32_t byte_pos = line_to_byte(editor->root, pos.row, nullptr) + pos.col;
Coord point = move_right_pure(editor, pos, len);
Coord point = move_right(editor, pos, len);
json lsp_range;
bool do_lsp = (editor->lsp != nullptr);
if (do_lsp) {
@@ -139,30 +119,12 @@ void edit_erase(Editor *editor, Coord pos, int64_t len) {
lock_1.unlock();
uint32_t start_row = pos.row;
uint32_t end_row = point.row;
apply_line_deletion(editor, start_row + 1, end_row);
apply_hook_deletion(editor, start_row + 1, end_row);
std::unique_lock lock_2(editor->knot_mtx);
editor->root = erase(editor->root, byte_pos, end - byte_pos);
if (editor->ts.tree) {
TSInputEdit edit = {
.start_byte = byte_pos,
.old_end_byte = end,
.new_end_byte = byte_pos,
.start_point = old_point,
.old_end_point = {point.row, point.col},
.new_end_point = old_point,
};
editor->edit_queue.push(edit);
}
std::unique_lock lock_3(editor->spans.mtx);
apply_edit(editor->spans.spans, byte_pos, byte_pos - end);
if (editor->spans.mid_parse)
editor->spans.edits.push({byte_pos, byte_pos - end});
lock_3.unlock();
lock_2.unlock();
std::unique_lock lock_4(editor->hex_color_spans.mtx);
apply_edit(editor->hex_color_spans.spans, byte_pos, byte_pos - end);
lock_4.unlock();
if (editor->parser)
editor->parser->edit(editor->root, start_row, end_row, start_row);
if (do_lsp) {
if (editor->lsp->incremental_sync) {
json message = {
@@ -197,7 +159,6 @@ void edit_insert(Editor *editor, Coord pos, char *data, uint32_t len) {
line_to_byte(editor->root, editor->cursor.row, nullptr) +
editor->cursor.col;
uint32_t byte_pos = line_to_byte(editor->root, pos.row, nullptr) + pos.col;
TSPoint start_point = {pos.row, pos.col};
if (cursor_original > byte_pos) {
uint32_t cursor_new = cursor_original + len;
uint32_t new_col;
@@ -207,39 +168,14 @@ void edit_insert(Editor *editor, Coord pos, char *data, uint32_t len) {
lock_1.unlock();
std::unique_lock lock_2(editor->knot_mtx);
editor->root = insert(editor->root, byte_pos, data, len);
uint32_t cols = 0;
uint32_t rows = 0;
for (uint32_t i = 0; i < len; i++) {
if (data[i] == '\n') {
for (uint32_t i = 0; i < len; i++)
if (data[i] == '\n')
rows++;
cols = 0;
} else {
cols++;
}
}
apply_line_insertion(editor, pos.row, rows);
apply_hook_insertion(editor, pos.row, rows);
if (editor->ts.tree) {
TSInputEdit edit = {
.start_byte = byte_pos,
.old_end_byte = byte_pos,
.new_end_byte = byte_pos + len,
.start_point = start_point,
.old_end_point = start_point,
.new_end_point = {start_point.row + rows,
(rows == 0) ? (start_point.column + cols) : cols},
};
editor->edit_queue.push(edit);
}
std::unique_lock lock_3(editor->spans.mtx);
apply_edit(editor->spans.spans, byte_pos, len);
if (editor->spans.mid_parse)
editor->spans.edits.push({byte_pos, len});
lock_3.unlock();
lock_2.unlock();
std::unique_lock lock_4(editor->hex_color_spans.mtx);
apply_edit(editor->hex_color_spans.spans, byte_pos, len);
lock_4.unlock();
if (editor->parser)
editor->parser->edit(editor->root, pos.row, pos.row, pos.row + rows);
if (editor->lsp) {
if (editor->lsp->incremental_sync) {
lock_1.lock();

View File

@@ -29,39 +29,20 @@ Editor *new_editor(const char *filename_arg, Coord position, Coord size) {
editor->root = load(str, len, optimal_chunk_size(len));
free(str);
editor->lang = language_for_file(filename.c_str());
if (editor->lang.name != "unknown" && len <= (1024 * 128)) {
editor->ts.parser = ts_parser_new();
editor->ts.language = editor->lang.fn();
ts_parser_set_language(editor->ts.parser, editor->ts.language);
editor->ts.query_file =
get_exe_dir() + "/../grammar/" + editor->lang.name + ".scm";
}
if (len <= (1024 * 28))
request_add_to_lsp(editor->lang, editor);
if (editor->lang.name != "unknown")
editor->parser = new Parser(editor->root, &editor->knot_mtx,
editor->lang.name, size.row + 5);
// if (len <= (1024 * 28))
// request_add_to_lsp(editor->lang, editor);
editor->indents.compute_indent(editor);
return editor;
}
void free_tsset(TSSetMain *set) {
if (set->parser)
ts_parser_delete(set->parser);
if (set->tree)
ts_tree_delete(set->tree);
if (set->query)
ts_query_delete(set->query);
for (auto &inj : set->injections) {
if (inj.second.parser)
ts_parser_delete(inj.second.parser);
if (inj.second.query)
ts_query_delete(inj.second.query);
if (inj.second.tree)
ts_tree_delete(inj.second.tree);
}
}
void free_editor(Editor *editor) {
remove_from_lsp(editor);
free_tsset(&editor->ts);
if (editor->parser)
delete editor->parser;
editor->parser = nullptr;
free_rope(editor->root);
delete editor;
}

View File

@@ -1,9 +1,7 @@
#include "editor/editor.h"
#include "editor/folds.h"
#include "lsp/lsp.h"
#include "main.h"
#include "utils/utils.h"
#include <cstdint>
void handle_editor_event(Editor *editor, KeyEvent event) {
static std::chrono::steady_clock::time_point last_click_time =
@@ -579,17 +577,6 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
char *text;
Coord start;
switch (event.c[0]) {
case 'f':
if (editor->cursor.row != editor->selection.row) {
uint32_t start = MIN(editor->cursor.row, editor->selection.row);
uint32_t end = MAX(editor->cursor.row, editor->selection.row);
add_fold(editor, start, end);
}
cursor_left(editor, 1);
cursor_down(editor, 1);
editor->selection_active = false;
mode = NORMAL;
break;
case 0x1B:
case 's':
case 'v':
@@ -648,10 +635,8 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
}
editor->hooks[event.c[0] - '!'] = editor->cursor.row + 1;
} else {
uint32_t line = editor->hooks[event.c[0] - '!'];
uint32_t line = editor->hooks[event.c[0] - '!'] - 1;
if (line > 0) {
if (line_is_folded(editor->folds, --line))
break;
editor->cursor = {line, 0};
editor->cursor_preffered = UINT32_MAX;
}

View File

@@ -17,9 +17,9 @@ void apply_lsp_edits(Editor *editor, std::vector<TextEdit> edits, bool move) {
std::shared_lock lock(editor->knot_mtx);
editor->cursor = first.start;
editor->cursor =
move_right_pure(editor, editor->cursor,
count_clusters(first.text.c_str(), first.text.size(), 0,
first.text.size()));
move_right(editor, editor->cursor,
count_clusters(first.text.c_str(), first.text.size(), 0,
first.text.size()));
} else {
if (cursor.row >= editor->root->line_count) {
editor->cursor.row = editor->root->line_count - 1;

View File

@@ -1,5 +1,4 @@
#include "editor/editor.h"
#include "editor/folds.h"
#include "main.h"
void move_line_up(Editor *editor) {
@@ -17,7 +16,7 @@ void move_line_up(Editor *editor) {
if (line_len > 0 && line[line_len - 1] == '\n')
line_len--;
line_cluster_len = count_clusters(line, line_len, 0, line_len);
uint32_t target_row = prev_unfolded_row(editor, editor->cursor.row - 1);
uint32_t target_row = editor->cursor.row - 1;
uint32_t up_by = editor->cursor.row - target_row;
if (up_by > 1)
up_by--;
@@ -68,7 +67,7 @@ void move_line_down(Editor *editor) {
if (line_len && line[line_len - 1] == '\n')
line_len--;
line_cluster_len = count_clusters(line, line_len, 0, line_len);
uint32_t target_row = next_unfolded_row(editor, editor->cursor.row + 1);
uint32_t target_row = editor->cursor.row + 1;
if (target_row >= editor->root->line_count) {
free(line);
lock.unlock();
@@ -95,7 +94,7 @@ void move_line_down(Editor *editor) {
std::shared_lock lock(editor->knot_mtx);
uint32_t start_row = MIN(editor->cursor.row, editor->selection.row);
uint32_t end_row = MAX(editor->cursor.row, editor->selection.row);
uint32_t target_row = next_unfolded_row(editor, end_row + 1);
uint32_t target_row = end_row + 1;
if (target_row >= editor->root->line_count)
return;
uint32_t down_by = target_row - end_row;

View File

@@ -1,7 +1,5 @@
#include "editor/editor.h"
#include "editor/folds.h"
#include "main.h"
#include "ts/decl.h"
void render_editor(Editor *editor) {
uint32_t sel_start = 0, sel_end = 0;
@@ -22,6 +20,9 @@ void render_editor(Editor *editor) {
while (warn_it != editor->warnings.end() &&
warn_it->line < editor->scroll.row)
++warn_it;
std::unique_lock<std::mutex> lock;
if (editor->parser)
lock = std::unique_lock<std::mutex>(editor->parser->mutex);
std::shared_lock knot_lock(editor->knot_mtx);
if (editor->selection_active) {
Coord start, end;
@@ -73,56 +74,12 @@ void render_editor(Editor *editor) {
}
Coord cursor = {UINT32_MAX, UINT32_MAX};
uint32_t line_index = editor->scroll.row;
SpanCursor span_cursor(editor->spans);
SpanCursor word_span_cursor(editor->word_spans);
SpanCursor hex_span_cursor(editor->hex_color_spans);
LineIterator *it = begin_l_iter(editor->root, line_index);
if (!it)
return;
uint32_t rendered_rows = 0;
uint32_t global_byte_offset = line_to_byte(editor->root, line_index, nullptr);
span_cursor.sync(global_byte_offset);
word_span_cursor.sync(global_byte_offset);
hex_span_cursor.sync(global_byte_offset);
while (rendered_rows < editor->size.row) {
const Fold *fold = fold_for_line(editor->folds, line_index);
if (fold) {
update(editor->position.row + rendered_rows, editor->position.col, "",
0xAAAAAA, 0, 0);
char buf[16];
int len = snprintf(buf, sizeof(buf), "%*u ", numlen - 3, fold->start + 1);
uint32_t num_color =
editor->cursor.row == fold->start ? 0xFFFFFF : 0x555555;
for (int i = 0; i < len; i++)
update(editor->position.row + rendered_rows,
editor->position.col + i + 2, (char[2]){buf[i], 0}, num_color, 0,
0);
const char marker[15] = "... folded ...";
uint32_t i = 0;
for (; i < 14 && i < render_width; i++)
update(rendered_rows, i + render_x, (char[2]){marker[i], 0}, 0xc6c6c6,
0, 0);
for (; i < render_width; i++)
update(rendered_rows, i + render_x, " ", 0xc6c6c6, 0, 0);
rendered_rows++;
uint32_t skip_until = fold->end;
while (line_index <= skip_until) {
if (hook_it != v.end() && hook_it->first == line_index + 1)
hook_it++;
while (warn_it != editor->warnings.end() && warn_it->line == line_index)
++warn_it;
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)
break;
global_byte_offset += line_len;
if (line_len > 0 && line[line_len - 1] == '\n')
global_byte_offset--;
global_byte_offset++;
line_index++;
}
continue;
}
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)
@@ -182,25 +139,13 @@ void render_editor(Editor *editor) {
}
uint32_t absolute_byte_pos =
global_byte_offset + current_byte_offset + local_render_offset;
Highlight *hl = span_cursor.get_highlight(absolute_byte_pos);
Highlight *word_hl = word_span_cursor.get_highlight(absolute_byte_pos);
Highlight *hex_hl = hex_span_cursor.get_highlight(absolute_byte_pos);
const Highlight *hl = nullptr;
if (editor->parser && editor->parser->line_data.size() > line_index)
hl = &highlight_map.at(editor->parser->get_type(
{line_index, current_byte_offset + local_render_offset}));
uint32_t fg = hl ? hl->fg : 0xFFFFFF;
uint32_t bg = hl ? hl->bg : 0;
uint8_t fl = hl ? hl->flags : 0;
if (hex_hl) {
if (hex_hl->fg != 0)
fg = hex_hl->fg;
if (hex_hl->bg != 0)
bg = hex_hl->bg;
fl |= hex_hl->flags;
} else if (word_hl) {
if (word_hl->fg != 0)
fg |= word_hl->fg;
if (word_hl->bg != 0)
bg |= word_hl->bg;
fl |= word_hl->flags;
}
if (editor->selection_active && absolute_byte_pos >= sel_start &&
absolute_byte_pos < sel_end)
bg = 0x555555;
@@ -468,6 +413,8 @@ void render_editor(Editor *editor) {
global_byte_offset += line_len + 1;
line_index++;
}
if (lock.owns_lock())
lock.unlock();
while (rendered_rows < editor->size.row) {
for (uint32_t col = 0; col < editor->size.col; col++)
update(editor->position.row + rendered_rows, editor->position.col + col,
@@ -498,4 +445,6 @@ void render_editor(Editor *editor) {
}
free(it->buffer);
free(it);
if (editor->parser)
editor->parser->scroll(line_index + 5);
}

View File

@@ -1,5 +1,4 @@
#include "editor/editor.h"
#include "editor/folds.h"
void scroll_up(Editor *editor, int32_t number) {
if (!editor || number == 0)
@@ -63,41 +62,6 @@ void scroll_up(Editor *editor, int32_t number) {
free(it);
return;
}
const Fold *fold = fold_for_line(editor->folds, line_index);
if (fold) {
while (line && line_index > fold->start) {
free(line);
line = prev_line(it, &len);
line_index--;
if (!line) {
editor->scroll = {0, 0};
free(it->buffer);
free(it);
return;
}
}
if (--number == 0) {
editor->scroll = {fold->start, 0};
free(it->buffer);
free(it);
return;
}
if (fold->start == 0) {
editor->scroll = {0, 0};
free(it->buffer);
free(it);
return;
}
line_index = fold->start - 1;
line = prev_line(it, &len);
if (!line) {
editor->scroll = {0, 0};
free(it->buffer);
free(it);
return;
}
continue;
}
if (len > 0 && line[len - 1] == '\n')
len--;
current_byte_offset = 0;
@@ -147,34 +111,6 @@ void scroll_down(Editor *editor, uint32_t number) {
uint32_t visual_seen = 0;
bool first_visual_line = true;
while (true) {
const Fold *fold = fold_for_line(editor->folds, line_index);
if (fold) {
Coord fold_coord = {fold->start, 0};
if (q_size < max_visual_lines) {
scroll_queue[(q_head + q_size) % max_visual_lines] = fold_coord;
q_size++;
} else {
scroll_queue[q_head] = fold_coord;
q_head = (q_head + 1) % max_visual_lines;
}
visual_seen++;
if (visual_seen >= number + max_visual_lines) {
editor->scroll = scroll_queue[q_head];
break;
}
uint32_t skip_until = fold->end;
while (line_index <= skip_until) {
char *line = next_line(it, nullptr);
if (!line) {
free(scroll_queue);
free(it->buffer);
free(it);
return;
}
line_index++;
}
continue;
}
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)

View File

@@ -1,7 +1,4 @@
#include "editor/editor.h"
#include "ts/ts.h"
static Highlight HL_UNDERLINE = {0, 0, CF_UNDERLINE, UINT8_MAX - 1};
void hover_diagnostic(Editor *editor) {
std::shared_lock lock(editor->v_mtx);
@@ -30,78 +27,8 @@ void hover_diagnostic(Editor *editor) {
void editor_worker(Editor *editor) {
if (!editor || !editor->root)
return;
if (editor->root->char_count > (1024 * 128))
return;
if (editor->ts.query_file != "" && !editor->ts.query)
editor->ts.query = load_query(editor->ts.query_file.c_str(), &editor->ts);
if (editor->ts.parser && editor->ts.query)
ts_collect_spans(editor);
if (editor->root->char_count > (1024 * 32))
return;
uint32_t prev_col, next_col;
word_boundaries_exclusive(editor, editor->cursor, &prev_col, &next_col);
std::unique_lock lock(editor->word_spans.mtx);
editor->word_spans.spans.clear();
lock.unlock();
if (next_col - prev_col > 0 && next_col - prev_col < 256 - 4) {
std::shared_lock lockk(editor->knot_mtx);
uint32_t offset = line_to_byte(editor->root, editor->cursor.row, nullptr);
char *word = read(editor->root, offset + prev_col, next_col - prev_col);
lockk.unlock();
if (word) {
char buf[256];
snprintf(buf, sizeof(buf), "\\b%s\\b", word);
std::shared_lock lockk(editor->knot_mtx);
std::vector<std::pair<size_t, size_t>> results =
search_rope_dfa(editor->root, buf);
lockk.unlock();
std::unique_lock lock2(editor->word_spans.mtx);
editor->word_spans.spans.reserve(results.size());
for (const auto &match : results) {
Span s;
s.start = match.first;
s.end = match.first + match.second;
s.hl = &HL_UNDERLINE;
editor->word_spans.spans.push_back(s);
}
free(word);
lock2.unlock();
}
}
static uint16_t limit = 150;
static Highlight *hl_s = (Highlight *)calloc(limit, sizeof(Highlight));
if (!hl_s)
exit(ENOMEM);
std::shared_lock lockk(editor->knot_mtx);
std::vector<Match> results =
search_rope(editor->root, "(?:0x|#)[0-9a-fA-F]{6,8}\\b");
if (results.size() > limit) {
limit = results.size() + 50;
free(hl_s);
hl_s = (Highlight *)calloc(limit, sizeof(Highlight));
if (!hl_s)
exit(ENOMEM);
}
lockk.unlock();
std::unique_lock lock2(editor->hex_color_spans.mtx);
editor->hex_color_spans.spans.clear();
editor->hex_color_spans.spans.reserve(results.size());
for (size_t i = 0; i < results.size(); ++i) {
Span s;
s.start = results[i].start;
s.end = results[i].end;
int x = results[i].text[0] == '#' ? 1 : 2;
uint32_t bg = HEX(results[i].text.substr(x, 6));
uint8_t r = bg >> 16;
uint8_t g = (bg >> 8) & 0xFF;
uint8_t b = bg & 0xFF;
double luminance = 0.299 * r + 0.587 * g + 0.114 * b;
uint32_t fg = (luminance > 128) ? 0x010101 : 0xFEFEFE;
hl_s[i] = {fg, bg, CF_BOLD, UINT8_MAX};
s.hl = &hl_s[i];
editor->hex_color_spans.spans.push_back(s);
}
lock2.unlock();
if (editor->parser)
editor->parser->work();
hover_diagnostic(editor);
if (editor->completion.active && editor->completion.hover_dirty) {
editor->completion.hover.render_first();