Minor fixes and optimizations
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
57
src/ts.cc
57
src/ts.cc
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user