Add jumping hooks for faster navigation
This commit is contained in:
@@ -6,7 +6,6 @@ A TUI IDE.
|
|||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
- [ ] Add `hooks` in files that can be set/unset/jumped to.
|
|
||||||
- [ ] Add folding support at tree-sitter level (basic folding is done).
|
- [ ] Add folding support at tree-sitter level (basic folding is done).
|
||||||
- [ ] Add feature where doing enter uses tree-sitter to add newline with indentation.
|
- [ ] Add feature where doing enter uses tree-sitter to add newline with indentation.
|
||||||
- it should also put stuff like `}` on the next line.
|
- it should also put stuff like `}` on the next line.
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
#define WORD 1
|
#define WORD 1
|
||||||
#define LINE 2
|
#define LINE 2
|
||||||
|
|
||||||
|
#define EXTRA_META 3
|
||||||
|
|
||||||
struct Highlight {
|
struct Highlight {
|
||||||
uint32_t fg;
|
uint32_t fg;
|
||||||
uint32_t bg;
|
uint32_t bg;
|
||||||
@@ -107,8 +109,11 @@ struct Editor {
|
|||||||
Spans spans;
|
Spans spans;
|
||||||
Spans def_spans;
|
Spans def_spans;
|
||||||
std::map<uint32_t, bool> folded_node;
|
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);
|
Editor *new_editor(const char *filename, Coord position, Coord size);
|
||||||
void free_editor(Editor *editor);
|
void free_editor(Editor *editor);
|
||||||
void render_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_cursor(Editor *editor);
|
||||||
void ensure_scroll(Editor *editor);
|
void ensure_scroll(Editor *editor);
|
||||||
void handle_editor_event(Editor *editor, KeyEvent event);
|
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_erase(Editor *editor, Coord pos, int64_t len);
|
||||||
void edit_insert(Editor *editor, Coord pos, char *data, uint32_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);
|
Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#define INSERT 1
|
#define INSERT 1
|
||||||
#define SELECT 2
|
#define SELECT 2
|
||||||
#define RUNNER 3
|
#define RUNNER 3
|
||||||
|
#define JUMPER 4
|
||||||
|
|
||||||
extern std::atomic<bool> running;
|
extern std::atomic<bool> running;
|
||||||
extern uint8_t mode;
|
extern uint8_t mode;
|
||||||
|
|||||||
@@ -20,12 +20,7 @@ Editor *new_editor(const char *filename, Coord position, Coord size) {
|
|||||||
editor->filename = filename;
|
editor->filename = filename;
|
||||||
editor->position = position;
|
editor->position = position;
|
||||||
editor->size = size;
|
editor->size = size;
|
||||||
editor->tree = nullptr;
|
|
||||||
editor->cursor = {0, 0};
|
|
||||||
editor->cursor_preffered = UINT32_MAX;
|
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));
|
editor->root = load(str, len, optimal_chunk_size(len));
|
||||||
free(str);
|
free(str);
|
||||||
editor->folded.resize(editor->root->line_count + 2);
|
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) {
|
void render_editor(Editor *editor) {
|
||||||
uint32_t sel_start = 0, sel_end = 0;
|
uint32_t sel_start = 0, sel_end = 0;
|
||||||
uint32_t numlen =
|
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_width = editor->size.col - numlen;
|
||||||
uint32_t render_x = editor->position.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);
|
std::shared_lock knot_lock(editor->knot_mtx);
|
||||||
if (editor->selection_active) {
|
if (editor->selection_active) {
|
||||||
Coord start, end;
|
Coord start, end;
|
||||||
@@ -167,8 +167,16 @@ void render_editor(Editor *editor) {
|
|||||||
while (current_byte_offset < line_len && rendered_rows < editor->size.row) {
|
while (current_byte_offset < line_len && rendered_rows < editor->size.row) {
|
||||||
uint32_t color = editor->cursor.row == line_index ? 0x222222 : 0;
|
uint32_t color = editor->cursor.row == line_index ? 0x222222 : 0;
|
||||||
if (current_byte_offset == 0 || rendered_rows == 0) {
|
if (current_byte_offset == 0 || rendered_rows == 0) {
|
||||||
char buf[16];
|
char buf[EXTRA_META + 16];
|
||||||
int len = snprintf(buf, sizeof(buf), "%*u", numlen - 1, line_index + 1);
|
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 =
|
uint32_t num_color =
|
||||||
editor->cursor.row == line_index ? 0xFFFFFF : 0x555555;
|
editor->cursor.row == line_index ? 0xFFFFFF : 0x555555;
|
||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
@@ -244,8 +252,16 @@ void render_editor(Editor *editor) {
|
|||||||
if (line_len == 0 ||
|
if (line_len == 0 ||
|
||||||
(current_byte_offset >= line_len && rendered_rows == 0)) {
|
(current_byte_offset >= line_len && rendered_rows == 0)) {
|
||||||
uint32_t color = editor->cursor.row == line_index ? 0x222222 : 0;
|
uint32_t color = editor->cursor.row == line_index ? 0x222222 : 0;
|
||||||
char buf[16];
|
char buf[EXTRA_META + 16];
|
||||||
int len = snprintf(buf, sizeof(buf), "%*u", numlen - 1, line_index + 1);
|
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 =
|
uint32_t num_color =
|
||||||
editor->cursor.row == line_index ? 0xFFFFFF : 0x555555;
|
editor->cursor.row == line_index ? 0xFFFFFF : 0x555555;
|
||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
@@ -283,6 +299,7 @@ void render_editor(Editor *editor) {
|
|||||||
case INSERT:
|
case INSERT:
|
||||||
type = CURSOR;
|
type = CURSOR;
|
||||||
break;
|
break;
|
||||||
|
case JUMPER:
|
||||||
case SELECT:
|
case SELECT:
|
||||||
type = UNDERLINE;
|
type = UNDERLINE;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -215,6 +215,21 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
|
|||||||
case 'i':
|
case 'i':
|
||||||
mode = INSERT;
|
mode = INSERT;
|
||||||
break;
|
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 's':
|
||||||
case 'v':
|
case 'v':
|
||||||
mode = SELECT;
|
mode = SELECT;
|
||||||
@@ -359,6 +374,26 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case RUNNER:
|
||||||
if (event.key_type == KEY_CHAR && event.len == 1) {
|
if (event.key_type == KEY_CHAR && event.len == 1) {
|
||||||
switch (event.c[0]) {
|
switch (event.c[0]) {
|
||||||
@@ -528,7 +563,7 @@ Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y) {
|
|||||||
if (mode == INSERT)
|
if (mode == INSERT)
|
||||||
x++;
|
x++;
|
||||||
uint32_t numlen =
|
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_width = editor->size.col - numlen;
|
||||||
x = MAX(x, numlen) - numlen;
|
x = MAX(x, numlen) - numlen;
|
||||||
uint32_t target_visual_row = y;
|
uint32_t target_visual_row = y;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ extern "C" {
|
|||||||
void scroll_up(Editor *editor, uint32_t number) {
|
void scroll_up(Editor *editor, uint32_t number) {
|
||||||
number++;
|
number++;
|
||||||
uint32_t numlen =
|
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_width = editor->size.col - numlen;
|
||||||
Coord *scroll_queue = (Coord *)malloc(sizeof(Coord) * number);
|
Coord *scroll_queue = (Coord *)malloc(sizeof(Coord) * number);
|
||||||
uint32_t q_head = 0;
|
uint32_t q_head = 0;
|
||||||
@@ -79,7 +79,7 @@ void scroll_down(Editor *editor, uint32_t number) {
|
|||||||
if (!editor || number == 0)
|
if (!editor || number == 0)
|
||||||
return;
|
return;
|
||||||
uint32_t numlen =
|
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_width = editor->size.col - numlen;
|
||||||
uint32_t line_index = editor->scroll.row;
|
uint32_t line_index = editor->scroll.row;
|
||||||
LineIterator *it = begin_l_iter(editor->root, line_index);
|
LineIterator *it = begin_l_iter(editor->root, line_index);
|
||||||
@@ -185,7 +185,7 @@ void ensure_cursor(Editor *editor) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t numlen =
|
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_width = editor->size.col - numlen;
|
||||||
uint32_t visual_rows = 0;
|
uint32_t visual_rows = 0;
|
||||||
uint32_t line_index = editor->scroll.row;
|
uint32_t line_index = editor->scroll.row;
|
||||||
@@ -267,7 +267,7 @@ void ensure_cursor(Editor *editor) {
|
|||||||
void ensure_scroll(Editor *editor) {
|
void ensure_scroll(Editor *editor) {
|
||||||
std::shared_lock knot_lock(editor->knot_mtx);
|
std::shared_lock knot_lock(editor->knot_mtx);
|
||||||
uint32_t numlen =
|
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_width = editor->size.col - numlen;
|
||||||
if (editor->cursor < editor->scroll) {
|
if (editor->cursor < editor->scroll) {
|
||||||
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
|
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
|
||||||
|
|||||||
Reference in New Issue
Block a user