vip

VI Plus
git clone https://codeberg.org/night0721/vip
Log | Files | Refs | README | LICENSE

commit 232db589e330589fcae177d2a0edbe8005d67a52
parent 5549a3d93ec28ecebf0b904b00bb5d7acb4e2d98
Author: night0721 <[email protected]>
Date:   Wed,  3 Jul 2024 09:58:51 +0100

Implement vim keystrokes, vim modes and bar's lines

Diffstat:
Minclude/editor.h | 1+
Minclude/vip.h | 5+++--
Msrc/bar.c | 42++++++++++++++++++++++++++++++++++--------
Msrc/editor.c | 10++++++++++
Msrc/vip.c | 108++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
5 files changed, 128 insertions(+), 38 deletions(-)

diff --git a/include/editor.h b/include/editor.h @@ -3,6 +3,7 @@ void insert_char(int c); void insert_new_line(); +void shift_new_line(); void del_char(); #endif diff --git a/include/vip.h b/include/vip.h @@ -10,17 +10,18 @@ #define VERSION "0.0.1" /* number of times of warning before quitting when there is modified text */ -#define QUIT_CONFIRM 2 +#define QUIT_CONFIRM 1 /* THEME */ /* 38 and 48 is reversed as bar's color is reversed */ #define SURFACE_1_BG "\x1b[38;2;49;50;68m" -#define BLACK_BG "\x1b[38;2;0;0;0m" #define BLACK_FG "\x1b[48;2;0;0;0m" +#define BLACK_BG "\x1b[38;2;0;0;0m" #define WHITE_FG "\x1b[48;2;205;214;244m" #define BLUE_FG "\x1b[48;2;137;180;250m" #define BLUE_BG "\x1b[38;2;137;180;250m" #define GREEN_FG "\x1b[48;2;166;227;161m" +#define GREEN_BG "\x1b[38;2;166;227;161m" #define NORMAL 0 diff --git a/src/bar.c b/src/bar.c @@ -11,11 +11,20 @@ void draw_status_bar(struct abuf *ab) { abAppend(ab, "\x1b[7m", 4); abAppend(ab, "\x1b[1m", 4); - abAppend(ab, BLUE_BG, 19); - char mode[9] = " NORMAL "; - int mode_len = 8; - abAppend(ab, mode, 8); + int mode_len; + if (vip.mode == NORMAL) { + abAppend(ab, BLUE_BG, 19); + char mode[9] = " NORMAL "; + abAppend(ab, mode, 8); + mode_len = 8; + } else { + abAppend(ab, GREEN_BG, 19); + char mode[9] = " INSERT "; + abAppend(ab, mode, 8); + mode_len = 8; + } + abAppend(ab, "\x1b[22m", 5); char git_branch[80], git_diff[80], file[80], lines[80], coord[80]; @@ -23,11 +32,20 @@ void draw_status_bar(struct abuf *ab) int gitd_len = snprintf(git_diff, sizeof(git_diff), " %s ", "+1"); int file_len = snprintf(file, sizeof(file), " %.20s %s", vip.filename ? vip.filename : "[No Name]", vip.dirty ? "[+]" : ""); - int lines_len = snprintf(lines, sizeof(lines), " %dL ", vip.rows); + int lines_len; + if (vip.rows == 0 || vip.rows == vip.cy + 1) { + lines_len = snprintf(lines, sizeof(lines), " %s ", vip.rows == 0 ? "Top" : "Bot"); + } else { + lines_len = snprintf(lines, sizeof(lines), " %d%% ", ((vip.cy + 1) * 100 / vip.rows)); + } int coord_len = snprintf(coord, sizeof(coord), " %d:%d ", vip.cy + 1, vip.rx + 1); abAppend(ab, SURFACE_1_BG, 16); /* background */ - abAppend(ab, BLUE_FG, 19); /* text */ + if (vip.mode == NORMAL) { + abAppend(ab, BLUE_FG, 19); /* text */ + } else { + abAppend(ab, GREEN_FG, 19); + } abAppend(ab, git_branch, gitb_len); abAppend(ab, "|", 1); abAppend(ab, GREEN_FG, 19); @@ -40,9 +58,17 @@ void draw_status_bar(struct abuf *ab) while (file_len < vip.screencols) { if (vip.screencols - mode_len - file_len - gitb_len - gitd_len - 1 == lines_len + coord_len) { abAppend(ab, SURFACE_1_BG, 16); - abAppend(ab, BLUE_FG, 19); + if (vip.mode == NORMAL) { + abAppend(ab, BLUE_FG, 19); + } else { + abAppend(ab, GREEN_FG, 19); + } abAppend(ab, lines, lines_len); - abAppend(ab, BLUE_BG, 19); + if (vip.mode == NORMAL) { + abAppend(ab, BLUE_BG, 19); + } else { + abAppend(ab, GREEN_BG, 19); + } abAppend(ab, BLACK_FG, 13); abAppend(ab, "\x1b[1m", 4); abAppend(ab, coord, coord_len); diff --git a/src/editor.c b/src/editor.c @@ -28,6 +28,16 @@ void insert_new_line() vip.cx = 0; } +/* + * 'o' in vim + */ +void shift_new_line() +{ + insert_row(vip.cy + 1, "", 0); + vip.cy++; + vip.cx = 0; +} + void del_char() { if (vip.cy == vip.rows) return; diff --git a/src/vip.c b/src/vip.c @@ -41,10 +41,6 @@ int read_key() die("read"); } } - if (c == 'k') return ARROW_UP; - if (c == 'j') return ARROW_DOWN; - if (c == 'l') return ARROW_RIGHT; - if (c == 'h') return ARROW_LEFT; if (c == '\x1b') { char seq[3]; @@ -302,7 +298,6 @@ void move_cursor(int key) void process_key() { - static int quit_times = QUIT_CONFIRM; int c = read_key(); switch (c) { @@ -310,21 +305,6 @@ void process_key() insert_new_line(); break; - case CTRL_KEY('q'): - if (vip.dirty && quit_times > 0) { - set_status_bar_message("No write since last change for buffer \"%s\"", vip.filename); - quit_times--; - return; - } - write(STDOUT_FILENO, "\x1b[2J", 4); - write(STDOUT_FILENO, "\x1b[H", 3); - exit(0); - break; - - case CTRL_KEY('s'): - save_file(); - break; - case HOME_KEY: vip.cx = 0; break; @@ -337,10 +317,12 @@ void process_key() case BACKSPACE: case CTRL_KEY('h'): - case DEL_KEY: - if (c == DEL_KEY) - move_cursor(ARROW_RIGHT); - del_char(); + case DEL_KEY: /* PASSTHROUGH */ + if (vip.mode == INSERT) { + if (c == DEL_KEY) + move_cursor(ARROW_RIGHT); + del_char(); + } break; case PAGE_UP: @@ -362,18 +344,88 @@ void process_key() case ARROW_DOWN: case ARROW_LEFT: case ARROW_RIGHT: - move_cursor(c); + if (vip.mode == INSERT) { + move_cursor(c); + } break; case CTRL_KEY('l'): case '\x1b': + if (vip.mode == INSERT) { + vip.mode = NORMAL; + move_cursor(ARROW_LEFT); + } break; + case 'i': + if (vip.mode == NORMAL) { + vip.mode = INSERT; + } + break; + + case ':': /* PASSTHROUGH */ + if (vip.mode == NORMAL) { + char *cmd = prompt_editor(":%s"); + switch (cmd[0]) { + case 'q': + if (cmd[1] == '!') { + write(STDOUT_FILENO, "\x1b[2J", 4); + write(STDOUT_FILENO, "\x1b[H", 3); + exit(0); + break; + } else { + if (vip.dirty) { + set_status_bar_message("No write since last change for buffer \"%s\"", vip.filename); + return; + } + write(STDOUT_FILENO, "\x1b[2J", 4); + write(STDOUT_FILENO, "\x1b[H", 3); + exit(0); + break; + + } + case 'w': + save_file(); + } + } + + case 'k': /* PASSTHROUGH */ + if (vip.mode != INSERT) { + move_cursor(ARROW_UP); + break; + } + + case 'j': /* PASSTHROUGH */ + if (vip.mode != INSERT) { + move_cursor(ARROW_DOWN); + break; + } + + case 'l': /* PASSTHROUGH */ + if (vip.mode != INSERT) { + move_cursor(ARROW_RIGHT); + break; + } + + case 'h': /* PASSTHROUGH */ + if (vip.mode != INSERT) { + move_cursor(ARROW_LEFT); + break; + } + + case 'o': /* PASSTHROUGH */ + if (vip.mode == NORMAL) { + shift_new_line(); + vip.mode = INSERT; + break; + } + default: - insert_char(c); + if (vip.mode == INSERT) { + insert_char(c); + } break; } - quit_times = QUIT_CONFIRM; } void init_editor() @@ -405,7 +457,7 @@ int main(int argc, char **argv) open_editor(argv[1]); } - set_status_bar_message("Ctrl-S: Save, Ctrl-Q:Quit"); + set_status_bar_message(":w - Save, :q - Quit"); while (1) { refresh_screen();