tvi: yank and put - neatvi - [fork] simple vi-type editor with UTF-8 support | |
git clone git://src.adamsgaard.dk/neatvi | |
Log | |
Files | |
Refs | |
README | |
--- | |
commit 01c3c8a62f1daee16d343488699f804c72dbca91 | |
parent f80a244199b5d2735fcdd0abd4664346ba51dd32 | |
Author: Ali Gholami Rudi <[email protected]> | |
Date: Tue, 5 May 2015 12:17:59 +0430 | |
vi: yank and put | |
Diffstat: | |
M Makefile | 2 +- | |
A reg.c | 26 ++++++++++++++++++++++++++ | |
M uc.c | 28 ++++++++++++++++++++++++++++ | |
M vi.c | 134 ++++++++++++++++++++---------… | |
M vi.h | 8 ++++++++ | |
5 files changed, 148 insertions(+), 50 deletions(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
t@@ -2,7 +2,7 @@ CC = cc | |
CFLAGS = -Wall -O2 | |
LDFLAGS = | |
-OBJS = vi.o ex.o lbuf.o sbuf.o ren.o led.o uc.o term.o | |
+OBJS = vi.o ex.o lbuf.o sbuf.o ren.o reg.o led.o uc.o term.o | |
all: vi | |
%.o: %.c | |
diff --git a/reg.c b/reg.c | |
t@@ -0,0 +1,26 @@ | |
+#include <stdlib.h> | |
+#include <string.h> | |
+#include "vi.h" | |
+ | |
+static char *reg; | |
+static int lnmode; | |
+ | |
+char *reg_get(int c, int *ln) | |
+{ | |
+ *ln = lnmode; | |
+ return reg; | |
+} | |
+ | |
+void reg_put(int c, char *s, int ln) | |
+{ | |
+ char *nreg = malloc(strlen(s) + 1); | |
+ strcpy(nreg, s); | |
+ free(reg); | |
+ reg = nreg; | |
+ lnmode = ln; | |
+} | |
+ | |
+void reg_done(void) | |
+{ | |
+ free(reg); | |
+} | |
diff --git a/uc.c b/uc.c | |
t@@ -94,6 +94,34 @@ char **uc_chop(char *s, int *n) | |
return chrs; | |
} | |
+char *uc_chr(char *s, int off) | |
+{ | |
+ int i = 0; | |
+ while (s && *s) { | |
+ if (i++ == off) | |
+ return s; | |
+ s = uc_next(s); | |
+ } | |
+ return s && (off < 0 || i == off) ? s : ""; | |
+} | |
+ | |
+char *uc_sub(char *s, int beg, int end) | |
+{ | |
+ char *sbeg = uc_chr(s, beg); | |
+ char *send = uc_chr(s, end); | |
+ int len = sbeg && send && sbeg <= send ? send - sbeg : 0; | |
+ char *r = malloc(len + 1); | |
+ memcpy(r, sbeg, len); | |
+ r[len] = '\0'; | |
+ return r; | |
+} | |
+ | |
+char *uc_dup(char *s) | |
+{ | |
+ char *r = malloc(strlen(s) + 1); | |
+ return r ? strcpy(r, s) : NULL; | |
+} | |
+ | |
int uc_isspace(char *s) | |
{ | |
int c = s ? (unsigned char) *s : 0; | |
diff --git a/vi.c b/vi.c | |
t@@ -98,17 +98,14 @@ static char *lbuf_chr(struct lbuf *lb, int r, int c) | |
{ | |
static char chr[8]; | |
char *ln = lbuf_get(lb, r); | |
- int n; | |
if (ln) { | |
- char **chrs = uc_chop(ln, &n); | |
int off = ren_off(ln, c); | |
- if (off >= 0 && off < n) { | |
- memcpy(chr, chrs[off], uc_len(chrs[off])); | |
- chr[uc_len(chr)] = '\0'; | |
- free(chrs); | |
+ char *s = uc_chr(ln, off); | |
+ if (s) { | |
+ memcpy(chr, s, uc_len(s)); | |
+ chr[uc_len(s)] = '\0'; | |
return chr; | |
} | |
- free(chrs); | |
} | |
return ""; | |
} | |
t@@ -364,30 +361,6 @@ static int vi_motion(int *row, int *col, int pre1, int pr… | |
return c; | |
} | |
-static char *vi_strprefix(char *s, int off) | |
-{ | |
- struct sbuf *sb = sbuf_make(); | |
- int n; | |
- char **chrs = uc_chop(s ? s : "", &n); | |
- if (n > 0) | |
- sbuf_mem(sb, s, chrs[MIN(n - 1, off)] - s); | |
- free(chrs); | |
- return sbuf_done(sb); | |
-} | |
- | |
-static char *vi_strpostfix(char *s, int off) | |
-{ | |
- struct sbuf *sb = sbuf_make(); | |
- int n; | |
- char **chrs = uc_chop(s ? s : "", &n); | |
- if (n >= 0 && off < n) | |
- sbuf_str(sb, chrs[off]); | |
- free(chrs); | |
- if (!sbuf_len(sb)) | |
- sbuf_chr(sb, '\n'); | |
- return sbuf_done(sb); | |
-} | |
- | |
static void swap(int *a, int *b) | |
{ | |
int t = *a; | |
t@@ -395,10 +368,23 @@ static void swap(int *a, int *b) | |
*b = t; | |
} | |
-static char *sdup(char *s) /* strdup() */ | |
+static char *lbuf_region(struct lbuf *lb, int r1, int l1, int r2, int l2) | |
{ | |
- char *r = malloc(strlen(s) + 1); | |
- return r ? strcpy(r, s) : NULL; | |
+ struct sbuf *sb; | |
+ char *s1, *s2, *s3; | |
+ if (r1 == r2) | |
+ return uc_sub(lbuf_get(lb, r1), l1, l2); | |
+ sb = sbuf_make(); | |
+ s1 = uc_sub(lbuf_get(lb, r1), l1, -1); | |
+ s3 = uc_sub(lbuf_get(lb, r2), 0, l2); | |
+ s2 = lbuf_cp(lb, r1 + 1, r2); | |
+ sbuf_str(sb, s1); | |
+ sbuf_str(sb, s2); | |
+ sbuf_str(sb, s3); | |
+ free(s1); | |
+ free(s2); | |
+ free(s3); | |
+ return sbuf_done(sb); | |
} | |
static void vc_motion(int c, int pre1) | |
t@@ -429,14 +415,34 @@ static void vc_motion(int c, int pre1) | |
swap(&r1, &r2); | |
swap(&c1, &c2); | |
} | |
+ if (c == 'y') { /* adjusting cursor pos… | |
+ xrow = r1; | |
+ xcol = ln ? xcol : c1; | |
+ } | |
for (i = 0; i < 2; i++) { | |
l1 = ren_insertionoffset(lbuf_get(xb, r1), c1, 1); | |
l2 = ren_insertionoffset(lbuf_get(xb, r2), c2, !closed); | |
if (r1 == r2 && l2 < l1) /* offsets out of order */ | |
swap(&l1, &l2); | |
} | |
- pref = ln ? sdup("") : vi_strprefix(lbuf_get(xb, r1), l1); | |
- post = ln ? sdup("\n") : vi_strpostfix(lbuf_get(xb, r2), l2); | |
+ pref = ln ? uc_dup("") : uc_sub(lbuf_get(xb, r1), 0, l1); | |
+ post = ln ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), l2, -1); | |
+ if (c == 'c' || c == 'd' || c == 'y') { | |
+ char *region = lbuf_region(xb, r1, ln ? 0 : l1, r2, ln ? -1 : … | |
+ reg_put(0, region, ln); | |
+ free(region); | |
+ } | |
+ if (c == 'c') { | |
+ int row, col; | |
+ char *rep = led_input(pref, post, &row, &col); | |
+ if (rep) { | |
+ lbuf_rm(xb, r1, r2 + 1); | |
+ lbuf_put(xb, r1, rep); | |
+ xrow = r1 + row; | |
+ xcol = col; | |
+ free(rep); | |
+ } | |
+ } | |
if (c == 'd') { | |
lbuf_rm(xb, r1, r2 + 1); | |
if (!ln) { | |
t@@ -451,17 +457,6 @@ static void vc_motion(int c, int pre1) | |
if (ln) | |
lbuf_postindents(xb, &xrow, &xcol); | |
} | |
- if (c == 'c') { | |
- int row, col; | |
- char *rep = led_input(pref, post, &row, &col); | |
- if (rep) { | |
- lbuf_rm(xb, r1, r2 + 1); | |
- lbuf_put(xb, r1, rep); | |
- xrow = r1 + row; | |
- xcol = col; | |
- free(rep); | |
- } | |
- } | |
free(pref); | |
free(post); | |
} | |
t@@ -486,8 +481,8 @@ static void vc_insert(int cmd) | |
off = ln ? ren_insertionoffset(ln, xcol, 1) : 0; | |
if (cmd == 'a' || cmd == 'A') | |
off = ln ? ren_insertionoffset(ln, xcol, 0) : 0; | |
- pref = ln ? vi_strprefix(ln, off) : sdup(""); | |
- post = ln ? vi_strpostfix(ln, off) : sdup("\n"); | |
+ pref = ln ? uc_sub(ln, 0, off) : uc_dup(""); | |
+ post = ln ? uc_sub(ln, off, -1) : uc_dup("\n"); | |
rep = led_input(pref, post, &row, &col); | |
if (rep) { | |
if (cmd != 'o' && cmd != 'O') | |
t@@ -501,6 +496,40 @@ static void vc_insert(int cmd) | |
free(post); | |
} | |
+static void vc_put(int cmd, int cnt) | |
+{ | |
+ int lnmode; | |
+ char *ln; | |
+ char *buf = reg_get(0, &lnmode); | |
+ struct sbuf *sb; | |
+ int off; | |
+ int i; | |
+ if (!buf) | |
+ return; | |
+ ln = lnmode ? NULL : lbuf_get(xb, xrow); | |
+ off = ln ? ren_insertionoffset(ln, xcol, cmd == 'P') : 0; | |
+ if (cmd == 'p' && !ln) | |
+ xrow++; | |
+ sb = sbuf_make(); | |
+ if (ln) { | |
+ char *s = uc_sub(ln, 0, off); | |
+ sbuf_str(sb, s); | |
+ free(s); | |
+ } | |
+ for (i = 0; i < MAX(cnt, 1); i++) | |
+ sbuf_str(sb, buf); | |
+ if (ln) { | |
+ char *s = uc_sub(ln, off, -1); | |
+ sbuf_str(sb, s); | |
+ free(s); | |
+ } | |
+ if (ln) | |
+ lbuf_rm(xb, xrow, xrow + 1); | |
+ lbuf_put(xb, xrow, sbuf_buf(sb)); | |
+ sbuf_free(sb); | |
+ | |
+} | |
+ | |
static void vi(void) | |
{ | |
int mark; | |
t@@ -559,6 +588,7 @@ static void vi(void) | |
break; | |
case 'c': | |
case 'd': | |
+ case 'y': | |
vc_motion(c, pre1); | |
redraw = 1; | |
break; | |
t@@ -575,6 +605,11 @@ static void vi(void) | |
if ((mark = vi_read()) > 0 && isalpha(mark)) | |
lbuf_mark(xb, mark, xrow); | |
break; | |
+ case 'p': | |
+ case 'P': | |
+ vc_put(c, pre1); | |
+ redraw = 1; | |
+ break; | |
default: | |
continue; | |
} | |
t@@ -618,5 +653,6 @@ int main(int argc, char *argv[]) | |
else | |
ex(); | |
lbuf_free(xb); | |
+ reg_done(); | |
return 0; | |
} | |
diff --git a/vi.h b/vi.h | |
t@@ -48,12 +48,20 @@ int ren_last(char *s); | |
int ren_cmp(char *s, int pos1, int pos2); | |
int ren_insertionoffset(char *s, int pos, int pre); | |
+/* string registers */ | |
+char *reg_get(int c, int *lnmode); | |
+void reg_put(int c, char *s, int lnmode); | |
+void reg_done(void); | |
+ | |
/* utf-8 helper functions */ | |
int uc_len(char *s); | |
int uc_dir(char *s); | |
int uc_wid(char *s); | |
int uc_slen(char *s); | |
int uc_code(char *s); | |
+char *uc_chr(char *s, int off); | |
+char *uc_sub(char *s, int beg, int end); | |
+char *uc_dup(char *s); | |
int uc_isspace(char *s); | |
int uc_isprint(char *s); | |
int uc_isdigit(char *s); |