about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2022-03-12 16:19:02 -0500
committerJune McEnroe <june@causal.agency>2022-03-12 16:19:02 -0500
commitfc56a9f8d70579393e66a22a7df15fba2d78c154 (patch)
tree92ce33595da31df07ce93db09d32959a5eae9f5c
parentReset to vi insert mode on enter (diff)
downloadcatgirl-fc56a9f8d70579393e66a22a7df15fba2d78c154.tar.gz
catgirl-fc56a9f8d70579393e66a22a7df15fba2d78c154.zip
Add edit option to set line editing mode
I'm not super happy with the guessing based on .editrc or .inputrc
because I'm not parsing the files for real, but it's a conservative
guess and should do the right thing in most cases.
-rw-r--r--catgirl.124
-rw-r--r--chat.c45
-rw-r--r--chat.h6
-rw-r--r--input.c5
4 files changed, 74 insertions, 6 deletions
diff --git a/catgirl.1 b/catgirl.1
index 16a59da..1349f4a 100644
--- a/catgirl.1
+++ b/catgirl.1
@@ -1,4 +1,4 @@
-.Dd February 22, 2022
+.Dd March 12, 2022
 .Dt CATGIRL 1
 .Os
 .
@@ -10,6 +10,7 @@
 .Nm
 .Op Fl KRelqv
 .Op Fl C Ar copy
+.Op Fl E Ar edit
 .Op Fl H Ar hash
 .Op Fl I Ar highlight
 .Op Fl N Ar notify
@@ -108,6 +109,24 @@ The default is the first available of
 .Xr xclip 1 ,
 .Xr xsel 1 .
 .
+.It Fl E Ar mode | Cm edit No = Ar mode
+Set the line editing mode to
+.Cm emacs
+or
+.Cm vi.
+The default is
+.Cm auto ,
+which sets the mode to
+.Cm vi
+if
+.Ql bind -v
+appears in
+.Pa ~/.editrc
+or
+.Ql set editing-mode vi
+appears in
+.Pa ~/.inputrc .
+.
 .It Fl H Ar seed,bound | Cm hash No = Ar seed,bound
 Set the initial seed
 of the nick and channel
@@ -904,6 +923,9 @@ usually
 .Pa /usr/local/share:/usr/share .
 .It Pa ~/.local/share/catgirl
 The most likely location of save files.
+.
+.It Pa ~/.editrc , Pa ~/.inputrc
+Used to guess the default line editing mode.
 .El
 .
 .Sh EXIT STATUS
diff --git a/chat.c b/chat.c
index b74fdc0..e23051b 100644
--- a/chat.c
+++ b/chat.c
@@ -125,6 +125,47 @@ static void utilRead(void) {
 	}
 }
 
+static void parseEdit(const char *str) {
+	if (!strcmp(str, "emacs")) {
+		inputMode = InputEmacs;
+		return;
+	} else if (!strcmp(str, "vi")) {
+		inputMode = InputVi;
+		return;
+	} else if (strcmp(str, "auto")) {
+		errx(EX_USAGE, "unrecognized edit mode %s", str);
+	}
+
+	inputMode = InputEmacs;
+	static const struct {
+		const char *name;
+		const char *line;
+	} Files[] = {
+		{ ".editrc", "bind -v\n" },
+		{ ".inputrc", "set editing-mode vi\n" },
+	};
+	size_t cap = 0;
+	char *buf = NULL;
+	char path[PATH_MAX];
+	const char *home = getenv("HOME");
+	if (!home) errx(EX_USAGE, "HOME unset");
+	for (size_t i = 0; i < ARRAY_LEN(Files); ++i) {
+		snprintf(path, sizeof(path), "%s/%s", home, Files[i].name);
+		FILE *file = fopen(path, "r");
+		if (!file) continue;
+		while (0 < getline(&buf, &cap, file)) {
+			if (!strcmp(buf, Files[i].line)) {
+				inputMode = InputVi;
+				fclose(file);
+				free(buf);
+				return;
+			}
+		}
+		fclose(file);
+	}
+	free(buf);
+}
+
 uint32_t hashInit;
 uint32_t hashBound = 75;
 
@@ -244,6 +285,7 @@ int main(int argc, char *argv[]) {
 	struct option options[] = {
 		{ .val = '!', .name = "insecure", no_argument },
 		{ .val = 'C', .name = "copy", required_argument },
+		{ .val = 'E', .name = "edit", required_argument },
 		{ .val = 'H', .name = "hash", required_argument },
 		{ .val = 'I', .name = "highlight", required_argument },
 		{ .val = 'K', .name = "kiosk", no_argument },
@@ -281,10 +323,12 @@ int main(int argc, char *argv[]) {
 		if (options[i].has_arg == optional_argument) opts[j++] = ':';
 	}
 
+	bool editSet = false;
 	for (int opt; 0 < (opt = getopt_config(argc, argv, opts, options, NULL));) {
 		switch (opt) {
 			break; case '!': insecure = true;
 			break; case 'C': utilPush(&urlCopyUtil, optarg);
+			break; case 'E': editSet = true; parseEdit(optarg);
 			break; case 'H': parseHash(optarg);
 			break; case 'I': filterAdd(Hot, optarg);
 			break; case 'K': self.kiosk = true;
@@ -333,6 +377,7 @@ int main(int argc, char *argv[]) {
 		return EX_OK;
 	}
 
+	if (!editSet) parseEdit("auto");
 	if (!nick) nick = getenv("USER");
 	if (!nick) errx(EX_CONFIG, "USER unset");
 	if (!user) user = nick;
diff --git a/chat.h b/chat.h
index 1c46f00..af9cea8 100644
--- a/chat.h
+++ b/chat.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2020  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -328,6 +328,10 @@ void uiFormat(
 void uiLoad(const char *name);
 int uiSave(void);
 
+extern enum InputMode {
+	InputEmacs,
+	InputVi,
+} inputMode;
 void inputInit(void);
 void inputWait(void);
 void inputUpdate(void);
diff --git a/input.c b/input.c
index 07b8b89..889bde7 100644
--- a/input.c
+++ b/input.c
@@ -44,10 +44,7 @@
 #include "chat.h"
 #include "edit.h"
 
-static enum {
-	InputEmacs,
-	InputVi,
-} inputMode;
+enum InputMode inputMode;
 
 #define ENUM_KEY \
 	X(KeyCtrlLeft, "\33[1;5D", NULL) \