about summary refs log tree commit diff
path: root/chat.c
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 /chat.c
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.
Diffstat (limited to 'chat.c')
-rw-r--r--chat.c45
1 files changed, 45 insertions, 0 deletions
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;