Search text
This commit is contained in:
parent
232db589e3
commit
47e4d61a6d
6 changed files with 170 additions and 78 deletions
|
@ -5,5 +5,8 @@ void insert_char(int c);
|
||||||
void insert_new_line();
|
void insert_new_line();
|
||||||
void shift_new_line();
|
void shift_new_line();
|
||||||
void del_char();
|
void del_char();
|
||||||
|
void open_editor(char *filename);
|
||||||
|
char *prompt_editor(char *prompt, void (*callback)(char *, int));
|
||||||
|
void find_editor();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define ROW_H_
|
#define ROW_H_
|
||||||
|
|
||||||
int row_cx_to_rx(row *row, int cx);
|
int row_cx_to_rx(row *row, int cx);
|
||||||
|
int row_rx_to_cx(row *row, int rx);
|
||||||
void update_row(row *row);
|
void update_row(row *row);
|
||||||
void insert_row(int at, char *s, size_t len);
|
void insert_row(int at, char *s, size_t len);
|
||||||
void free_row(row *row);
|
void free_row(row *row);
|
||||||
|
|
|
@ -23,11 +23,25 @@
|
||||||
#define GREEN_FG "\x1b[48;2;166;227;161m"
|
#define GREEN_FG "\x1b[48;2;166;227;161m"
|
||||||
#define GREEN_BG "\x1b[38;2;166;227;161m"
|
#define GREEN_BG "\x1b[38;2;166;227;161m"
|
||||||
|
|
||||||
|
|
||||||
#define NORMAL 0
|
#define NORMAL 0
|
||||||
#define INSERT 1
|
#define INSERT 1
|
||||||
#define VISUAL 2
|
#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 {
|
typedef struct row {
|
||||||
int size;
|
int size;
|
||||||
int render_size;
|
int render_size;
|
||||||
|
@ -60,10 +74,11 @@ struct abuf {
|
||||||
|
|
||||||
void abAppend(struct abuf *ab, const char *s, int len);
|
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 append_row(char *s, size_t len);
|
||||||
void row_insert_char(row *row, int at, int c);
|
void row_insert_char(row *row, int at, int c);
|
||||||
void row_del_char(row *row, int at);
|
void row_del_char(row *row, int at);
|
||||||
char *prompt_editor(char *prompt);
|
|
||||||
|
|
||||||
extern editor vip;
|
extern editor vip;
|
||||||
|
|
||||||
|
|
123
src/editor.c
123
src/editor.c
|
@ -1,5 +1,12 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "vip.h"
|
#include "vip.h"
|
||||||
|
#include "bar.h"
|
||||||
#include "row.h"
|
#include "row.h"
|
||||||
|
#include "term.h"
|
||||||
|
|
||||||
extern editor vip;
|
extern editor vip;
|
||||||
|
|
||||||
|
@ -54,3 +61,119 @@ void del_char()
|
||||||
vip.cy--;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
15
src/row.c
15
src/row.c
|
@ -18,6 +18,21 @@ int row_cx_to_rx(row *row, int cx)
|
||||||
return rx;
|
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)
|
void update_row(row *row)
|
||||||
{
|
{
|
||||||
int tabs = 0;
|
int tabs = 0;
|
||||||
|
|
87
src/vip.c
87
src/vip.c
|
@ -15,21 +15,6 @@
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
#include "row.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;
|
editor vip;
|
||||||
|
|
||||||
int read_key()
|
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()
|
void save_file()
|
||||||
{
|
{
|
||||||
if (vip.filename == NULL) {
|
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) {
|
if (vip.filename == NULL) {
|
||||||
set_status_bar_message("Save aborted");
|
set_status_bar_message("Save aborted");
|
||||||
return;
|
return;
|
||||||
|
@ -230,40 +191,6 @@ void refresh_screen()
|
||||||
abFree(&ab);
|
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)
|
void move_cursor(int key)
|
||||||
{
|
{
|
||||||
row *row = (vip.cy >= vip.rows) ? NULL : &vip.row[vip.cy];
|
row *row = (vip.cy >= vip.rows) ? NULL : &vip.row[vip.cy];
|
||||||
|
@ -365,7 +292,10 @@ void process_key()
|
||||||
|
|
||||||
case ':': /* PASSTHROUGH */
|
case ':': /* PASSTHROUGH */
|
||||||
if (vip.mode == NORMAL) {
|
if (vip.mode == NORMAL) {
|
||||||
char *cmd = prompt_editor(":%s");
|
char *cmd = prompt_editor(":%s", NULL);
|
||||||
|
if (cmd == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (cmd[0]) {
|
switch (cmd[0]) {
|
||||||
case 'q':
|
case 'q':
|
||||||
if (cmd[1] == '!') {
|
if (cmd[1] == '!') {
|
||||||
|
@ -388,6 +318,11 @@ void process_key()
|
||||||
save_file();
|
save_file();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case '/': /* PASSTHROUGH */
|
||||||
|
if (vip.mode == NORMAL) {
|
||||||
|
find_editor();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 'k': /* PASSTHROUGH */
|
case 'k': /* PASSTHROUGH */
|
||||||
if (vip.mode != INSERT) {
|
if (vip.mode != INSERT) {
|
||||||
|
@ -457,7 +392,7 @@ int main(int argc, char **argv)
|
||||||
open_editor(argv[1]);
|
open_editor(argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_status_bar_message(":w - Save, :q - Quit");
|
set_status_bar_message("By night0721 and gnucolas");
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
refresh_screen();
|
refresh_screen();
|
||||||
|
|
Loading…
Reference in a new issue