vip

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

commit 5df8a3fb5f92ff75e648abafa3e8a1e82f288576
parent e603eaa74cdd6e95fd5f6fa07ecc0d484fa6fdf0
Author: night0721 <[email protected]>
Date:   Tue,  2 Jul 2024 22:56:09 +0100

Add save file, quit confirm, make bar look better

Diffstat:
Minclude/vip.h | 14++++++++++++++
Msrc/bar.c | 37+++++++++++++++++++++++++------------
Msrc/vip.c | 59++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 97 insertions(+), 13 deletions(-)

diff --git a/include/vip.h b/include/vip.h @@ -7,6 +7,19 @@ /* CONFIG */ #define TAB_SIZE 4 +/* number of times of warning before quitting when there is modified text */ +#define QUIT_CONFIRM 2 + +/* 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 WHITE_FG "\x1b[48;2;255;255;255m" +#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 VERSION "0.0.1" typedef struct row { @@ -24,6 +37,7 @@ typedef struct editor { int screenrows, screencols; int rows; row *row; + int dirty; char *filename; char statusmsg[80]; time_t statusmsg_time; diff --git a/src/bar.c b/src/bar.c @@ -11,29 +11,42 @@ void draw_status_bar(struct abuf *ab) { abAppend(ab, "\x1b[7m", 4); abAppend(ab, "\x1b[1m", 4); - abAppend(ab, "\x1b[38;2;137;180;250m", 19); + abAppend(ab, BLUE_BG, 19); char mode[9] = " NORMAL "; int mode_len = 8; abAppend(ab, mode, 8); + abAppend(ab, "\x1b[22m", 5); - char file[80], lines[80]; - int file_len = snprintf(file, sizeof(file), " %.20s ", - vip.filename ? vip.filename : "[No Name]"); - int lines_len = snprintf(lines, sizeof(lines), "%dL | %d:%d", vip.rows, - vip.cy + 1, vip.rx + 1); + char git_branch[80], git_diff[80], file[80], lines[80], coord[80]; + int gitb_len = snprintf(git_branch, sizeof(git_branch), " %s ", "master"); + 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 coord_len = snprintf(coord, sizeof(coord), " %d:%d ", vip.cy + 1, vip.rx + 1); - abAppend(ab, "\x1b[38;2;49;50;68m", 16); - abAppend(ab, "\x1b[22m", 5); - abAppend(ab, "\x1b[48;2;137;180;250m", 19); + abAppend(ab, SURFACE_1_BG, 16); /* background */ + abAppend(ab, BLUE_FG, 19); /* text */ + abAppend(ab, git_branch, gitb_len); + abAppend(ab, "|", 1); + abAppend(ab, GREEN_FG, 19); + abAppend(ab, git_diff, gitd_len); + abAppend(ab, BLACK_BG, 13); + abAppend(ab, WHITE_FG, 19); abAppend(ab, file, file_len); - abAppend(ab, "\x1b[38;2;0;0;0m", 13); while (file_len < vip.screencols) { - if (vip.screencols - mode_len - file_len == lines_len) { - abAppend(ab, "\x1b[48;2;255;255;255m", 19); + 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); abAppend(ab, lines, lines_len); + abAppend(ab, BLUE_BG, 19); + abAppend(ab, BLACK_FG, 13); + abAppend(ab, "\x1b[1m", 4); + abAppend(ab, coord, coord_len); + abAppend(ab, "\x1b[22m", 5); break; } else { abAppend(ab, " ", 1); diff --git a/src/vip.c b/src/vip.c @@ -3,6 +3,7 @@ #include <string.h> #include <ctype.h> #include <errno.h> +#include <fcntl.h> #include <termios.h> #include <unistd.h> #include <sys/ioctl.h> @@ -139,6 +140,7 @@ void append_row(char *s, size_t len) update_row(&vip.row[at]); vip.rows++; + vip.dirty++; } void row_insert_char(row *row, int at, int c) @@ -151,6 +153,25 @@ void row_insert_char(row *row, int at, int c) row->size++; row->chars[at] = c; update_row(row); + vip.dirty++; +} + +char *rows_to_str(int *buflen) +{ + int total_len = 0; + for (int j = 0; j < vip.rows; j++) { + total_len += vip.row[j].size + 1; + } + *buflen = total_len; + char *buf = malloc(total_len); + char *p = buf; + for (int j = 0; j < vip.rows; j++) { + memcpy(p, vip.row[j].chars, vip.row[j].size); + p += vip.row[j].size; + *p = '\n'; + p++; + } + return buf; } void open_editor(char *filename) @@ -173,6 +194,30 @@ void open_editor(char *filename) } free(line); fclose(fp); + /* reset dirtiness as nothing is modified yet */ + vip.dirty = 0; +} + +void save_file() +{ + if (vip.filename == NULL) return; + int len; + char *buf = rows_to_str(&len); + int fd = open(vip.filename, O_RDWR | O_CREAT, 0644); + if (fd != -1) { + if (ftruncate(fd, len) != -1) { + if (write(fd, buf, len) == len) { + close(fd); + free(buf); + vip.dirty = 0; + set_status_bar_message("\"%s\" %dL, %dB written", vip.filename, vip.rows, len); + return; + } + } + close(fd); + } + free(buf); + set_status_bar_message("Error saving: %s", strerror(errno)); } void abAppend(struct abuf *ab, const char *s, int len) @@ -300,6 +345,7 @@ void move_cursor(int key) void process_key() { + static int quit_times = QUIT_CONFIRM int c = read_key(); switch (c) { case '\r': @@ -307,11 +353,20 @@ void process_key() 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; @@ -358,6 +413,7 @@ void process_key() insert_char(c); break; } + quit_times = QUIT_CONFIRM; } void init_editor() @@ -369,6 +425,7 @@ void init_editor() vip.coloff = 0; vip.rows = 0; vip.row = NULL; + vip.dirty = 0; vip.filename = NULL; vip.statusmsg[0] = '\0'; vip.statusmsg_time = 0; @@ -387,7 +444,7 @@ int main(int argc, char **argv) open_editor(argv[1]); } - set_status_bar_message("Ctrl-Q = Quit"); + set_status_bar_message("Ctrl-S: Save, Ctrl-Q:Quit"); while (1) { refresh_screen();