vip

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

commit 47e4d61a6d4032ad5385e4ec2b250d03b33e3ee2
parent 232db589e330589fcae177d2a0edbe8005d67a52
Author: night0721 <[email protected]>
Date:   Wed,  3 Jul 2024 11:11:48 +0100

Search text

Diffstat:
Minclude/editor.h | 3+++
Minclude/row.h | 1+
Minclude/vip.h | 19+++++++++++++++++--
Msrc/editor.c | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/row.c | 15+++++++++++++++
Msrc/vip.c | 87++++++++++---------------------------------------------------------------------
6 files changed, 170 insertions(+), 78 deletions(-)

diff --git a/include/editor.h b/include/editor.h @@ -5,5 +5,8 @@ void insert_char(int c); void insert_new_line(); void shift_new_line(); void del_char(); +void open_editor(char *filename); +char *prompt_editor(char *prompt, void (*callback)(char *, int)); +void find_editor(); #endif diff --git a/include/row.h b/include/row.h @@ -2,6 +2,7 @@ #define ROW_H_ int row_cx_to_rx(row *row, int cx); +int row_rx_to_cx(row *row, int rx); void update_row(row *row); void insert_row(int at, char *s, size_t len); void free_row(row *row); diff --git a/include/vip.h b/include/vip.h @@ -23,11 +23,25 @@ #define GREEN_FG "\x1b[48;2;166;227;161m" #define GREEN_BG "\x1b[38;2;166;227;161m" - #define NORMAL 0 #define INSERT 1 #define VISUAL 2 +#define CTRL_KEY(k) ((k) & 0x1f) + +enum keys { + BACKSPACE = 127, + ARROW_LEFT = 1000, + ARROW_RIGHT, + ARROW_UP, + ARROW_DOWN, + DEL_KEY, + HOME_KEY, + END_KEY, + PAGE_UP, + PAGE_DOWN +}; + typedef struct row { int size; int render_size; @@ -60,10 +74,11 @@ struct abuf { void abAppend(struct abuf *ab, const char *s, int len); +int read_key(); +void refresh_screen(); void append_row(char *s, size_t len); void row_insert_char(row *row, int at, int c); void row_del_char(row *row, int at); -char *prompt_editor(char *prompt); extern editor vip; diff --git a/src/editor.c b/src/editor.c @@ -1,5 +1,12 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + #include "vip.h" +#include "bar.h" #include "row.h" +#include "term.h" extern editor vip; @@ -54,3 +61,119 @@ void del_char() vip.cy--; } } + +void open_editor(char *filename) +{ + free(vip.filename); + vip.filename = strdup(filename); + FILE *fp = fopen(filename, "r"); + if (!fp) { + die("fopen"); + } + char *line = NULL; + size_t linecap = 0; + ssize_t len; + while ((len = getline(&line, &linecap, fp)) != -1) { + /* remove new line and carriage return at end of line */ + while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) { + len--; + } + insert_row(vip.rows, line, len); + } + free(line); + fclose(fp); + /* reset dirtiness as nothing is modified yet */ + vip.dirty = 0; +} + +char *prompt_editor(char *prompt, void (*callback)(char *, int)) +{ + size_t bufsize = 128; + char *buf = malloc(bufsize); + size_t buflen = 0; + buf[0] = '\0'; + while (1) { + set_status_bar_message(prompt, buf); + refresh_screen(); + int c = read_key(); + if (c == DEL_KEY || c == CTRL_KEY('h') || c == BACKSPACE) { + if (buflen != 0) { + buf[--buflen] = '\0'; + } + } else if (c == '\x1b') { + set_status_bar_message(""); + if (callback) callback(buf, c); + free(buf); + return NULL; + } else if (c == '\r') { + if (buflen != 0) { + set_status_bar_message(""); + if (callback) callback(buf, c); + return buf; + } + } else if (!iscntrl(c) && c < 128) { + if (buflen == bufsize - 1) { + bufsize *= 2; + buf = realloc(buf, bufsize); + } + buf[buflen++] = c; + buf[buflen] = '\0'; + } + + if (callback) callback(buf, c); + } +} + +void find_callback(char *query, int key) +{ + static int last_match = -1; + static int direction = 1; + if (key == '\r' || key == '\x1b') { + last_match = -1; + direction = 1; + return; + } else if (key == CTRL_KEY('n')) { + direction = 1; + } else if (key == CTRL_KEY('p')) { + direction = -1; + } else { + last_match = -1; + direction = 1; + } + + if (last_match == -1) direction = 1; + int current = last_match; + for (int i = 0; i < vip.rows; i++) { + current += direction; + + if (current == -1) current = vip.rows - 1; + else if (current == vip.rows) current = 0; + + row *row = &vip.row[current]; + char *match = strstr(row->render, query); + if (match) { + last_match = current; + vip.cy = current; + vip.cx = row_rx_to_cx(row, match - row->render); + vip.rowoff = vip.rows; + break; + } + } +} + +void find_editor() +{ + int tmp_cx = vip.cx; + int tmp_cy = vip.cy; + int tmp_coloff = vip.coloff; + int tmp_rowoff = vip.rowoff; + char *query = prompt_editor("/%s", find_callback); + if (query) { + free(query); + } else { + vip.cx = tmp_cx; + vip.cy = tmp_cy; + vip.coloff = tmp_coloff; + vip.rowoff = tmp_rowoff; + } +} diff --git a/src/row.c b/src/row.c @@ -18,6 +18,21 @@ int row_cx_to_rx(row *row, int cx) return rx; } +int row_rx_to_cx(row *row, int rx) +{ + int cur_rx = 0; + int cx; + for (cx = 0; cx < row->size; cx++) { + if (row->chars[cx] == '\t') { + cur_rx += (TAB_SIZE - 1) - (cur_rx % TAB_SIZE); + } + cur_rx++; + if (cur_rx > rx) + return cx; + } + return cx; +} + void update_row(row *row) { int tabs = 0; diff --git a/src/vip.c b/src/vip.c @@ -15,21 +15,6 @@ #include "editor.h" #include "row.h" -#define CTRL_KEY(k) ((k) & 0x1f) - -enum editorKey { - BACKSPACE = 127, - ARROW_LEFT = 1000, - ARROW_RIGHT, - ARROW_UP, - ARROW_DOWN, - DEL_KEY, - HOME_KEY, - END_KEY, - PAGE_UP, - PAGE_DOWN -}; - editor vip; int read_key() @@ -87,34 +72,10 @@ int read_key() } } -void open_editor(char *filename) -{ - free(vip.filename); - vip.filename = strdup(filename); - FILE *fp = fopen(filename, "r"); - if (!fp) { - die("fopen"); - } - char *line = NULL; - size_t linecap = 0; - ssize_t len; - while ((len = getline(&line, &linecap, fp)) != -1) { - /* remove new line and carriage return at end of line */ - while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) { - len--; - } - insert_row(vip.rows, line, len); - } - free(line); - fclose(fp); - /* reset dirtiness as nothing is modified yet */ - vip.dirty = 0; -} - void save_file() { if (vip.filename == NULL) { - vip.filename = prompt_editor("Save as: %s (ESC to cancel)"); + vip.filename = prompt_editor("Save as: %s", NULL); if (vip.filename == NULL) { set_status_bar_message("Save aborted"); return; @@ -230,40 +191,6 @@ void refresh_screen() abFree(&ab); } -char *prompt_editor(char *prompt) -{ - size_t bufsize = 128; - char *buf = malloc(bufsize); - size_t buflen = 0; - buf[0] = '\0'; - while (1) { - set_status_bar_message(prompt, buf); - refresh_screen(); - int c = read_key(); - if (c == DEL_KEY || c == CTRL_KEY('h') || c == BACKSPACE) { - if (buflen != 0) { - buf[--buflen] = '\0'; - } - } else if (c == '\x1b') { - set_status_bar_message(""); - free(buf); - return NULL; - } else if (c == '\r') { - if (buflen != 0) { - set_status_bar_message(""); - return buf; - } - } else if (!iscntrl(c) && c < 128) { - if (buflen == bufsize - 1) { - bufsize *= 2; - buf = realloc(buf, bufsize); - } - buf[buflen++] = c; - buf[buflen] = '\0'; - } - } -} - void move_cursor(int key) { row *row = (vip.cy >= vip.rows) ? NULL : &vip.row[vip.cy]; @@ -365,7 +292,10 @@ void process_key() case ':': /* PASSTHROUGH */ if (vip.mode == NORMAL) { - char *cmd = prompt_editor(":%s"); + char *cmd = prompt_editor(":%s", NULL); + if (cmd == NULL) { + return; + } switch (cmd[0]) { case 'q': if (cmd[1] == '!') { @@ -388,6 +318,11 @@ void process_key() save_file(); } } + case '/': /* PASSTHROUGH */ + if (vip.mode == NORMAL) { + find_editor(); + break; + } case 'k': /* PASSTHROUGH */ if (vip.mode != INSERT) { @@ -457,7 +392,7 @@ int main(int argc, char **argv) open_editor(argv[1]); } - set_status_bar_message(":w - Save, :q - Quit"); + set_status_bar_message("By night0721 and gnucolas"); while (1) { refresh_screen();