Commits

ttouch committed bd4f1dd

Added mode support to all keys

  • Participants
  • Parent commits d5d6d20

Comments (0)

Files changed (3)

File config.def.h

 { .keyv.i = KEY_NPAGE,      { 0,     0,    0,   0 },   f_move,      { .m = m_nextscr  } },
 { .keyv.i = KEY_UP,         { t_sent,0,    0,   0 },   f_adjective, { .m = m_prevline } },
 { .keyv.i = KEY_UP,         { 0,     0,    0,   0 },   f_move,      { .m = m_prevline } },
-{ .keyv.i = KEY_DOWN,       { t_sent,0,    0,   0 },   f_move,      { .m = m_nextline } },
 { .keyv.i = KEY_DOWN,       { t_sent,0,    0,   0 },   f_adjective, { .m = m_nextline } },
 { .keyv.i = KEY_DOWN,       { 0,     0,    0,   0 },   f_move,      { .m = m_nextline } },
 { .keyv.i = KEY_LEFT,       { t_sent,0,    0,   0 },   f_adjective, { .m = m_prevchar } },
 { .keyv.c = { 'b' },      { t_sent,0,    0,   0 },  f_adjective, { .m = m_prevword     } },
 { .keyv.c = { 'b' },      { 0,     0,    0,   0 },  f_move,      { .m = m_prevword     } },
 { .keyv.c = { 'c' },      { t_sel, t_rw, 0,   0 },  f_delete,    { .m = m_tosel        } },
-{ .keyv.c = { 'c' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_adjective    } }, /* TODO: queue insert mode, similar to 'y' */
+{ .keyv.c = { 'c' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_sentence    } }, /* TODO: queue insert mode, similar to 'y' */
 { .keyv.c = { 'C' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_eol          } },
 { .keyv.c = { 'C' },      { t_rw,  0,    0,   0 },  f_toggle,    { .i = S_Command      } },
 { .keyv.c = { 'd' },      { t_sel, t_rw, 0,   0 },  f_delete,    { .m = m_tosel        } },
-{ .keyv.c = { 'd' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_adjective    } },
+{ .keyv.c = { 'd' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_sentence    } },
 { .keyv.c = { 'D' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_eol          } },
 { .keyv.c = { 'g' },      { t_sent,0,    0,   0 },  f_adjective, { .m = m_bof          } },
 { .keyv.c = { 'g' },      { 0,     0,    0,   0 },  f_move,      { .m = m_bof          } },
 { .keyv.c = { 'x' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_nextchar     } },
 { .keyv.c = { 'X' },      { t_sel, t_rw, 0,   0 },  f_delete,    { .m = m_tosel        } },
 { .keyv.c = { 'X' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_prevchar     } },
-{ .keyv.c = { 'y' },      { t_rw,  0,    0,   0 },  f_pipero,    { .m = m_adjective, .v = TOCLIP } }, /* TODO: won't work since Arg is a union */
+{ .keyv.c = { 'y' },      { t_rw,  0,    0,   0 },  f_pipero,    { .m = m_sentence, .v = TOCLIP } }, /* TODO: won't work since Arg is a union */
 { .keyv.c = { ';' },      { 0,     0,    0,   0 },  f_spawn,     CMD_P                   },
 { .keyv.c = { ':' },      { 0,     0,    0,   0 },  f_spawn,     CMD_P                   },
 { .keyv.c = { '\'' },     { 0,     0,    0,   0 },  f_move,      { .m = m_tomark       } },
 { .keyv.i = KEY_NPAGE,      { 0,     0,    0,   0 },   f_move,      { .m = m_nextscr  } },
 { .keyv.i = KEY_UP,         { t_sent,0,    0,   0 },   f_adjective, { .m = m_prevline } },
 { .keyv.i = KEY_UP,         { 0,     0,    0,   0 },   f_move,      { .m = m_prevline } },
-{ .keyv.i = KEY_DOWN,       { t_sent,0,    0,   0 },   f_move,      { .m = m_nextline } },
 { .keyv.i = KEY_DOWN,       { t_sent,0,    0,   0 },   f_adjective, { .m = m_nextline } },
 { .keyv.i = KEY_DOWN,       { 0,     0,    0,   0 },   f_move,      { .m = m_nextline } },
 { .keyv.i = KEY_LEFT,       { t_sent,0,    0,   0 },   f_adjective, { .m = m_prevchar } },
 { .keyv.c = { 'b' },      { t_sent,0,    0,   0 },  f_adjective, { .m = m_prevword     } },
 { .keyv.c = { 'b' },      { 0,     0,    0,   0 },  f_move,      { .m = m_prevword     } },
 { .keyv.c = { 'c' },      { t_sel, t_rw, 0,   0 },  f_delete,    { .m = m_tosel        } },
-{ .keyv.c = { 'c' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_adjective    } }, /* TODO: queue insert mode, similar to 'y' */
+{ .keyv.c = { 'c' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_sentence    } }, /* TODO: queue insert mode, similar to 'y' */
 { .keyv.c = { 'C' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_eol          } },
 { .keyv.c = { 'C' },      { t_rw,  0,    0,   0 },  f_toggle,    { .i = S_Command      } },
 { .keyv.c = { 'd' },      { t_sel, t_rw, 0,   0 },  f_delete,    { .m = m_tosel        } },
-{ .keyv.c = { 'd' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_adjective    } },
+{ .keyv.c = { 'd' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_sentence    } },
 { .keyv.c = { 'D' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_eol          } },
 { .keyv.c = { 'g' },      { t_sent,0,    0,   0 },  f_adjective, { .m = m_bof          } },
 { .keyv.c = { 'g' },      { 0,     0,    0,   0 },  f_move,      { .m = m_bof          } },
 { .keyv.c = { 'x' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_nextchar     } },
 { .keyv.c = { 'X' },      { t_sel, t_rw, 0,   0 },  f_delete,    { .m = m_tosel        } },
 { .keyv.c = { 'X' },      { t_rw,  0,    0,   0 },  f_delete,    { .m = m_prevchar     } },
-{ .keyv.c = { 'y' },      { t_rw,  0,    0,   0 },  f_pipero,    { .m = m_adjective, .v = TOCLIP } }, /* TODO: won't work since Arg is a union */
+{ .keyv.c = { 'y' },      { t_rw,  0,    0,   0 },  f_pipero,    { .m = m_sentence, .v = TOCLIP } }, /* TODO: won't work since Arg is a union */
 { .keyv.c = { ';' },      { 0,     0,    0,   0 },  f_spawn,     CMD_P                   },
 { .keyv.c = { ':' },      { 0,     0,    0,   0 },  f_spawn,     CMD_P                   },
 { .keyv.c = { '\'' },     { 0,     0,    0,   0 },  f_move,      { .m = m_tomark       } },
 static int       syntx = -1;                        /* Current syntax index */
 static regex_t  *find_res[2];                       /* Compiled regex for search term */
 static int       sel_re = 0;                        /* Index to the above, we keep 2 REs so regexec does not segfault */
+static char      c[7];                              /* Used to store input */
 static char     *fifopath = NULL;                   /* Path to command fifo */
 static char     *filename = NULL;                   /* Path to file loade on buffer */
 static char     *title    = NULL;                   /* Screen title */
 static void           i_die(char *str);
 static void           i_dirtyrange(Line*, Line*);
 static bool           i_dotests(bool (*const a[])(void));
+static bool           i_dokeys(const Key bindings[], int index, bool multi);
 static void           i_edit(void);
 static void           i_find(bool);
 static char          *i_gettext(Filepos, Filepos);
 static bool t_warn(void);
 
 /* m_ functions represent a cursor movement and can be passed in an Arg */
-static Filepos m_adjective(Filepos);
 static Filepos m_bof(Filepos);
 static Filepos m_bol(Filepos);
 static Filepos m_smartbol(Filepos);
 static Filepos m_prevline(Filepos);
 static Filepos m_nextscr(Filepos);
 static Filepos m_prevscr(Filepos);
+static Filepos m_parameter(Filepos);
+static Filepos m_sentence(Filepos);
 static Filepos m_stay(Filepos);
 static Filepos m_tomark(Filepos);
 static Filepos m_tosel(Filepos);
 		} else return TRUE;
 }
 
+bool
+i_dokeys(const Key bindings[], int index, bool multi) {
+	int i;
+
+	if(bindings[index].func != f_insert) statusflags&=~(S_GroupUndo);
+
+	/* Handle sentences */
+	if(t_sent()) {
+		if(bindings[index].func == verb) i_multiply(verb, (const Arg){ .m = m_nextline });
+
+		if(bindings[index].func != f_adjective) {
+			statusflags&=~S_Sentence;
+			return FALSE;
+		}
+	} else if(bindings[index].arg.m == m_sentence) {
+		statusflags|=(long)S_Sentence;
+		verb=bindings[index].func;
+		return FALSE;
+	}
+
+	/* Handle parameter sentences (verb is used here to define the command to execute) */
+	if(statusflags & S_Parameter) {
+		statusflags&=~S_Parameter;
+		i_multiply(verb, (const Arg){ .v = c });
+		return FALSE;
+	} else if(bindings[index].arg.m == m_parameter) {
+		statusflags|=(long)S_Parameter;
+		verb=bindings[index].func;
+		return FALSE;
+	}
+
+	i_multiply(bindings[index].func, bindings[index].arg);
+
+	/* Handle multi-function commands */
+	if(multi) {
+		i=-1;
+
+		while(1)
+			if(bindings[index].test[++i]) {
+				if(bindings[index].test[i] != bindings[index+1].test[i]) {
+					return FALSE;
+				}
+			} else return TRUE;
+	}
+
+	return FALSE;
+}
+
 void /* Main editing loop */
 i_edit(void) {
-	int ch, i, j;
-	char c[7];
-	bool pass;
+	int ch, i;
+	bool multif;
 	fd_set fds;
 	Filepos oldsel, oldcur;
 
 #endif /* HANDLE_MOUSE */
 			for(i=0; i<LENGTH(curskeys); i++) {
 				if(ch == curskeys[i].keyv.i && i_dotests(curskeys[i].test) ) {
-
-#if VIM_BINDINGS
-					if(t_sent()) {
-						if(curskeys[i].func == verb) i_multiply(verb, (const Arg){ .m = m_nextline });
-
-						if(curskeys[i].func != f_adjective) {
-							statusflags&=~S_Sentence;
-							break;
+					if(i+1 < LENGTH(curskeys)) {
+						if(curskeys[i].keyv.i == curskeys[i+1].keyv.i) {
+							multif = TRUE;
 						}
-					}
-#endif /* VIM_BINDINGS */
+					} else multif = FALSE;
 
-					if(curskeys[i].func != f_insert) statusflags&=~(S_GroupUndo);
-					i_multiply(curskeys[i].func, curskeys[i].arg);
-					break;
+					if(i_dokeys(curskeys, i, multif)) continue;
+					else break;
 				}
 			}
 			continue;
 		if(!(statusflags&S_InsEsc) && ISCTRL(c[0])) {
 			for(i=0; i<LENGTH(stdkeys); i++) {
 				if(memcmp(c, stdkeys[i].keyv.c, sizeof stdkeys[i].keyv.c) == 0 && i_dotests(stdkeys[i].test) ) {
-
-#if VIM_BINDINGS
-					if(t_sent()) {
-						if(stdkeys[i].func == verb) i_multiply(verb, (const Arg){ .m = m_nextline });
-
-						if(stdkeys[i].func != f_adjective) {
-							statusflags&=~S_Sentence;
-							break;
+					if(i+1 < LENGTH(stdkeys)) {
+						if(memcmp(stdkeys[i+1].keyv.c, stdkeys[i].keyv.c, sizeof stdkeys[i].keyv.c) == 0) {
+							multif = TRUE;
 						}
-					}
-#endif /* VIM_BINDINGS */
+					} else multif = FALSE;
 
-					if(stdkeys[i].func != f_insert) statusflags&=~(S_GroupUndo);
-					i_multiply(stdkeys[i].func, stdkeys[i].arg);
-					break;
+					if(i_dokeys(stdkeys, i, multif)) continue;
+					else break;
 				}
 			}
 			continue;
 		}
 		statusflags&=~(S_InsEsc);
 
-#if VIM_BINDINGS
 		if(t_rw() && t_ins()) f_insert(&(const Arg){ .v = c });
+#if VIM_BINDINGS
 		else if(!t_ins()) {
 			if(ch >= '0' && ch <= '9' && !(statusflags & S_Parameter)) {
 				if(statusflags & S_Multiply) {
 				}
 			} else for(i=0; i<LENGTH(commkeys); i++) {
 				if(memcmp(c, commkeys[i].keyv.c, sizeof commkeys[i].keyv.c) == 0 && i_dotests(commkeys[i].test) ) {
-					if(commkeys[i].func != f_insert) statusflags&=~(S_GroupUndo);
-
-					/* Handle sentences */
-					// FIXME: Find a better way to tell if a func is a verb or parameter
-					if(t_sent()) {
-						if(commkeys[i].func == verb) i_multiply(verb, (const Arg){ .m = m_nextline });
-
-						if(commkeys[i].func != f_adjective) {
-							statusflags&=~S_Sentence;
-							break;
-						}
-					} else if(commkeys[i].arg.m == m_adjective) {
-						statusflags|=(long)S_Sentence;
-						verb=commkeys[i].func;
-						break;
-					}
-
-					/* Handle parameter sentences (verb is used here to define the command to execute) */
-					if(statusflags & S_Parameter) {
-						statusflags&=~S_Parameter;
-						i_multiply(verb, (const Arg){ .v = c });
-						break;
-					} else if(commkeys[i].arg.m == m_adjective) {
-						statusflags|=(long)S_Parameter;
-						verb=commkeys[i].func;
-						break;
-					}
-
-					i_multiply(commkeys[i].func, commkeys[i].arg);
-
-					/* Handle multi-function commands */
-					// TODO: Find a way to handle multi-function verbs
 					if(i+1 < LENGTH(commkeys)) {
 						if(memcmp(commkeys[i+1].keyv.c, commkeys[i].keyv.c, sizeof commkeys[i].keyv.c) == 0) {
-							j=-1;
-							pass=TRUE;
-
-							while(1)
-								if(commkeys[i].test[++j]) {
-									if(commkeys[i].test[j] != commkeys[i+1].test[j]) {
-										pass=FALSE;
-										break;
-									}
-								} else break;
-
-							if(pass) continue;
-							else break;
+							multif = TRUE;
 						}
-					}
+					} else multif = FALSE;
 
-					break;
+					if(i_dokeys(commkeys, i, multif)) continue;
+					else break;
 				}
 			}
 		}
-#else
-		if(t_rw()) f_insert(&(const Arg){ .v = c });
 #endif /* VIM_BINDINGS */
 		else tmptitle="WARNING! File is read-only!!!";
 
 
 /* M_* FUNCTIONS
 	Represent a cursor motion, always take a Filepos and return an update Filepos */
-Filepos /* Go to where the adjective says */
-m_adjective(Filepos pos) {
-  /* WARNING: this code is actually not used */
-  return pos;
-}
 
 Filepos /* Go to beginning of file */
 m_bof(Filepos pos) {
 	return pos;
 }
 
+Filepos /* Go to where the adjective says */
+m_parameter(Filepos pos) {
+  /* WARNING: this code is actually not used */
+  return pos;
+}
+
 Filepos /* Backup as many lines as the screen size */
 m_prevscr(Filepos pos) {
 	int i;
 	return pos;
 }
 
+Filepos /* Go to where the adjective says */
+m_sentence(Filepos pos) {
+  /* WARNING: this code is actually not used */
+  return pos;
+}
+
 Filepos /* Do not move */
 m_stay(Filepos pos) {
 	return pos;