ledit

Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

commit 36a12616e748e39265af475dbaee5e8356cc984a
parent 5d691e9f97b979d571d38c101554d72e91cb7db5
Author: lumidify <nobody@lumidify.org>
Date:   Sun, 19 Sep 2021 19:27:06 +0200

Add basic support for commands

Diffstat:
ABUG | 9+++++++++
MMakefile | 4++--
Mbuffer.c | 2+-
Mcommands.c | 159+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Acommands.h | 1+
Mledit.c | 2++
6 files changed, 142 insertions(+), 35 deletions(-)

diff --git a/BUG b/BUG @@ -0,0 +1,9 @@ +Random bugs noted down so I remember them; you are not expected to understand this +deleting two lines in middle: leaves stray empty line without cursor; undo not right order; +#0 0x00000d017890ccef in memcpy (dst0=0xd01adb5cf00, src0=0xd01c90a610b, length=18446744073709551566) at /usr/src/lib/libc/string/memcpy.c:97 +#1 0x00000cff1763be78 in ledit_insert_text_base (buffer=0xd01adb67300, line_index=6, index=0, text=0xd01c90a610b "\001\r", len=-50) at buffer.c:322 +#2 0x00000cff1763c516 in ledit_insert_text_with_newlines_base (buffer=0xd01adb67300, line_index=4, index=0, + text=0xd01c90a6080 "اسجد\233ا\204کسجدا\233س\204کجاس\233\204دکاج\233د\204کسادجا\233سداکج\204د\233ا\n", len=89, end_line_ret=0x0, + end_char_ret=0x0) at buffer.c:391 +#3 0x00000cff17640058 in ledit_undo (buffer=0xd01adb67300) at undo.c:172 +#4 0x00000cff17639d8a in undo () at ledit.c:1774 diff --git a/Makefile b/Makefile @@ -9,8 +9,8 @@ MANPREFIX = ${PREFIX}/man BIN = ${NAME} MAN1 = ${BIN:=.1} -OBJ = ${BIN:=.o} cache.o buffer.o memory.o util.o search.o lbuf.o undo.o -HDR = cache.h buffer.h memory.h common.h util.h search.h lbuf.h undo.h +OBJ = ${BIN:=.o} cache.o buffer.o memory.o util.o search.o lbuf.o undo.o commands.o +HDR = cache.h buffer.h memory.h common.h util.h search.h lbuf.h undo.h commands.h CFLAGS_LEDIT = -g -Wall -Wextra -D_POSIX_C_SOURCE=200809L `pkg-config --cflags x11 xkbfile pangoxft xext` LDFLAGS_LEDIT = ${LDFLAGS} `pkg-config --libs x11 xkbfile pangoxft xext` -lm diff --git a/buffer.c b/buffer.c @@ -1035,7 +1035,7 @@ ledit_delete_range_base( rgl1 = l1; rgb1 = 0; rgl2 = l2 + 1; - rgb2 = nextline->len; + rgb2 = 0; } if (text_ret) { ledit_copy_text_to_lbuf( diff --git a/commands.c b/commands.c @@ -1,12 +1,52 @@ /* FIXME: Parse commands properly and allow combinations of commands */ +#include <ctype.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <pango/pangoxft.h> +#include <X11/extensions/Xdbe.h> + +#include "memory.h" +#include "common.h" +#include "lbuf.h" +#include "buffer.h" + +static int +handle_write(ledit_buffer *buffer, char *cmd, int l1, int l2) { + (void)buffer; + (void)cmd; + (void)l1; + (void)l2; + printf("write\n"); + return 0; +} + +static int +handle_quit(ledit_buffer *buffer, char *cmd, int l1, int l2) { + (void)buffer; + (void)cmd; + (void)l1; + (void)l2; + printf("quit\n"); + return 0; +} static int handle_write_quit(ledit_buffer *buffer, char *cmd, int l1, int l2) { + (void)buffer; + (void)cmd; + (void)l1; + (void)l2; + printf("write quit\n"); return 0; } static int handle_substitute(ledit_buffer *buffer, char *cmd, int l1, int l2) { + (void)buffer; + (void)cmd; + (void)l1; + (void)l2; + printf("substitute\n"); return 0; } @@ -20,48 +60,103 @@ static const struct { enum cmd_type type; int (*handler)(ledit_buffer *buffer, char *cmd, int l1, int l2); } cmds[] = { - {"w", CMD_NORMAL, &handle_write_quit}, - {"q", CMD_NORMAL, &handle_write_quit}, + {"wq", CMD_OPTIONAL_RANGE, &handle_write_quit}, + {"w", CMD_OPTIONAL_RANGE, &handle_write}, + {"q", CMD_NORMAL, &handle_quit}, {"s", CMD_OPTIONAL_RANGE, &handle_substitute} }; #define LENGTH(X) (sizeof(X) / sizeof(X[0])) +/* +. current line - FIXME: implement +$ last line +% all lines +*/ + +/* FIXME: ACTUALLY USE LEN!!! */ +static int +parse_range(ledit_buffer *buffer, char *cmd, int len, char **cmd_ret, int *line1_ret, int *line2_ret) { + (void)len; + enum { + START_LINENO = 1, + START_RANGE = 2, + IN_RANGE = 4, + IN_LINENO = 8 + } s = START_LINENO | START_RANGE; + int l1 = -1, l2 = -1; + char *c = cmd; + for (; *c != '\0'; c++) { + if (isdigit(*c)) { + /* FIXME: integer overflow */ + if (s & IN_LINENO) { + if (l2 != -1) + l2 = l2 * 10 + (*c - '0'); + else + l1 = l1 * 10 + (*c - '0'); + } else if ((s & START_LINENO) && (s & START_RANGE)) { + l1 = *c - '0'; + s &= ~START_RANGE; + s &= ~START_LINENO; + s |= IN_RANGE | IN_LINENO; + } else if ((s & START_LINENO)) { + l2 = *c - '0'; + s &= ~START_LINENO; + s |= IN_LINENO; + } + } else if (*c == ',' && !(s & START_RANGE)) { + if (l1 != -1 && l2 != -1) { + return 1; + } else { + s |= START_LINENO; + s &= ~IN_LINENO; + } + } else if (*c == '%') { + if (s & START_RANGE) { + l1 = 1; + l2 = buffer->lines_num; + break; + } else { + return 1; + } + } else if (*c == '$') { + if (s & START_LINENO) { + if (l1 == -1) + l1 = buffer->lines_num; + else + l2 = buffer->lines_num; + s &= ~START_LINENO; + s &= ~IN_LINENO; + } else { + return 1; + } + } else { + break; + } + } + if ((l1 == -1 || l2 == -1) && !(s & START_RANGE)) + return 1; + *cmd_ret = c; + *line1_ret = l1; + *line2_ret = l2; + return 0; +} + int ledit_handle_cmd(ledit_buffer *buffer, char *cmd, int len) { if (len < 0) len = strlen(cmd); if (len < 1) - return; - char *cur_pos = cmd; - int l1 = buffer->cur_line; - int l2 = buffer->cur_line; - int range_given = 0; - switch (cur_pos[0]) { - case '%': - l1 = 0; - l2 = buffer->lines_num - 1; - range_given = 1; - cur_pos++; - break; - case '&' - l1 = buffer->sel.line1; - l2 = buffer->sel.line2; - if (l1 < 0 || l2 < 0) - return 1; - if (l1 < l2) { - int tmp = l1; - l1 = l2; - l2 = tmp; - } - range_given = 1; - cur_pos++; - break - } - for (int i = 0; i < LENGTH(cmds); i++) { - if (!strncmp(cmds[i].cmd, cur_pos, strlen(cmds[i].cmd)) && - (!range_given || cmds[i].type == CMD_NORMAL)) { - return cmds[i].handler(buffer, cur_pos, l1, l2); + return 1; + char *c; + int l1, l2; + if (parse_range(buffer, cmd, len, &c, &l1, &l2)) + return 1; + int range_given = l1 != -1 && l2 != -1; + for (size_t i = 0; i < LENGTH(cmds); i++) { + if (!strncmp(cmds[i].cmd, c, strlen(cmds[i].cmd)) && + (!range_given || cmds[i].type == CMD_OPTIONAL_RANGE)) { + return cmds[i].handler(buffer, c, l1, l2); } } return 1; diff --git a/commands.h b/commands.h @@ -0,0 +1 @@ +int ledit_handle_cmd(ledit_buffer *buffer, char *cmd, int len); diff --git a/ledit.c b/ledit.c @@ -1755,6 +1755,8 @@ end_lineedit(void) { else ledit_set_search_backward(bottom_bar.line_text + 1); search_next(); + } else if (old_mode == COMMANDEDIT) { + ledit_handle_cmd(buffer, bottom_bar.line_text + 1, -1); } }