tSet editor mode, improve cursor navigation - ve - a minimal text editor (work … | |
git clone git://src.adamsgaard.dk/ve | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 812ddc49f3f4312a59bf50452a2b5384160dd415 | |
parent b8e623a52f0e936fd1a85796f6ab7af8d030fac7 | |
Author: Anders Damsgaard <[email protected]> | |
Date: Tue, 6 Aug 2019 11:11:16 +0200 | |
Set editor mode, improve cursor navigation | |
Diffstat: | |
M byote.h | 11 +++++++++++ | |
M input.c | 65 +++++++++++++++++++++++++++--… | |
M output.c | 42 +++++++++++++++++++++--------… | |
M terminal.c | 7 +++++-- | |
M terminal.h | 10 ---------- | |
5 files changed, 102 insertions(+), 33 deletions(-) | |
--- | |
diff --git a/byote.h b/byote.h | |
t@@ -1,7 +1,18 @@ | |
#ifndef BYOTE_H_ | |
#define BYOTE_H_ | |
+#include <termios.h> | |
+ | |
#define PROGNAME "byote" | |
#define VERSION "0.0.1" | |
+struct editor_config { | |
+ int cursor_x, cursor_y; | |
+ int screen_rows, screen_cols; | |
+ struct termios orig_termios; | |
+ int status_height; | |
+ int mode; /* 0: normal, 1: insert, 2: visual */ | |
+}; | |
+ | |
+extern struct editor_config E; | |
#endif | |
diff --git a/input.c b/input.c | |
t@@ -1,18 +1,69 @@ | |
#include <unistd.h> | |
#include <stdlib.h> | |
+#include "byote.h" | |
#include "terminal.h" | |
#define CTRL_KEY(k) ((k) & 0x1f) | |
void | |
-editor_process_keypress() | |
+editor_move_cursor(char key) | |
{ | |
- char c = editor_read_key(); | |
- switch (c) { | |
- case CTRL_KEY('q'): | |
- write(STDOUT_FILENO, "\x1b[2J", 4); | |
- write(STDOUT_FILENO, "\x1b[H", 3); | |
- exit(0); | |
+ switch(key) { | |
+ case 'h': | |
+ if (E.cursor_x > 0) | |
+ E.cursor_x--; | |
+ break; | |
+ case 'j': | |
+ if (E.cursor_y < E.screen_rows - 1 - E.status_height) | |
+ E.cursor_y++; | |
+ break; | |
+ case 'k': | |
+ if (E.cursor_y > 0) | |
+ E.cursor_y--; | |
+ break; | |
+ case 'l': | |
+ if (E.cursor_x < E.screen_cols - 1) | |
+ E.cursor_x++; | |
break; | |
} | |
} | |
+ | |
+void | |
+editor_process_keypress() | |
+{ | |
+ char c; | |
+ int i; | |
+ | |
+ c = editor_read_key(); | |
+ | |
+ if (E.mode == 0) { /* normal mode */ | |
+ switch (c) { | |
+ case CTRL_KEY('q'): | |
+ write(STDOUT_FILENO, "\x1b[2J", 4); | |
+ write(STDOUT_FILENO, "\x1b[H", 3); | |
+ exit(0); | |
+ break; | |
+ case 'h': | |
+ case 'j': | |
+ case 'k': | |
+ case 'l': | |
+ editor_move_cursor(c); | |
+ break; | |
+ | |
+ case CTRL_KEY('d'): | |
+ i = E.screen_rows/2; | |
+ while (i--) | |
+ editor_move_cursor('j'); | |
+ break; | |
+ case CTRL_KEY('u'): | |
+ i = E.screen_rows/2; | |
+ while (i--) | |
+ editor_move_cursor('k'); | |
+ break; | |
+ | |
+ case '0': | |
+ E.cursor_x = 0; | |
+ break; | |
+ } | |
+ } | |
+} | |
diff --git a/output.c b/output.c | |
t@@ -31,24 +31,35 @@ ab_free(struct abuf *ab) { | |
void | |
draw_status(struct abuf *ab) | |
{ | |
- char left_status[80], right_status[80]; | |
+ E.status_height = 1; | |
+ char left_status[512], right_status[512]; | |
int left_status_len, right_status_len, padding; | |
- left_status_len = snprintf(left_status, sizeof(left_status), | |
- "%s editor -- version %s", | |
- PROGNAME, VERSION); | |
+ | |
+ left_status_len = 0; | |
+ switch (E.mode) { | |
+ case 1: | |
+ left_status_len = snprintf(left_status, sizeof(left_st… | |
+ "INSERT"); | |
+ break; | |
+ case 2: | |
+ left_status_len = snprintf(left_status, sizeof(left_st… | |
+ "VISUAL"); | |
+ break; | |
+ } | |
+ | |
right_status_len = snprintf(right_status, sizeof(right_status), | |
"%s editor -- version %s", | |
PROGNAME, VERSION); | |
- if (left_status_len > E.screencols) | |
- left_status_len = E.screencols; | |
+ if (left_status_len > E.screen_cols) | |
+ left_status_len = E.screen_cols; | |
- padding = E.screencols - left_status_len - right_status_len; | |
+ padding = E.screen_cols - left_status_len - right_status_len; | |
if (padding < 0) { | |
- if (left_status_len < E.screencols) | |
+ if (left_status_len < E.screen_cols) | |
ab_append(ab, left_status, left_status_len); | |
else | |
- ab_append(ab, left_status, E.screencols); | |
+ ab_append(ab, left_status, E.screen_cols); | |
} else { | |
ab_append(ab, left_status, left_status_len); | |
while (padding--) | |
t@@ -63,21 +74,21 @@ void | |
editor_draw_rows(struct abuf *ab) | |
{ | |
int y; | |
- for (y = -1; y < E.screenrows; ++y) { | |
+ for (y = -1; y < E.screen_rows; ++y) { | |
- if (y == E.screenrows-1) | |
+ if (y == E.screen_rows-1) | |
draw_status(ab); | |
else | |
ab_append(ab, "~", 1); | |
ab_append(ab, "\x1b[K", 3); /* erase to end of line */ | |
- if (y < E.screenrows - 1) | |
+ if (y < E.screen_rows - 1) | |
ab_append(ab, "\r\n", 2); | |
} | |
} | |
/* fill output append buffer and write to terminal. | |
- * move cursor to top left before and after repaint. | |
+ * move cursor to left before repaint, and to cursor position after. | |
* hide the cursor when repainting. | |
* VT100 escape sequences: | |
* - http://vt100.net/docs/vt100-ug/chapter3.html | |
t@@ -91,7 +102,10 @@ editor_refresh_screen() | |
editor_draw_rows(&ab); | |
- ab_append(&ab, "\x1b[H", 3); /* cursor to home */ | |
+ char buf[32]; | |
+ snprintf(buf, sizeof(buf), "\x1b[%d;%dH", E.cursor_y+1, E.cursor_x+1); | |
+ ab_append(&ab, buf, strlen(buf)); | |
+ | |
ab_append(&ab, "\x1b[?25h", 6); /* show cursor */ | |
write(STDOUT_FILENO, ab.b, ab.len); | |
diff --git a/terminal.c b/terminal.c | |
t@@ -5,7 +5,7 @@ | |
#include <termios.h> | |
#include <unistd.h> | |
#include <sys/ioctl.h> | |
-#include "terminal.h" | |
+#include "byote.h" | |
struct editor_config E; | |
t@@ -108,6 +108,9 @@ get_window_size(int *rows, int *cols) | |
void | |
init_editor() { | |
- if (get_window_size(&E.screenrows, &E.screencols) == -1) | |
+ E.cursor_x = 0; | |
+ E.cursor_y = 0; | |
+ E.mode = 0; | |
+ if (get_window_size(&E.screen_rows, &E.screen_cols) == -1) | |
die("get_window_size"); | |
} | |
diff --git a/terminal.h b/terminal.h | |
t@@ -1,16 +1,6 @@ | |
#ifndef TERMINAL_H_ | |
#define TERMINAL_H_ | |
-#include <termios.h> | |
- | |
-struct editor_config { | |
- int screenrows; | |
- int screencols; | |
- struct termios orig_termios; | |
-}; | |
- | |
-extern struct editor_config E; | |
- | |
void die(const char *s); | |
void disable_raw_mode(); | |
void enable_raw_mode(); |