Minor fixes and optimizations

This commit is contained in:
2025-12-26 22:13:11 +00:00
parent 655f0e7d77
commit a38ba1f813
6 changed files with 59 additions and 48 deletions

View File

@@ -6,14 +6,12 @@ A TUI IDE.
# TODO
- [ ] Get lsp warnings byte offsets/lengths and render them as background color.
- [ ] Add support for LSP & autocomplete / snippets.
- First research
- `textDocument/documentHighlight` - for highlighting stuff (probably tree-sitter is enough)
- `textDocument/selectionRange` //
- `textDocument/completion` - Obviously
- `textDocument/onTypeFormatting` - seems promising for auto formatting (indentation etc)
- `textDocument/inlayHint` & `textDocument/inlineHint` & `textDocument/codeLens`
- `textDocument/formatting` & `textDocument/rangeFormatting`
- `textDocument/semanticTokens/*` (probably tree-sitter is enough)
- `textDocument/linkedEditingRange` - probably useful
@@ -28,9 +26,6 @@ A TUI IDE.
2. One for stuff that only affects highlighting and styles . like symbol highlighting etc.
3. One for Warnings/errors and inlay hints etc. (stuff that adds virtual text to the editor)
4. One for fromatting and stuff like that. (stuff that edits the buffer text)
- [ ] Make tree sitter spans truly incremental - or atleast make them pos based and not byte so minor changes only shifts inline
- And make inner trees incremental too
- [ ] Use LSP to add inlay hints in order to test virtual text. then make an iterator over screen that mimics the renderer for scrolling functions.
- [ ] Add codeium/copilot support for auto-completion (uses the VAI virtual text) as a test phase.
- [ ] Add a whitespace highlighter (nerd font). for spaces and tabs at start/end of line. not as virtual but instead at render time.
- [ ] Once renderer is proven to work well (i.e. redo this commit) merge `experimental` branch into `main`. commit `43f443e` on `experimental`.
@@ -42,7 +37,6 @@ A TUI IDE.
- [ ] Add alt + click to set multiple cursors.
- [ ] Add search / replace along with search / virtual cursors are searched pos.
- [ ] Add support for undo/redo.
- [ ] Add `.scm` files for all the supported languages. (2/14) Done.
- [ ] Add splash screen / minigame jumping.
- [ ] Normalize / validate unicode on file open.
- [ ] Add git stuff.

View File

@@ -14,7 +14,7 @@
(#match? @variable.builtin
"^(arguments|console|window|document|globalThis|process|module|exports)$"))
;; #59C2FF #000000 0 0 0 3
;; #59C2FF #000000 0 0 0 1
((identifier) @constructor
(#match? @constructor "^[A-Z][a-zA-Z0-9]*$"))
@@ -84,12 +84,11 @@
key: (property_identifier) @name
value: [(arrow_function) (function_expression)]) @definition.function
;; #59C2FF #000000 0 0 0 2
;; #59C2FF #000000 0 0 0 0
(
(call_expression
function: (identifier) @name) @reference.call
(#not-match? @name "^(require)$")
)
(#not-match? @name "^(require)$"))
;; #7dcfff #000000 0 0 0 2
(new_expression

View File

@@ -94,17 +94,12 @@ struct SpanCursor {
}
};
struct VHint {
Coord pos;
std::string hint;
bool operator<(const VHint &other) const { return pos < other.pos; }
};
struct VWarn {
uint32_t line;
std::string text;
int8_t type; // For hl
int8_t type;
uint32_t start;
uint32_t end{UINT32_MAX};
bool operator<(const VWarn &other) const { return line < other.line; }
};
@@ -123,6 +118,7 @@ struct TSSetBase {
TSParser *parser;
std::string query_file;
TSQuery *query;
TSTree *tree;
std::map<uint16_t, Highlight> query_map;
std::map<uint16_t, Language> injection_map;
const TSLanguage *language;
@@ -133,7 +129,6 @@ struct TSSet : TSSetBase {
};
struct TSSetMain : TSSetBase {
TSTree *tree;
std::unordered_map<std::string, TSSet> injections;
};
@@ -158,7 +153,6 @@ struct Editor {
uint32_t hooks[94];
bool jumper_set;
std::shared_mutex v_mtx;
std::vector<VHint> hints;
std::vector<VWarn> warnings;
VAI ai;
std::shared_mutex lsp_mtx;

View File

@@ -253,6 +253,25 @@ void render_editor(Editor *editor) {
if (editor->selection_active && absolute_byte_pos >= sel_start &&
absolute_byte_pos < sel_end)
bg = 0x555555;
for (const auto &w : line_warnings) {
if (w.start <= current_byte_offset + local_render_offset &&
current_byte_offset + local_render_offset < w.end) {
switch (w.type) {
case 1:
bg = 0x500000;
break;
case 2:
bg = 0x505000;
break;
case 3:
bg = 0x500050;
break;
case 4:
bg = 0x505050;
break;
}
}
}
uint32_t cluster_len = grapheme_next_character_break_utf8(
line + current_byte_offset + local_render_offset, line_left);
std::string cluster(line + current_byte_offset + local_render_offset,

View File

@@ -611,6 +611,10 @@ void editor_lsp_handle(Editor *editor, json msg) {
json d = diagnostics[i];
VWarn w;
w.line = d["range"]["start"]["line"];
w.start = d["range"]["start"]["character"];
uint32_t end = d["range"]["end"]["character"];
if (d["range"]["end"]["line"] == w.line)
w.end = end;
std::string text = d["message"].get<std::string>();
auto pos = text.find('\n');
w.text = (pos == std::string::npos) ? text : text.substr(0, pos);

View File

@@ -204,35 +204,40 @@ void ts_collect_spans(Editor *editor) {
.encoding = TSInputEncodingUTF8,
.decode = nullptr,
};
TSTree *tree = nullptr;
TSTree *copy = nullptr;
std::unique_lock knot_mtx(editor->knot_mtx);
if (editor->ts.tree)
copy = ts_tree_copy(editor->ts.tree);
knot_mtx.unlock();
std::vector<TSInputEdit> edits;
TSInputEdit edit;
if (copy)
while (editor->edit_queue.pop(edit)) {
if (!editor->edit_queue.empty()) {
while (editor->edit_queue.pop(edit))
edits.push_back(edit);
ts_tree_edit(copy, &edits.back());
if (editor->ts.tree) {
for (auto &e : edits)
ts_tree_edit(editor->ts.tree, &e);
}
if (copy && edits.empty() && parse_counter < 64) {
for (auto &inj : editor->ts.injections) {
if (inj.second.tree) {
for (auto &e : edits) {
TSInputEdit inj_edit = e;
for (auto &r : inj.second.ranges) {
if (e.start_byte >= r.start_byte && e.start_byte <= r.end_byte) {
inj_edit.start_byte -= r.start_byte;
inj_edit.old_end_byte -= r.start_byte;
inj_edit.new_end_byte -= r.start_byte;
}
}
ts_tree_edit(inj.second.tree, &inj_edit);
}
}
}
} else if (editor->ts.tree && parse_counter < 64) {
parse_counter++;
ts_tree_delete(copy);
return;
}
parse_counter = 0;
editor->spans.mid_parse = true;
std::shared_lock lock(editor->knot_mtx);
tree = ts_parser_parse(editor->ts.parser, copy, tsinput);
editor->ts.tree =
ts_parser_parse(editor->ts.parser, editor->ts.tree, tsinput);
lock.unlock();
if (copy)
ts_tree_delete(copy);
if (editor->ts.tree)
ts_tree_delete(editor->ts.tree);
editor->ts.tree = tree;
copy = ts_tree_copy(tree);
std::vector<Span> new_spans;
new_spans.reserve(4096);
struct PendingRanges {
@@ -243,12 +248,11 @@ void ts_collect_spans(Editor *editor) {
TSSetBase *tsset;
TSTree *tree;
int depth;
TSSet *as_injection;
};
const int kMaxInjectionDepth = 4;
std::vector<WorkItem> work;
work.push_back(
{reinterpret_cast<TSSetBase *>(&editor->ts), copy, 0, nullptr});
{reinterpret_cast<TSSetBase *>(&editor->ts), editor->ts.tree, 0});
auto overlaps = [](const Span &s, const TSRange &r) {
return !(s.end <= r.start_byte || s.start >= r.end_byte);
};
@@ -268,12 +272,10 @@ void ts_collect_spans(Editor *editor) {
WorkItem item = work.back();
work.pop_back();
TSQuery *q = item.tsset->query;
if (!q) {
ts_tree_delete(item.tree);
if (!q)
continue;
}
TSQueryCursor *cursor = ts_query_cursor_new();
ts_query_cursor_exec(cursor, q, ts_tree_root_node(item.tree));
ts_query_cursor_exec(cursor, q, ts_tree_root_node(item.tsset->tree));
std::unordered_map<std::string, PendingRanges> pending_injections;
TSQueryMatch match;
while (ts_query_cursor_next_match(cursor, &match)) {
@@ -322,13 +324,12 @@ void ts_collect_spans(Editor *editor) {
ts_parser_set_included_ranges(tsset->parser, tsset->ranges.data(),
tsset->ranges.size());
lock.lock();
TSTree *inj_tree = ts_parser_parse(tsset->parser, nullptr, tsinput);
tsset->tree = ts_parser_parse(tsset->parser, tsset->tree, tsinput);
lock.unlock();
work.push_back({reinterpret_cast<TSSetBase *>(tsset), inj_tree,
item.depth + 1, tsset});
work.push_back({reinterpret_cast<TSSetBase *>(tsset), tsset->tree,
item.depth + 1});
}
}
ts_tree_delete(item.tree);
}
std::pair<uint32_t, int64_t> span_edit;
while (editor->spans.edits.pop(span_edit))