about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--input.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/input.c b/input.c
index 87a4eb9..2662cda 100644
--- a/input.c
+++ b/input.c
@@ -44,6 +44,11 @@
 #include "chat.h"
 #include "edit.h"
 
+static enum {
+	InputEmacs,
+	InputVi,
+} inputMode;
+
 #define ENUM_KEY \
 	X(KeyCtrlLeft, "\33[1;5D", NULL) \
 	X(KeyCtrlRight, "\33[1;5C", NULL) \
@@ -58,14 +63,10 @@
 	X(KeyMeta8, "\0338", "\33*") \
 	X(KeyMeta9, "\0339", "\33(") \
 	X(KeyMetaA, "\33a", NULL) \
-	X(KeyMetaB, "\33b", NULL) \
-	X(KeyMetaD, "\33d", NULL) \
-	X(KeyMetaF, "\33f", NULL) \
 	X(KeyMetaL, "\33l", NULL) \
 	X(KeyMetaM, "\33m", NULL) \
 	X(KeyMetaN, "\33n", NULL) \
 	X(KeyMetaP, "\33p", NULL) \
-	X(KeyMetaQ, "\33q", NULL) \
 	X(KeyMetaS, "\33s", NULL) \
 	X(KeyMetaT, "\33t", NULL) \
 	X(KeyMetaU, "\33u", NULL) \
@@ -83,10 +84,17 @@
 	X(KeyPasteOff, "\33[201~", NULL) \
 	X(KeyPasteManual, "\32p", "\32\20")
 
+#define ENUM_KEY_EMACS \
+	X(KeyMetaB, "\33b", NULL) \
+	X(KeyMetaD, "\33d", NULL) \
+	X(KeyMetaF, "\33f", NULL) \
+	X(KeyMetaQ, "\33q", NULL)
+
 enum {
 	KeyMax = KEY_MAX,
 #define X(id, seq, alt) id,
 	ENUM_KEY
+	ENUM_KEY_EMACS
 #undef X
 };
 
@@ -119,10 +127,18 @@ void inputInit(void) {
 
 #define X(id, seq, alt) define_key(seq, id); if (alt) define_key(alt, id);
 	ENUM_KEY
+	ENUM_KEY_EMACS
+#undef X
+
+	if (inputMode != InputEmacs) {
+#define X(id, seq, alt) define_key(NULL, id);
+		ENUM_KEY_EMACS
 #undef X
+	}
 
 	keypad(uiInput, true);
 	nodelay(uiInput, true);
+	notimeout(uiInput, inputMode == InputVi);
 }
 
 static void inputAdd(struct Style reset, struct Style *style, const char *str) {
@@ -455,29 +471,33 @@ static void keyCode(int code) {
 static void keyCtrl(wchar_t ch) {
 	int error = 0;
 	struct Edit *edit = &edits[windowID()];
+	if (inputMode == InputEmacs) {
+		switch (ch ^ L'@') {
+			break; case L'?': error = editFn(edit, EditDeletePrev);
+			break; case L'A': error = editFn(edit, EditHead);
+			break; case L'B': error = editFn(edit, EditPrev);
+			break; case L'D': error = editFn(edit, EditDeleteNext);
+			break; case L'E': error = editFn(edit, EditTail);
+			break; case L'F': error = editFn(edit, EditNext);
+			break; case L'H': error = editFn(edit, EditDeletePrev);
+			break; case L'K': error = editFn(edit, EditDeleteTail);
+			break; case L'T': error = editFn(edit, EditTranspose);
+			break; case L'U': error = editFn(edit, EditDeleteHead);
+			break; case L'W': error = editFn(edit, EditDeletePrevWord);
+			break; case L'Y': error = editFn(edit, EditPaste);
+		}
+	}
 	switch (ch ^ L'@') {
-		break; case L'?': error = editFn(edit, EditDeletePrev);
-		break; case L'A': error = editFn(edit, EditHead);
-		break; case L'B': error = editFn(edit, EditPrev);
 		break; case L'C': raise(SIGINT);
-		break; case L'D': error = editFn(edit, EditDeleteNext);
-		break; case L'E': error = editFn(edit, EditTail);
-		break; case L'F': error = editFn(edit, EditNext);
-		break; case L'H': error = editFn(edit, EditDeletePrev);
 		break; case L'I': error = tabComplete(edit, windowID());
 		break; case L'J': inputEnter();
-		break; case L'K': error = editFn(edit, EditDeleteTail);
 		break; case L'L': clearok(curscr, true); wrefresh(curscr);
 		break; case L'N': windowShow(windowNum() + 1);
 		break; case L'P': windowShow(windowNum() - 1);
 		break; case L'R': windowSearch(editString(edit, &buf, &cap, NULL), -1);
 		break; case L'S': windowSearch(editString(edit, &buf, &cap, NULL), +1);
-		break; case L'T': error = editFn(edit, EditTranspose);
-		break; case L'U': error = editFn(edit, EditDeleteHead);
 		break; case L'V': windowScroll(ScrollPage, -1);
-		break; case L'W': error = editFn(edit, EditDeletePrevWord);
 		break; case L'X': error = macroExpand(edit); tabAccept();
-		break; case L'Y': error = editFn(edit, EditPaste);
 	}
 	if (error) err(EX_OSERR, "editFn");
 }