Add jumping hooks for faster navigation

This commit is contained in:
2025-12-14 12:17:38 +00:00
parent 5fae2f3bb6
commit d82389bc42
6 changed files with 73 additions and 17 deletions

View File

@@ -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.

View File

@@ -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<uint32_t, bool> folded_node;
uint32_t hooks[94];
bool jumper_set;
};
void apply_edit(std::vector<Span> &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<Span> &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);

View File

@@ -8,6 +8,7 @@
#define INSERT 1
#define SELECT 2
#define RUNNER 3
#define JUMPER 4
extern std::atomic<bool> running;
extern uint8_t mode;

View File

@@ -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<int>(std::log10(editor->root->line_count + 1));
EXTRA_META + static_cast<int>(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<std::pair<uint32_t, char>> 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;

View File

@@ -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<int>(std::log10(editor->root->line_count + 1));
EXTRA_META + static_cast<int>(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;

View File

@@ -9,7 +9,7 @@ extern "C" {
void scroll_up(Editor *editor, uint32_t number) {
number++;
uint32_t numlen =
2 + static_cast<int>(std::log10(editor->root->line_count + 1));
EXTRA_META + static_cast<int>(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<int>(std::log10(editor->root->line_count + 1));
EXTRA_META + static_cast<int>(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<int>(std::log10(editor->root->line_count + 1));
EXTRA_META + static_cast<int>(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<int>(std::log10(editor->root->line_count + 1));
EXTRA_META + static_cast<int>(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);