Minor fixes
This commit is contained in:
3
Makefile
3
Makefile
@@ -29,7 +29,6 @@ LIBS := \
|
|||||||
libs/tree-sitter-ruby/libtree-sitter-ruby.a \
|
libs/tree-sitter-ruby/libtree-sitter-ruby.a \
|
||||||
-lpcre2-8
|
-lpcre2-8
|
||||||
|
|
||||||
|
|
||||||
SRC := $(wildcard $(SRC_DIR)/*.cc)
|
SRC := $(wildcard $(SRC_DIR)/*.cc)
|
||||||
OBJ_DEBUG := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/debug/%.o,$(SRC))
|
OBJ_DEBUG := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/debug/%.o,$(SRC))
|
||||||
OBJ_RELEASE := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/release/%.o,$(SRC))
|
OBJ_RELEASE := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/release/%.o,$(SRC))
|
||||||
@@ -53,7 +52,6 @@ $(TARGET_RELEASE): $(OBJ_RELEASE) $(UNICODE_OBJ_RELEASE)
|
|||||||
mkdir -p $(BIN_DIR)
|
mkdir -p $(BIN_DIR)
|
||||||
$(CXX_RELEASE) $(CFLAGS_RELEASE) -o $@ $^ $(LIBS)
|
$(CXX_RELEASE) $(CFLAGS_RELEASE) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
# Pattern rules for object files + dependency generation
|
|
||||||
$(OBJ_DIR)/debug/%.o: $(SRC_DIR)/%.cc
|
$(OBJ_DIR)/debug/%.o: $(SRC_DIR)/%.cc
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
$(CXX_DEBUG) $(CFLAGS_DEBUG) -MMD -MP -c $< -o $@
|
$(CXX_DEBUG) $(CFLAGS_DEBUG) -MMD -MP -c $< -o $@
|
||||||
@@ -70,7 +68,6 @@ $(OBJ_DIR)/release/unicode_width/%.o: libs/unicode_width/%.c
|
|||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
$(CXX_RELEASE) $(CFLAGS_RELEASE) -MMD -MP -c $< -o $@
|
$(CXX_RELEASE) $(CFLAGS_RELEASE) -MMD -MP -c $< -o $@
|
||||||
|
|
||||||
# Include deps if they exist
|
|
||||||
DEP_DEBUG += $(UNICODE_OBJ_DEBUG:.o=.d)
|
DEP_DEBUG += $(UNICODE_OBJ_DEBUG:.o=.d)
|
||||||
DEP_RELEASE += $(UNICODE_OBJ_RELEASE:.o=.d)
|
DEP_RELEASE += $(UNICODE_OBJ_RELEASE:.o=.d)
|
||||||
|
|
||||||
|
|||||||
@@ -3,3 +3,8 @@ Copyright 2025 Syed Daanish
|
|||||||
# Crib
|
# Crib
|
||||||
|
|
||||||
A TUI IDE.
|
A TUI IDE.
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
|
||||||
|
- [ ] VERY HIGH PRIORITY: fix bug when moving upwards into wrapped line (cuses random line amongst the wrapped lines to be visually focused while in reality the top is selected), has be somewhere in `ensure_scroll` function.
|
||||||
|
- [ ] Add support for wide characters with wrapping.
|
||||||
|
|||||||
@@ -142,17 +142,17 @@
|
|||||||
((identifier) @keyword.modifier
|
((identifier) @keyword.modifier
|
||||||
(#match? @keyword.modifier "^(private|protected|public)$" ))
|
(#match? @keyword.modifier "^(private|protected|public)$" ))
|
||||||
|
|
||||||
;; #fbb152 #000000 0 0 0 1
|
;; #fbb152 #000000 0 0 0 3
|
||||||
(program
|
(program
|
||||||
(call
|
(call
|
||||||
(identifier) @keyword.import)
|
(identifier) @keyword.import)
|
||||||
(#match? @keyword.import "^(require|require_relative|load)$"))
|
(#match? @keyword.import "^(require|require_relative|load)$"))
|
||||||
|
|
||||||
;; #fbb152 #000000 0 0 0 2
|
;; #fbb152 #000000 0 0 0 4
|
||||||
((identifier) @constant.builtin
|
((identifier) @constant.builtin
|
||||||
(#match? @constant.builtin "^(__callee__|__dir__|__id__|__method__|__send__|__ENCODING__|__FILE__|__LINE__)$" ))
|
(#match? @constant.builtin "^(__callee__|__dir__|__id__|__method__|__send__|__ENCODING__|__FILE__|__LINE__)$" ))
|
||||||
|
|
||||||
;; #aad84c #000000 0 0 0 1
|
;; #aad84c #000000 0 0 0 3
|
||||||
((identifier) @function.builtin
|
((identifier) @function.builtin
|
||||||
(#match? @function.builtin "^(attr_reader|attr_writer|attr_accessor|module_function)$" ))
|
(#match? @function.builtin "^(attr_reader|attr_writer|attr_accessor|module_function)$" ))
|
||||||
|
|
||||||
|
|||||||
@@ -31,31 +31,6 @@ struct Spans {
|
|||||||
Queue<std::pair<uint32_t, int64_t>> edits;
|
Queue<std::pair<uint32_t, int64_t>> edits;
|
||||||
bool mid_parse = false;
|
bool mid_parse = false;
|
||||||
std::shared_mutex mtx;
|
std::shared_mutex mtx;
|
||||||
|
|
||||||
void apply(uint32_t x, int64_t y) {
|
|
||||||
std::unique_lock lock(mtx);
|
|
||||||
auto it = std::lower_bound(
|
|
||||||
spans.begin(), spans.end(), Span{.start = x, .end = 0, .hl = nullptr},
|
|
||||||
[](auto &a, auto &b) { return a.start < b.start; });
|
|
||||||
while (it != spans.begin()) {
|
|
||||||
auto prev = std::prev(it);
|
|
||||||
if (prev->end <= x)
|
|
||||||
break;
|
|
||||||
it = prev;
|
|
||||||
}
|
|
||||||
while (it != spans.end()) {
|
|
||||||
if (it->start < x && it->end > x) {
|
|
||||||
it->end += y;
|
|
||||||
} else if (it->start > x) {
|
|
||||||
it->start += y;
|
|
||||||
it->end += y;
|
|
||||||
}
|
|
||||||
if (it->end <= it->start)
|
|
||||||
it = spans.erase(it);
|
|
||||||
else
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SpanCursor {
|
struct SpanCursor {
|
||||||
@@ -145,5 +120,6 @@ void cursor_down(Editor *editor, uint32_t number);
|
|||||||
void cursor_left(Editor *editor, uint32_t number);
|
void cursor_left(Editor *editor, uint32_t number);
|
||||||
void cursor_right(Editor *editor, uint32_t number);
|
void cursor_right(Editor *editor, uint32_t number);
|
||||||
void ensure_scroll(Editor *editor);
|
void ensure_scroll(Editor *editor);
|
||||||
|
void apply_edit(std::vector<Span> &spans, uint32_t x, int64_t y);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -40,19 +40,20 @@ Editor *new_editor(const char *filename, Coord position, Coord size) {
|
|||||||
editor->size = size;
|
editor->size = size;
|
||||||
editor->tree = nullptr;
|
editor->tree = nullptr;
|
||||||
editor->cursor = {0, 0};
|
editor->cursor = {0, 0};
|
||||||
|
editor->cursor_preffered = UINT32_MAX;
|
||||||
editor->selection_active = false;
|
editor->selection_active = false;
|
||||||
editor->selection = {0, 0};
|
editor->selection = {0, 0};
|
||||||
editor->scroll = {0, 0};
|
editor->scroll = {0, 0};
|
||||||
editor->root = load(str, len, optimal_chunk_size(len));
|
editor->root = load(str, len, optimal_chunk_size(len));
|
||||||
|
free(str);
|
||||||
editor->folded.resize(editor->root->line_count + 2);
|
editor->folded.resize(editor->root->line_count + 2);
|
||||||
std::string query = get_exe_dir() + "/../grammar/ruby.scm";
|
std::string query = get_exe_dir() + "/../grammar/ruby.scm";
|
||||||
if (!(len > (1024 * 1024))) {
|
if (len < (1024 * 64)) {
|
||||||
editor->parser = ts_parser_new();
|
editor->parser = ts_parser_new();
|
||||||
editor->language = tree_sitter_ruby();
|
editor->language = tree_sitter_ruby();
|
||||||
ts_parser_set_language(editor->parser, editor->language);
|
ts_parser_set_language(editor->parser, editor->language);
|
||||||
editor->query = load_query(query.c_str(), editor);
|
editor->query = load_query(query.c_str(), editor);
|
||||||
}
|
}
|
||||||
free(str);
|
|
||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,8 +184,10 @@ void cursor_down(Editor *editor, uint32_t number) {
|
|||||||
char *line_content = next_line(it);
|
char *line_content = next_line(it);
|
||||||
if (line_content == nullptr)
|
if (line_content == nullptr)
|
||||||
return;
|
return;
|
||||||
uint32_t visual_col =
|
if (editor->cursor_preffered == UINT32_MAX)
|
||||||
get_visual_col_from_bytes(line_content, editor->cursor.col);
|
editor->cursor_preffered =
|
||||||
|
get_visual_col_from_bytes(line_content, editor->cursor.col);
|
||||||
|
uint32_t visual_col = editor->cursor_preffered;
|
||||||
do {
|
do {
|
||||||
free(line_content);
|
free(line_content);
|
||||||
line_content = next_line(it);
|
line_content = next_line(it);
|
||||||
@@ -212,8 +215,10 @@ void cursor_up(Editor *editor, uint32_t number) {
|
|||||||
free(it);
|
free(it);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t visual_col =
|
if (editor->cursor_preffered == UINT32_MAX)
|
||||||
get_visual_col_from_bytes(line_content, editor->cursor.col);
|
editor->cursor_preffered =
|
||||||
|
get_visual_col_from_bytes(line_content, editor->cursor.col);
|
||||||
|
uint32_t visual_col = editor->cursor_preffered;
|
||||||
free(line_content);
|
free(line_content);
|
||||||
while (number > 0 && editor->cursor.row > 0) {
|
while (number > 0 && editor->cursor.row > 0) {
|
||||||
editor->cursor.row--;
|
editor->cursor.row--;
|
||||||
@@ -275,6 +280,19 @@ void cursor_right(Editor *editor, uint32_t number) {
|
|||||||
}
|
}
|
||||||
number--;
|
number--;
|
||||||
}
|
}
|
||||||
|
LineIterator *it2 = begin_l_iter(editor->root, editor->cursor.row);
|
||||||
|
char *cur_line = next_line(it2);
|
||||||
|
free(it2);
|
||||||
|
if (cur_line) {
|
||||||
|
uint32_t len2 = strlen(cur_line);
|
||||||
|
if (len2 > 0 && cur_line[len2 - 1] == '\n')
|
||||||
|
cur_line[--len2] = '\0';
|
||||||
|
editor->cursor_preffered =
|
||||||
|
get_visual_col_from_bytes(cur_line, editor->cursor.col);
|
||||||
|
free(cur_line);
|
||||||
|
} else {
|
||||||
|
editor->cursor_preffered = UINT32_MAX;
|
||||||
|
}
|
||||||
if (line)
|
if (line)
|
||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
@@ -328,6 +346,19 @@ void cursor_left(Editor *editor, uint32_t number) {
|
|||||||
}
|
}
|
||||||
number--;
|
number--;
|
||||||
}
|
}
|
||||||
|
LineIterator *it2 = begin_l_iter(editor->root, editor->cursor.row);
|
||||||
|
char *cur_line = next_line(it2);
|
||||||
|
free(it2);
|
||||||
|
if (cur_line) {
|
||||||
|
uint32_t len2 = strlen(cur_line);
|
||||||
|
if (len2 > 0 && cur_line[len2 - 1] == '\n')
|
||||||
|
cur_line[--len2] = '\0';
|
||||||
|
editor->cursor_preffered =
|
||||||
|
get_visual_col_from_bytes(cur_line, editor->cursor.col);
|
||||||
|
free(cur_line);
|
||||||
|
} else {
|
||||||
|
editor->cursor_preffered = UINT32_MAX;
|
||||||
|
}
|
||||||
if (line)
|
if (line)
|
||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
@@ -376,6 +407,29 @@ void update_render_fold_marker(uint32_t row, uint32_t cols) {
|
|||||||
update(row, i, " ", 0xc6c6c6, 0, 0);
|
update(row, i, " ", 0xc6c6c6, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void apply_edit(std::vector<Span> &spans, uint32_t x, int64_t y) {
|
||||||
|
Span key{.start = x, .end = 0, .hl = nullptr};
|
||||||
|
auto it = std::lower_bound(
|
||||||
|
spans.begin(), spans.end(), key,
|
||||||
|
[](const Span &a, const Span &b) { return a.start < b.start; });
|
||||||
|
size_t idx = std::distance(spans.begin(), it);
|
||||||
|
while (idx > 0 && spans.at(idx - 1).end > x)
|
||||||
|
--idx;
|
||||||
|
for (size_t i = idx; i < spans.size();) {
|
||||||
|
Span &s = spans.at(i);
|
||||||
|
if (s.start < x && s.end > x) {
|
||||||
|
s.end += y;
|
||||||
|
} else if (s.start > x) {
|
||||||
|
s.start += y;
|
||||||
|
s.end += y;
|
||||||
|
}
|
||||||
|
if (s.end <= s.start)
|
||||||
|
spans.erase(spans.begin() + i);
|
||||||
|
else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void render_editor(Editor *editor) {
|
void render_editor(Editor *editor) {
|
||||||
uint32_t screen_rows = editor->size.row;
|
uint32_t screen_rows = editor->size.row;
|
||||||
uint32_t screen_cols = editor->size.col;
|
uint32_t screen_cols = editor->size.col;
|
||||||
|
|||||||
19
src/main.cc
19
src/main.cc
@@ -75,10 +75,10 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
|
|||||||
};
|
};
|
||||||
editor->edit_queue.push(edit);
|
editor->edit_queue.push(edit);
|
||||||
}
|
}
|
||||||
editor->spans.apply(pos, 1);
|
cursor_right(editor, 1);
|
||||||
|
apply_edit(editor->spans.spans, pos, 1);
|
||||||
if (editor->spans.mid_parse)
|
if (editor->spans.mid_parse)
|
||||||
editor->spans.edits.push({pos, 1});
|
editor->spans.edits.push({pos, 1});
|
||||||
cursor_right(editor, 1);
|
|
||||||
}
|
}
|
||||||
if (event.key_type == KEY_CHAR && event.c == '\t') {
|
if (event.key_type == KEY_CHAR && event.c == '\t') {
|
||||||
std::shared_lock lock_1(editor->knot_mtx);
|
std::shared_lock lock_1(editor->knot_mtx);
|
||||||
@@ -99,10 +99,11 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
|
|||||||
};
|
};
|
||||||
editor->edit_queue.push(edit);
|
editor->edit_queue.push(edit);
|
||||||
}
|
}
|
||||||
editor->spans.apply(pos, 2);
|
cursor_right(editor, 2);
|
||||||
|
std::unique_lock lock_3(editor->spans.mtx);
|
||||||
|
apply_edit(editor->spans.spans, pos, 2);
|
||||||
if (editor->spans.mid_parse)
|
if (editor->spans.mid_parse)
|
||||||
editor->spans.edits.push({pos, 2});
|
editor->spans.edits.push({pos, 2});
|
||||||
cursor_right(editor, 2);
|
|
||||||
}
|
}
|
||||||
if (event.key_type == KEY_CHAR && (event.c == '\n' || event.c == '\r')) {
|
if (event.key_type == KEY_CHAR && (event.c == '\n' || event.c == '\r')) {
|
||||||
std::shared_lock lock_1(editor->knot_mtx);
|
std::shared_lock lock_1(editor->knot_mtx);
|
||||||
@@ -120,14 +121,15 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
|
|||||||
.new_end_byte = pos + 1,
|
.new_end_byte = pos + 1,
|
||||||
.start_point = {editor->cursor.row, editor->cursor.col},
|
.start_point = {editor->cursor.row, editor->cursor.col},
|
||||||
.old_end_point = {editor->cursor.row, editor->cursor.col},
|
.old_end_point = {editor->cursor.row, editor->cursor.col},
|
||||||
.new_end_point = {editor->cursor.row, editor->cursor.col + 1},
|
.new_end_point = {editor->cursor.row + 1, 0},
|
||||||
};
|
};
|
||||||
editor->edit_queue.push(edit);
|
editor->edit_queue.push(edit);
|
||||||
}
|
}
|
||||||
editor->spans.apply(pos + 1, 1);
|
cursor_right(editor, 1);
|
||||||
|
std::unique_lock lock_3(editor->spans.mtx);
|
||||||
|
apply_edit(editor->spans.spans, pos + 1, 1);
|
||||||
if (editor->spans.mid_parse)
|
if (editor->spans.mid_parse)
|
||||||
editor->spans.edits.push({pos + 1, 1});
|
editor->spans.edits.push({pos + 1, 1});
|
||||||
cursor_right(editor, 1);
|
|
||||||
}
|
}
|
||||||
if (event.key_type == KEY_CHAR && event.c == 0x7F) {
|
if (event.key_type == KEY_CHAR && event.c == 0x7F) {
|
||||||
std::shared_lock lock_1(editor->knot_mtx);
|
std::shared_lock lock_1(editor->knot_mtx);
|
||||||
@@ -152,7 +154,8 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
|
|||||||
};
|
};
|
||||||
editor->edit_queue.push(edit);
|
editor->edit_queue.push(edit);
|
||||||
}
|
}
|
||||||
editor->spans.apply(start, start - pos);
|
std::unique_lock lock_3(editor->spans.mtx);
|
||||||
|
apply_edit(editor->spans.spans, start, start - pos);
|
||||||
if (editor->spans.mid_parse)
|
if (editor->spans.mid_parse)
|
||||||
editor->spans.edits.push({start, start - pos});
|
editor->spans.edits.push({start, start - pos});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ static inline bool ts_predicate(TSQuery *query, const TSQueryMatch &match,
|
|||||||
ts_query_predicates_for_pattern(query, match.pattern_index, &step_count);
|
ts_query_predicates_for_pattern(query, match.pattern_index, &step_count);
|
||||||
if (!steps || step_count != 4)
|
if (!steps || step_count != 4)
|
||||||
return true;
|
return true;
|
||||||
if (source->char_count >= (64 * 1024))
|
if (source->char_count >= (16 * 1024))
|
||||||
return false;
|
return false;
|
||||||
std::string command;
|
std::string command;
|
||||||
std::string regex_txt;
|
std::string regex_txt;
|
||||||
@@ -233,11 +233,11 @@ void ts_collect_spans(Editor *editor) {
|
|||||||
if (!running)
|
if (!running)
|
||||||
return;
|
return;
|
||||||
std::sort(new_spans.begin(), new_spans.end());
|
std::sort(new_spans.begin(), new_spans.end());
|
||||||
|
std::pair<uint32_t, int64_t> span_edit;
|
||||||
|
while (editor->spans.edits.pop(span_edit))
|
||||||
|
apply_edit(new_spans, span_edit.first, span_edit.second);
|
||||||
std::unique_lock span_mtx(editor->spans.mtx);
|
std::unique_lock span_mtx(editor->spans.mtx);
|
||||||
editor->spans.mid_parse = false;
|
editor->spans.mid_parse = false;
|
||||||
editor->spans.spans.swap(new_spans);
|
editor->spans.spans.swap(new_spans);
|
||||||
span_mtx.unlock();
|
span_mtx.unlock();
|
||||||
std::pair<uint32_t, int64_t> span_edit;
|
|
||||||
while (editor->spans.edits.pop(span_edit))
|
|
||||||
editor->spans.apply(span_edit.first, span_edit.second);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user