From d82389bc42461462669130526d5dfe1172677a80 Mon Sep 17 00:00:00 2001 From: Syed Daanish Date: Sun, 14 Dec 2025 12:17:38 +0000 Subject: [PATCH] Add jumping hooks for faster navigation --- README.md | 1 - include/editor.h | 6 +++++- include/main.h | 1 + src/editor.cc | 37 +++++++++++++++++++++++++++---------- src/editor_ctrl.cc | 37 ++++++++++++++++++++++++++++++++++++- src/editor_scroll.cc | 8 ++++---- 6 files changed, 73 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index c3a05e3..8f1b65a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ A TUI IDE. # TODO -- [ ] Add `hooks` in files that can be set/unset/jumped to. - [ ] Add folding support at tree-sitter level (basic folding is done). - [ ] Add feature where doing enter uses tree-sitter to add newline with indentation. - it should also put stuff like `}` on the next line. diff --git a/include/editor.h b/include/editor.h index a125b8f..3c8ddbd 100644 --- a/include/editor.h +++ b/include/editor.h @@ -15,6 +15,8 @@ #define WORD 1 #define LINE 2 +#define EXTRA_META 3 + struct Highlight { uint32_t fg; uint32_t bg; @@ -107,8 +109,11 @@ struct Editor { Spans spans; Spans def_spans; std::map folded_node; + uint32_t hooks[94]; + bool jumper_set; }; +void apply_edit(std::vector &spans, uint32_t x, int64_t y); Editor *new_editor(const char *filename, Coord position, Coord size); void free_editor(Editor *editor); void render_editor(Editor *editor); @@ -124,7 +129,6 @@ void scroll_down(Editor *editor, uint32_t number); void ensure_cursor(Editor *editor); void ensure_scroll(Editor *editor); void handle_editor_event(Editor *editor, KeyEvent event); -void apply_edit(std::vector &spans, uint32_t x, int64_t y); void edit_erase(Editor *editor, Coord pos, int64_t len); void edit_insert(Editor *editor, Coord pos, char *data, uint32_t len); Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y); diff --git a/include/main.h b/include/main.h index e16d952..76f0967 100644 --- a/include/main.h +++ b/include/main.h @@ -8,6 +8,7 @@ #define INSERT 1 #define SELECT 2 #define RUNNER 3 +#define JUMPER 4 extern std::atomic running; extern uint8_t mode; diff --git a/src/editor.cc b/src/editor.cc index 2cc8bda..ec8a2d8 100644 --- a/src/editor.cc +++ b/src/editor.cc @@ -20,12 +20,7 @@ Editor *new_editor(const char *filename, Coord position, Coord size) { editor->filename = filename; editor->position = position; editor->size = size; - editor->tree = nullptr; - editor->cursor = {0, 0}; editor->cursor_preffered = UINT32_MAX; - editor->selection_active = false; - editor->selection = {0, 0}; - editor->scroll = {0, 0}; editor->root = load(str, len, optimal_chunk_size(len)); free(str); editor->folded.resize(editor->root->line_count + 2); @@ -71,9 +66,14 @@ void update_render_fold_marker(uint32_t row, uint32_t cols) { void render_editor(Editor *editor) { uint32_t sel_start = 0, sel_end = 0; uint32_t numlen = - 2 + static_cast(std::log10(editor->root->line_count + 1)); + EXTRA_META + static_cast(std::log10(editor->root->line_count + 1)); uint32_t render_width = editor->size.col - numlen; uint32_t render_x = editor->position.col + numlen; + std::vector> v; + for (size_t i = 0; i < 94; ++i) + if (editor->hooks[i] != 0) + v.push_back({editor->hooks[i], '!' + i}); + std::sort(v.begin(), v.end()); std::shared_lock knot_lock(editor->knot_mtx); if (editor->selection_active) { Coord start, end; @@ -167,8 +167,16 @@ void render_editor(Editor *editor) { while (current_byte_offset < line_len && rendered_rows < editor->size.row) { uint32_t color = editor->cursor.row == line_index ? 0x222222 : 0; if (current_byte_offset == 0 || rendered_rows == 0) { - char buf[16]; - int len = snprintf(buf, sizeof(buf), "%*u", numlen - 1, line_index + 1); + char buf[EXTRA_META + 16]; + char hook = ' '; + for (auto &p : v) { + if (p.first == line_index + 1) { + hook = p.second; + break; + } + } + int len = snprintf(buf, sizeof(buf), "%c%*u", hook, numlen - 2, + line_index + 1); uint32_t num_color = editor->cursor.row == line_index ? 0xFFFFFF : 0x555555; for (int i = 0; i < len; i++) @@ -244,8 +252,16 @@ void render_editor(Editor *editor) { if (line_len == 0 || (current_byte_offset >= line_len && rendered_rows == 0)) { uint32_t color = editor->cursor.row == line_index ? 0x222222 : 0; - char buf[16]; - int len = snprintf(buf, sizeof(buf), "%*u", numlen - 1, line_index + 1); + char buf[EXTRA_META + 16]; + char hook = ' '; + for (auto &p : v) { + if (p.first == line_index + 1) { + hook = p.second; + break; + } + } + int len = + snprintf(buf, sizeof(buf), "%c%*u", hook, numlen - 2, line_index + 1); uint32_t num_color = editor->cursor.row == line_index ? 0xFFFFFF : 0x555555; for (int i = 0; i < len; i++) @@ -283,6 +299,7 @@ void render_editor(Editor *editor) { case INSERT: type = CURSOR; break; + case JUMPER: case SELECT: type = UNDERLINE; break; diff --git a/src/editor_ctrl.cc b/src/editor_ctrl.cc index 46efd46..ba79f14 100644 --- a/src/editor_ctrl.cc +++ b/src/editor_ctrl.cc @@ -215,6 +215,21 @@ void handle_editor_event(Editor *editor, KeyEvent event) { case 'i': mode = INSERT; break; + case 'n': + mode = JUMPER; + editor->jumper_set = true; + break; + case 'm': + mode = JUMPER; + editor->jumper_set = false; + break; + case 'N': + for (uint8_t i = 0; i < 94; i++) + if (editor->hooks[i] == editor->cursor.row + 1) { + editor->hooks[i] = 0; + break; + } + break; case 's': case 'v': mode = SELECT; @@ -359,6 +374,26 @@ void handle_editor_event(Editor *editor, KeyEvent event) { } } break; + case JUMPER: + if (event.key_type == KEY_CHAR && event.len == 1 && + (event.c[0] > '!' && event.c[0] < '~')) { + if (editor->jumper_set) { + for (uint8_t i = 0; i < 94; i++) + if (editor->hooks[i] == editor->cursor.row + 1) { + editor->hooks[i] = 0; + break; + } + editor->hooks[event.c[0] - '!'] = editor->cursor.row + 1; + } else { + uint32_t line = editor->hooks[event.c[0] - '!']; + if (line > 0) { + editor->cursor = {line - 1, 0}; + editor->cursor_preffered = UINT32_MAX; + } + } + } + mode = NORMAL; + break; case RUNNER: if (event.key_type == KEY_CHAR && event.len == 1) { switch (event.c[0]) { @@ -528,7 +563,7 @@ Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y) { if (mode == INSERT) x++; uint32_t numlen = - 2 + static_cast(std::log10(editor->root->line_count + 1)); + EXTRA_META + static_cast(std::log10(editor->root->line_count + 1)); uint32_t render_width = editor->size.col - numlen; x = MAX(x, numlen) - numlen; uint32_t target_visual_row = y; diff --git a/src/editor_scroll.cc b/src/editor_scroll.cc index 63115d3..5dcb45a 100644 --- a/src/editor_scroll.cc +++ b/src/editor_scroll.cc @@ -9,7 +9,7 @@ extern "C" { void scroll_up(Editor *editor, uint32_t number) { number++; uint32_t numlen = - 2 + static_cast(std::log10(editor->root->line_count + 1)); + EXTRA_META + static_cast(std::log10(editor->root->line_count + 1)); uint32_t render_width = editor->size.col - numlen; Coord *scroll_queue = (Coord *)malloc(sizeof(Coord) * number); uint32_t q_head = 0; @@ -79,7 +79,7 @@ void scroll_down(Editor *editor, uint32_t number) { if (!editor || number == 0) return; uint32_t numlen = - 2 + static_cast(std::log10(editor->root->line_count + 1)); + EXTRA_META + static_cast(std::log10(editor->root->line_count + 1)); uint32_t render_width = editor->size.col - numlen; uint32_t line_index = editor->scroll.row; LineIterator *it = begin_l_iter(editor->root, line_index); @@ -185,7 +185,7 @@ void ensure_cursor(Editor *editor) { return; } uint32_t numlen = - 2 + static_cast(std::log10(editor->root->line_count + 1)); + EXTRA_META + static_cast(std::log10(editor->root->line_count + 1)); uint32_t render_width = editor->size.col - numlen; uint32_t visual_rows = 0; uint32_t line_index = editor->scroll.row; @@ -267,7 +267,7 @@ void ensure_cursor(Editor *editor) { void ensure_scroll(Editor *editor) { std::shared_lock knot_lock(editor->knot_mtx); uint32_t numlen = - 2 + static_cast(std::log10(editor->root->line_count + 1)); + EXTRA_META + static_cast(std::log10(editor->root->line_count + 1)); uint32_t render_width = editor->size.col - numlen; if (editor->cursor < editor->scroll) { LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);