Introduction
Introduction Statistics Contact Development Disclaimer Help
Introduce modes - lchat - A line oriented chat front end for ii.
git clone git://git.suckless.org/lchat
Log
Files
Refs
README
---
commit a2e85fdc57c1322c16d120d1865acc8f13f4c8bd
parent 19b4d99293ad470c98406b94935565750339b716
Author: Tom Schwindl <[email protected]>
Date: Thu, 29 Dec 2022 13:17:48 +0100
Introduce modes
A mode determines how keyborad input is interpreted and which keybindings
are available. Currently, there is a default- and an emacs-mode from which
the user can choose.
Diffstat:
M Makefile | 7 +++++--
M lchat.c | 9 ++++++---
M slackline.c | 112 +++++++++++++++++++++--------…
A slackline_emacs.c | 53 ++++++++++++++++++++++++++++++
4 files changed, 139 insertions(+), 42 deletions(-)
---
diff --git a/Makefile b/Makefile
@@ -22,8 +22,8 @@ dist:
tar -czf lchat-$(VERSION).tar.gz lchat-$(VERSION)
rm -fr lchat-$(VERSION)
-lchat: lchat.o slackline.o util.o
- $(CC) -o $@ lchat.o slackline.o util.o $(LIBS)
+lchat: lchat.o slackline.o util.o slackline_emacs.o
+ $(CC) -o $@ lchat.o slackline.o slackline_emacs.o util.o $(LIBS)
lchat.o: lchat.c
$(CC) -c $(CFLAGS) -D_BSD_SOURCE -D_XOPEN_SOURCE -D_GNU_SOURCE \
@@ -42,5 +42,8 @@ sl_test: sl_test.o slackline.o slackline.h
slackline.o: slackline.c slackline.h
$(CC) -c $(CFLAGS) -o $@ slackline.c
+slackline_emacs.o: slackline_emacs.c slackline.h
+ $(CC) -c $(CFLAGS) -o $@ slackline_emacs.c
+
util.o: util.c util.h
$(CC) -c $(CFLAGS) -D_BSD_SOURCE -o $@ util.c
diff --git a/lchat.c b/lchat.c
@@ -23,6 +23,7 @@
#include <limits.h>
#include <poll.h>
#include <signal.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -183,7 +184,7 @@ main(int argc, char *argv[])
char *in_file = NULL;
char *out_file = NULL;
- while ((ch = getopt(argc, argv, "an:i:eo:p:t:uh")) != -1) {
+ while ((ch = getopt(argc, argv, "an:i:eo:p:t:uhm:")) != -1) {
switch (ch) {
case 'a':
bell_flag = false;
@@ -217,6 +218,10 @@ main(int argc, char *argv[])
case 'u':
ucspi = true;
break;
+ case 'm':
+ if (strcmp(optarg, "emacs") == 0)
+ sl_mode(sl, SL_EMACS);
+ break;
case 'h':
default:
usage();
@@ -342,8 +347,6 @@ main(int argc, char *argv[])
return EXIT_SUCCESS;
switch (c) {
- case 4: /* eot */
- return EXIT_SUCCESS;
case 13: /* return */
if (sl->rlen == 0 && empty_line == false)
goto out;
diff --git a/slackline.c b/slackline.c
@@ -22,13 +22,14 @@
#include <grapheme.h>
+#include "slackline_internals.h"
#include "slackline.h"
-
-enum direction {LEFT, RIGHT, HOME, END};
+#include "util.h"
struct slackline *
sl_init(void)
{
+ char *mode = getenv("EDITOR");
struct slackline *sl = malloc(sizeof *sl);
if (sl == NULL)
@@ -45,6 +46,14 @@ sl_init(void)
sl_reset(sl);
+ sl->mode = SL_DEFAULT;
+ if (mode != NULL) {
+ if (strcmp(mode, "emacs") == 0)
+ sl->mode = SL_EMACS;
+ else if (strcmp(mode, "vi") == 0)
+ sl->mode = SL_VI;
+ }
+
return sl;
}
@@ -71,7 +80,13 @@ sl_reset(struct slackline *sl)
sl->ubuf_len = 0;
}
-static size_t
+void
+sl_mode(struct slackline *sl, enum mode mode)
+{
+ sl->mode = mode;
+}
+
+size_t
sl_postobyte(struct slackline *sl, size_t pos)
{
char *ptr = &sl->buf[0];
@@ -84,13 +99,13 @@ sl_postobyte(struct slackline *sl, size_t pos)
return byte;
}
-static char *
+char *
sl_postoptr(struct slackline *sl, size_t pos)
{
return &sl->buf[sl_postobyte(sl, pos)];
}
-static void
+void
sl_backspace(struct slackline *sl)
{
char *ncur;
@@ -114,7 +129,7 @@ sl_backspace(struct slackline *sl)
sl->ptr = ncur;
}
-static void
+void
sl_move(struct slackline *sl, enum direction dir)
{
switch (dir) {
@@ -139,21 +154,41 @@ sl_move(struct slackline *sl, enum direction dir)
sl->ptr = sl->buf + sl->bcur;
}
-int
-sl_keystroke(struct slackline *sl, int key)
+static void
+sl_default(struct slackline *sl, int key)
{
- uint_least32_t cp;
-
- if (sl == NULL || sl->rlen < sl->rcur)
- return -1;
+ switch (key) {
+ case 27: /* Escape */
+ sl->esc = ESC;
+ break;
+ case 21:
+ sl_reset(sl);
+ break;
+ case 23: /* ctrl+w -- erase previous word */
+ while (sl->rcur != 0 && isspace((unsigned char) *(sl->ptr-1)))
+ sl_backspace(sl);
+ while (sl->rcur != 0 && !isspace((unsigned char) *(sl->ptr-1)))
+ sl_backspace(sl);
+ break;
+ case 127: /* backspace */
+ case 8: /* backspace */
+ sl_backspace(sl);
+ break;
+ default:
+ break;
+ }
+}
+static int
+sl_esc(struct slackline *sl, int key)
+{
/* handle escape sequences */
switch (sl->esc) {
case ESC_NONE:
break;
case ESC:
sl->esc = key == '[' ? ESC_BRACKET : ESC_NONE;
- return 0;
+ return 1;
case ESC_BRACKET:
switch (key) {
case 'A': /* up */
@@ -189,10 +224,10 @@ sl_keystroke(struct slackline *sl, int key)
case '9':
sl->nummod = key;
sl->esc = ESC_BRACKET_NUM;
- return 0;
+ return 1;
}
sl->esc = ESC_NONE;
- return 0;
+ return 1;
case ESC_BRACKET_NUM:
switch(key) {
case '~':
@@ -213,35 +248,38 @@ sl_keystroke(struct slackline *sl, int key)
break;
}
sl->esc = ESC_NONE;
- return 0;
+ return 1;
}
}
- if (!iscntrl((unsigned char) key))
- goto compose;
+ return 0;
+}
- /* handle ctl keys */
- switch (key) {
- case 27: /* Escape */
- sl->esc = ESC;
- return 0;
- case 127: /* backspace */
- case 8: /* backspace */
- sl_backspace(sl);
- return 0;
- case 21: /* ctrl+u -- clearline */
- sl_reset(sl);
- return 0;
- case 23: /* ctrl+w -- erase previous word */
- while (sl->rcur != 0 && isspace((unsigned char) *(sl->ptr-1)))
- sl_backspace(sl);
+int
+sl_keystroke(struct slackline *sl, int key)
+{
+ uint_least32_t cp;
- while (sl->rcur != 0 && !isspace((unsigned char) *(sl->ptr-1)))
- sl_backspace(sl);
- return 0;
- default:
+ if (sl == NULL || sl->rlen < sl->rcur)
+ return -1;
+ if (sl_esc(sl, key))
return 0;
+ if (!iscntrl((unsigned char) key))
+ goto compose;
+
+ switch (sl->mode) {
+ case SL_DEFAULT:
+ sl_default(sl, key);
+ break;
+ case SL_EMACS:
+ sl_default(sl, key);
+ sl_emacs(sl, key);
+ break;
+ case SL_VI:
+ /* TODO: implement vi-mode */
+ break;
}
+ return 0;
compose:
/* byte-wise composing of UTF-8 runes */
diff --git a/slackline_emacs.c b/slackline_emacs.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "slackline_internals.h"
+
+void
+sl_emacs(struct slackline *sl, int key)
+{
+ char tmp;
+
+ switch (key) {
+ case 27: /* Escape */
+ sl->esc = ESC;
+ break;
+ case 1: /* ctrl+a -- start of line */
+ sl_move(sl, HOME);
+ break;
+ case 2: /* ctrl+b -- previous char */
+ sl_move(sl, LEFT);
+ break;
+ case 4: /* ctrl+d -- delete char in front of the cursor or exit */
+ if (sl->rcur < sl->rlen) {
+ sl_move(sl, RIGHT);
+ sl_backspace(sl);
+ } else {
+ exit(EXIT_SUCCESS);
+ }
+ break;
+ case 5: /* ctrl+e -- end of line */
+ sl_move(sl, END);
+ break;
+ case 6: /* ctrl+f -- next char */
+ sl_move(sl, RIGHT);
+ break;
+ case 11: /* ctrl+k -- delete line from cursor to end */
+ for (int i = sl->rlen - sl->rcur; i > 0; --i) {
+ sl_move(sl, RIGHT);
+ sl_backspace(sl);
+ }
+ break;
+ case 20: /* ctrl+t -- swap last two chars */
+ if (sl->rcur >= 2) {
+ tmp = *sl_postoptr(sl, sl->rcur-1);
+ sl->buf[sl->rcur-1] = *sl_postoptr(sl, sl->rcur-2);
+ sl->buf[sl->rcur-2] = tmp;
+ }
+ break;
+ default:
+ break;
+ }
+}
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.