Compare commits

...

2 Commits

Author SHA1 Message Date
eaec32975a CE edit save/restore terminal state
All checks were successful
Build documentation / build-and-deploy (push) Successful in 2m16s
2026-03-07 01:58:47 +01:00
75635bcc2e CE edit modes 2026-03-07 01:32:50 +01:00
3 changed files with 85 additions and 41 deletions

121
ce/edit.c
View File

@@ -27,6 +27,9 @@
struct edit_line { struct edit_line {
struct list_node_link lines_link; struct list_node_link lines_link;
struct list_node_link select_link;
size_t select_start;
size_t select_end;
struct gapbuffer gb; struct gapbuffer gb;
}; };
@@ -35,6 +38,18 @@ struct cursor {
size_t line; size_t line;
}; };
#define EDIT_MODE_NORMAL 0
#define EDIT_MODE_COMAMND 1
static const char* string_modes[] = {
[EDIT_MODE_NORMAL] = "Normal",
[EDIT_MODE_COMAMND] = "Command",
};
struct edit_select {
struct list_node_link* lines;
};
struct editor { struct editor {
struct list_node_link* lines; struct list_node_link* lines;
struct edit_line* current_line; struct edit_line* current_line;
@@ -42,6 +57,8 @@ struct editor {
size_t col_offset; size_t col_offset;
size_t row_offset; size_t row_offset;
size_t total_lines; size_t total_lines;
struct edit_select select;
int mode;
}; };
static struct editor editor; static struct editor editor;
@@ -98,6 +115,8 @@ static size_t count_digits (size_t n) {
} }
void edit_start (const char* file_path, const char* text) { void edit_start (const char* file_path, const char* text) {
mprintf (ANSIQ_SCR_SAVE);
prepare_lines (text); prepare_lines (text);
struct arena temp_arena; struct arena temp_arena;
memset (&temp_arena, 0, sizeof (temp_arena)); memset (&temp_arena, 0, sizeof (temp_arena));
@@ -105,7 +124,7 @@ void edit_start (const char* file_path, const char* text) {
terminal_dimensions (&cols, &rows); terminal_dimensions (&cols, &rows);
mprintf (ANSIQ_SCR_CLR_ALL ANSIQ_CUR_INVISIBLE); mprintf (ANSIQ_CUR_INVISIBLE);
bool edit_run = true; bool edit_run = true;
@@ -207,8 +226,9 @@ void edit_start (const char* file_path, const char* text) {
bbptr += w; bbptr += w;
bb_remaining -= w; bb_remaining -= w;
w = snprintf (bbptr, bb_remaining, " Editing %s; line %zu col %zu" ANSIQ_GR_RESET, file_path, w = snprintf (bbptr, bb_remaining, " Editing %s; line %zu col %zu; Mode: %s" ANSIQ_GR_RESET,
editor.cursor.line + 1, editor.cursor.col + 1); file_path, editor.cursor.line + 1, editor.cursor.col + 1,
string_modes[editor.mode]);
bbptr += w; bbptr += w;
bb_remaining -= w; bb_remaining -= w;
@@ -225,50 +245,58 @@ void edit_start (const char* file_path, const char* text) {
switch (ch) { switch (ch) {
case '\b': case '\b':
if (editor.cursor.col > 0) { if (editor.mode == EDIT_MODE_NORMAL) {
gapbuffer_move (&editor.current_line->gb, editor.cursor.col); if (editor.cursor.col > 0) {
editor.cursor.col--; gapbuffer_move (&editor.current_line->gb, editor.cursor.col);
gapbuffer_backspace (&editor.current_line->gb); editor.cursor.col--;
gapbuffer_backspace (&editor.current_line->gb);
}
} }
break; break;
case '\t': case '\t':
gapbuffer_move (&editor.current_line->gb, editor.cursor.col); if (editor.mode == EDIT_MODE_NORMAL) {
for (size_t i = 0; i < sizeof (TAB_INSERT) - 1; i++) gapbuffer_move (&editor.current_line->gb, editor.cursor.col);
gapbuffer_insert (&wrealloc, NULL, &editor.current_line->gb, TAB_INSERT[i]); for (size_t i = 0; i < sizeof (TAB_INSERT) - 1; i++)
gapbuffer_insert (&wrealloc, NULL, &editor.current_line->gb, TAB_INSERT[i]);
editor.cursor.col += sizeof (TAB_INSERT) - 1; editor.cursor.col += sizeof (TAB_INSERT) - 1;
}
break; break;
case '\n': { case '\n': {
gapbuffer_move (&editor.current_line->gb, editor.cursor.col); if (editor.mode == EDIT_MODE_NORMAL) {
gapbuffer_move (&editor.current_line->gb, editor.cursor.col);
struct edit_line* new_line = malloc (sizeof (*new_line)); struct edit_line* new_line = malloc (sizeof (*new_line));
memset (new_line, 0, sizeof (*new_line)); memset (new_line, 0, sizeof (*new_line));
char* tail = gapbuffer_string_at (&warena_malloc, &temp_arena, &editor.current_line->gb, char* tail = gapbuffer_string_at (&warena_malloc, &temp_arena, &editor.current_line->gb,
editor.cursor.col); editor.cursor.col);
size_t tail_size = strlen (tail); size_t tail_size = strlen (tail);
size_t init_cap = tail_size > 0 ? tail_size : 32; size_t init_cap = tail_size > 0 ? tail_size : 32;
gapbuffer_init (&wmalloc, NULL, &new_line->gb, init_cap); gapbuffer_init (&wmalloc, NULL, &new_line->gb, init_cap);
if (tail_size > 0) { if (tail_size > 0) {
memcpy (new_line->gb.buffer, memcpy (new_line->gb.buffer,
editor.current_line->gb.buffer + editor.current_line->gb.gap_end, tail_size); editor.current_line->gb.buffer + editor.current_line->gb.gap_end, tail_size);
new_line->gb.gap_start = tail_size; new_line->gb.gap_start = tail_size;
}
editor.current_line->gb.gap_end = editor.current_line->gb.size;
list_insert_after (editor.lines, &editor.current_line->lines_link, &new_line->lines_link);
editor.cursor.col = 0;
editor.cursor.line++;
editor.current_line = new_line;
} }
editor.current_line->gb.gap_end = editor.current_line->gb.size;
list_insert_after (editor.lines, &editor.current_line->lines_link, &new_line->lines_link);
editor.cursor.col = 0;
editor.cursor.line++;
editor.current_line = new_line;
} break; } break;
case KB_DELETE: case KB_DELETE:
if (editor.cursor.col < gapbuffer_length (&editor.current_line->gb)) { if (editor.mode == EDIT_MODE_NORMAL) {
gapbuffer_move (&editor.current_line->gb, editor.cursor.col); if (editor.cursor.col < gapbuffer_length (&editor.current_line->gb)) {
editor.current_line->gb.gap_end++; gapbuffer_move (&editor.current_line->gb, editor.cursor.col);
editor.current_line->gb.gap_end++;
}
} }
break; break;
case KB_LEFT: case KB_LEFT:
@@ -305,14 +333,28 @@ void edit_start (const char* file_path, const char* text) {
case KB_END: case KB_END:
editor.cursor.col = gapbuffer_length (&editor.current_line->gb); editor.cursor.col = gapbuffer_length (&editor.current_line->gb);
break; break;
case KB_CTRL ('Q'): case KB_ESCAPE:
edit_run = false; editor.mode = EDIT_MODE_NORMAL;
break; break;
case KB_CTRL ('X'):
editor.mode = EDIT_MODE_COMAMND;
default: default:
if (isprint (ch)) { if (isprint (ch)) {
gapbuffer_move (&editor.current_line->gb, editor.cursor.col); if (editor.mode == EDIT_MODE_COMAMND) {
gapbuffer_insert (&wrealloc, NULL, &editor.current_line->gb, ch); switch (ch) {
editor.cursor.col++; case 'q':
edit_run = false;
editor.mode = EDIT_MODE_NORMAL;
break;
default:
editor.mode = EDIT_MODE_NORMAL;
break;
}
} else if (editor.mode == EDIT_MODE_NORMAL) {
gapbuffer_move (&editor.current_line->gb, editor.cursor.col);
gapbuffer_insert (&wrealloc, NULL, &editor.current_line->gb, ch);
editor.cursor.col++;
}
} }
break; break;
} }
@@ -333,4 +375,5 @@ void edit_start (const char* file_path, const char* text) {
} }
memset (&editor, 0, sizeof (editor)); memset (&editor, 0, sizeof (editor));
mprintf (ANSIQ_SCR_RESTORE);
} }

View File

@@ -20,6 +20,7 @@
#define KB_PAGEDN 0xe7 #define KB_PAGEDN 0xe7
#define KB_INSERT 0xe8 #define KB_INSERT 0xe8
#define KB_DELETE 0xe9 #define KB_DELETE 0xe9
#define KB_ESCAPE 0x1b
#define KB_CTRL(x) ((x) - '@') #define KB_CTRL(x) ((x) - '@')

View File

@@ -10,8 +10,8 @@
#define ANSIQ_SCR_CLR2LEND ANSIQ_ESC"[0K" // Clear to end of line #define ANSIQ_SCR_CLR2LEND ANSIQ_ESC"[0K" // Clear to end of line
#define ANSIQ_SCR_CLR2LBEG ANSIQ_ESC"[1K" // Clear to begining of line #define ANSIQ_SCR_CLR2LBEG ANSIQ_ESC"[1K" // Clear to begining of line
#define ANSIQ_SCR_CLR_LINE ANSIQ_ESC"[2K" // Clear entire line #define ANSIQ_SCR_CLR_LINE ANSIQ_ESC"[2K" // Clear entire line
#define ANSIQ_SCR_RESTORE ANSIQ_ESC"[?47l" #define ANSIQ_SCR_RESTORE ANSIQ_ESC"[?1049l"
#define ANSIQ_SCR_SAVE ANSIQ_ESC"[?47h" #define ANSIQ_SCR_SAVE ANSIQ_ESC"[?1049h"
/* clang-format on */ /* clang-format on */
#endif /* ANSIQ_SCREEN_H */ #endif /* ANSIQ_SCREEN_H */