[dev][vis] Set tabwidth and expandtab in config.h

From: Matthias Rabault <matthias.rabault_AT_mailoo.org>
Date: Sat, 3 Jan 2015 22:41:19 +0100

The two values were previously supplied as "magic constants".

Signed-off-by: Matthias Rabault <matthias.rabault_AT_mailoo.org>

This raises another problem with the includes. I had to put some of the
definitions in vis.h, but in turn that made gcc complain that there were
functions declared in vis.h but not defined in this header, although
they were used. I'm not sure how best to handle that, though. I'm sorry
if I've made stupid errors, but I wanted to help with this project.
vis runs fine after the patch, it's only gcc warnings.

Please forgive any English errors I might have made, English is not my
primary language.
---
 config.def.h |   8 +
 editor.c     |   5 +-
 vis.c        | 482 +---------------------------------------------------------
 vis.h        | 486 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 498 insertions(+), 483 deletions(-)
 create mode 100644 vis.h
diff --git a/config.def.h b/config.def.h
index aac28a8..cc6192d 100644
--- a/config.def.h
+++ b/config.def.h
_AT_@ -1,3 +1,7 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+#include "vis.h"
+
 /** start by reading from the top of vis.c up until config.h is included */
 #define DEFAULT_TERM "xterm" /* default term to use if $TERM isn't set */
 /* macros used to specify keys for key bindings */
_AT_@ -12,6 +16,9 @@
 	{ { NONE(127) },      (func), { .name = (arg) } }, \
 	{ { CONTROL('B') },   (func), { .name = (arg) } }
 
+#define TABWIDTH 8
+#define EXPANDTAB false
+
 /* a mode contains a set of key bindings which are currently valid.
  *
  * each mode can specify one parent mode which is consultated if a given key
_AT_@ -1208,3 +1215,4 @@ static Syntax syntaxes[] = {{
 },{
 	/* empty last element, array terminator */
 }};
+#endif
diff --git a/editor.c b/editor.c
index ef59242..902e383 100644
--- a/editor.c
+++ b/editor.c
_AT_@ -4,6 +4,7 @@
 #include <unistd.h>
 #include "editor.h"
 #include "util.h"
+#include "config.h"
 
 #ifdef NCURSES_VERSION
 # ifndef NCURSES_EXT_COLORS
_AT_@ -441,8 +442,8 @@ Editor *editor_new(int width, int height) {
 		goto err;
 	ed->width = width;
 	ed->height = height;
-	ed->tabwidth = 8;
-	ed->expandtab = false;
+	ed->tabwidth = TABWIDTH;
+	ed->expandtab = EXPANDTAB;
 	ed->windows_arrange = windows_arrange_horizontal;
 	return ed;
 err:
diff --git a/vis.c b/vis.c
index 7ccfa22..bad309e 100644
--- a/vis.c
+++ b/vis.c
_AT_@ -40,487 +40,7 @@ int ESCDELAY;
 # define set_escdelay(d) (ESCDELAY = (d))
 #endif
 
-typedef union {
-	bool b;
-	int i;
-	const char *s;
-	void (*w)(Win*);    /* generic window commands */
-	void (*f)(Editor*); /* generic editor commands */
-} Arg;
-
-typedef struct {
-	char str[6]; /* UTF8 character or terminal escape code */
-	int code;    /* curses KEY_* constant */
-} Key;
-
-#define MAX_KEYS 2
-typedef Key KeyCombo[MAX_KEYS];
-
-typedef struct {
-	KeyCombo key;
-	void (*func)(const Arg *arg);
-	const Arg arg;
-} KeyBinding;
-
-typedef struct Mode Mode;
-struct Mode {
-	Mode *parent;                       /* if no match is found in this mode, search will continue there */
-	KeyBinding *bindings;               /* NULL terminated array of keybindings for this mode */
-	const char *name;                   /* descriptive, user facing name of the mode */
-	bool isuser;                        /* whether this is a user or internal mode */
-	bool common_prefix;                 /* whether the first key in this mode is always the same */
-	void (*enter)(Mode *old);           /* called right before the mode becomes active */
-	void (*leave)(Mode *new);           /* called right before the mode becomes inactive */
-	bool (*unknown)(KeyCombo);          /* called whenever a key combination is not found in this mode,
-	                                       the return value determines whether parent modes will be searched */
-	void (*input)(const char*, size_t); /* called whenever a key is not found in this mode and all its parent modes */
-	void (*idle)(void);                 /* called whenever a certain idle time i.e. without any user input elapsed */
-	time_t idle_timeout;                /* idle time in seconds after which the registered function will be called */
-	bool visual;                        /* whether text selection is possible in this mode */
-};
-
-typedef struct {
-	char *name;                    /* is used to match against argv[0] to enable this config */
-	Mode *mode;                    /* default mode in which the editor should start in */
-	void (*statusbar)(EditorWin*); /* routine which is called whenever the cursor is moved within a window */
-	bool (*keypress)(Key*);        /* called before any other keybindings are checked,
-	                                * return value decides whether key should be ignored */
-} Config;
-
-typedef struct {
-	int count;        /* how many times should the command be executed? */
-	Register *reg;    /* always non-NULL, set to a default register */
-	Filerange range;  /* which part of the file should be affected by the operator */
-	size_t pos;       /* at which byte from the start of the file should the operation start? */
-	bool linewise;    /* should the changes always affect whole lines? */
-	const Arg *arg;   /* arbitrary arguments */
-} OperatorContext;
-
-typedef struct {
-	void (*func)(OperatorContext*); /* function implementing the operator logic */
-} Operator;
-
-typedef struct {
-	size_t (*cmd)(const Arg*);        /* a custom movement based on user input from vis.c */
-	size_t (*win)(Win*);              /* a movement based on current window content from window.h */
-	size_t (*txt)(Text*, size_t pos); /* a movement form text-motions.h */
-	enum {
-		LINEWISE  = 1 << 0,
-		CHARWISE  = 1 << 1,
-		INCLUSIVE = 1 << 2,
-		EXCLUSIVE = 1 << 3,
-		IDEMPOTENT = 1 << 4,
-		JUMP = 1 << 5,
-	} type;
-	int count;
-} Movement;
-
-typedef struct {
-	Filerange (*range)(Text*, size_t pos); /* a text object from text-objects.h */
-	enum {
-		INNER,
-		OUTER,
-	} type;
-} TextObject;
-
-typedef struct {             /** collects all information until an operator is executed */
-	int count;
-	bool linewise;
-	Operator *op;
-	Movement *movement;
-	TextObject *textobj;
-	Register *reg;
-	MarkIntern mark;
-	Key key;
-	Arg arg;
-} Action;
-
-typedef struct {                         /* command definitions for the ':'-prompt */
-	const char *name;                /* regular expression pattern to match command */
-	bool (*cmd)(Filerange*, const char *argv[]);
-	                                 /* command logic called with a NULL terminated array
-	                                  * of arguments. argv[0] will be the command name,
-	                                  * as matched by the regex. */
-	bool args;                       /* whether argv should be populated with words
-	                                  * separated by spaces. if false, argv[1] will
-	                                  * contain the remaining command line unmodified */
-	regex_t regex;                   /* compiled form of the pattern in 'name' */
-} Command;
-
-/** global variables */
-static volatile bool running = true; /* exit main loop once this becomes false */
-static Editor *vis;         /* global editor instance, keeps track of all windows etc. */
-static Mode *mode;          /* currently active mode, used to search for keybindings */
-static Mode *mode_prev;     /* previsouly active user mode */
-static Mode *mode_before_prompt; /* user mode which was active before entering prompt */
-static Action action;       /* current action which is in progress */
-static Action action_prev;  /* last operator action used by the repeat '.' key */
-static Buffer buffer_repeat;/* repeat last modification i.e. insertion/replacement */
-
-/** operators */
-static void op_change(OperatorContext *c);
-static void op_yank(OperatorContext *c);
-static void op_put(OperatorContext *c);
-static void op_delete(OperatorContext *c);
-static void op_shift_right(OperatorContext *c);
-static void op_shift_left(OperatorContext *c);
-static void op_case_change(OperatorContext *c);
-static void op_join(OperatorContext *c);
-static void op_repeat_insert(OperatorContext *c);
-static void op_repeat_replace(OperatorContext *c);
-
-/* these can be passed as int argument to operator(&(const Arg){ .i = OP_*}) */
-enum {
-	OP_DELETE,
-	OP_CHANGE,
-	OP_YANK,
-	OP_PUT,
-	OP_SHIFT_RIGHT,
-	OP_SHIFT_LEFT,
-	OP_CASE_CHANGE,
-	OP_JOIN,
-	OP_REPEAT_INSERT,
-	OP_REPEAT_REPLACE,
-};
-
-static Operator ops[] = {
-	[OP_DELETE]      = { op_delete      },
-	[OP_CHANGE]      = { op_change      },
-	[OP_YANK]        = { op_yank        },
-	[OP_PUT]         = { op_put         },
-	[OP_SHIFT_RIGHT] = { op_shift_right },
-	[OP_SHIFT_LEFT]  = { op_shift_left  },
-	[OP_CASE_CHANGE] = { op_case_change },
-	[OP_JOIN]          = { op_join          },
-	[OP_REPEAT_INSERT]  = { op_repeat_insert  },
-	[OP_REPEAT_REPLACE] = { op_repeat_replace },
-};
-
-#define PAGE      INT_MAX
-#define PAGE_HALF (INT_MAX-1)
-
-/* these can be passed as int argument to movement(&(const Arg){ .i = MOVE_* }) */
-enum {
-	MOVE_SCREEN_LINE_UP,
-	MOVE_SCREEN_LINE_DOWN,
-	MOVE_SCREEN_LINE_BEGIN,
-	MOVE_SCREEN_LINE_MIDDLE,
-	MOVE_SCREEN_LINE_END,
-	MOVE_LINE_PREV,
-	MOVE_LINE_BEGIN,
-	MOVE_LINE_START,
-	MOVE_LINE_FINISH,
-	MOVE_LINE_LASTCHAR,
-	MOVE_LINE_END,
-	MOVE_LINE_NEXT,
-	MOVE_LINE,
-	MOVE_COLUMN,
-	MOVE_CHAR_PREV,
-	MOVE_CHAR_NEXT,
-	MOVE_WORD_START_NEXT,
-	MOVE_WORD_END_PREV,
-	MOVE_WORD_END_NEXT,
-	MOVE_WORD_START_PREV,
-	MOVE_LONGWORD_START_PREV,
-	MOVE_LONGWORD_START_NEXT,
-	MOVE_LONGWORD_END_PREV,
-	MOVE_LONGWORD_END_NEXT,
-	MOVE_SENTENCE_PREV,
-	MOVE_SENTENCE_NEXT,
-	MOVE_PARAGRAPH_PREV,
-	MOVE_PARAGRAPH_NEXT,
-	MOVE_BRACKET_MATCH,
-	MOVE_LEFT_TO,
-	MOVE_RIGHT_TO,
-	MOVE_LEFT_TILL,
-	MOVE_RIGHT_TILL,
-	MOVE_FILE_BEGIN,
-	MOVE_FILE_END,
-	MOVE_MARK,
-	MOVE_MARK_LINE,
-	MOVE_SEARCH_WORD_FORWARD,
-	MOVE_SEARCH_WORD_BACKWARD,
-	MOVE_SEARCH_FORWARD,
-	MOVE_SEARCH_BACKWARD,
-	MOVE_WINDOW_LINE_TOP,
-	MOVE_WINDOW_LINE_MIDDLE,
-	MOVE_WINDOW_LINE_BOTTOM,
-};
-
-/** movements which can be used besides the one in text-motions.h and window.h */
-
-/* search in forward direction for the word under the cursor */
-static size_t search_word_forward(const Arg *arg);
-/* search in backward direction for the word under the cursor */
-static size_t search_word_backward(const Arg *arg);
-/* search again for the last used search pattern */
-static size_t search_forward(const Arg *arg);
-static size_t search_backward(const Arg *arg);
-/* goto action.mark */
-static size_t mark_goto(const Arg *arg);
-/* goto first non-blank char on line pointed by action.mark */
-static size_t mark_line_goto(const Arg *arg);
-/* goto to next occurence of action.key to the right */
-static size_t to(const Arg *arg);
-/* goto to position before next occurence of action.key to the right */
-static size_t till(const Arg *arg);
-/* goto to next occurence of action.key to the left */
-static size_t to_left(const Arg *arg);
-/* goto to position after next occurence of action.key to the left */
-static size_t till_left(const Arg *arg);
-/* goto line number action.count */
-static size_t line(const Arg *arg);
-/* goto to byte action.count on current line */
-static size_t column(const Arg *arg);
-/* goto the action.count-th line from top of the focused window */
-static size_t window_lines_top(const Arg *arg);
-/* goto the start of middle line of the focused window */
-static size_t window_lines_middle(const Arg *arg);
-/* goto the action.count-th line from bottom of the focused window */
-static size_t window_lines_bottom(const Arg *arg);
-
-static Movement moves[] = {
-	[MOVE_SCREEN_LINE_UP]      = { .win = window_line_up                                       },
-	[MOVE_SCREEN_LINE_DOWN]    = { .win = window_line_down                                     },
-	[MOVE_SCREEN_LINE_BEGIN]   = { .win = window_line_begin,        .type = CHARWISE           },
-	[MOVE_SCREEN_LINE_MIDDLE]  = { .win = window_line_middle,       .type = CHARWISE           },
-	[MOVE_SCREEN_LINE_END]     = { .win = window_line_end,          .type = CHARWISE|INCLUSIVE },
-	[MOVE_LINE_PREV]           = { .txt = text_line_prev,           .type = LINEWISE           },
-	[MOVE_LINE_BEGIN]          = { .txt = text_line_begin,          .type = LINEWISE           },
-	[MOVE_LINE_START]          = { .txt = text_line_start,          .type = LINEWISE           },
-	[MOVE_LINE_FINISH]         = { .txt = text_line_finish,         .type = LINEWISE|INCLUSIVE },
-	[MOVE_LINE_LASTCHAR]       = { .txt = text_line_lastchar,       .type = LINEWISE|INCLUSIVE },
-	[MOVE_LINE_END]            = { .txt = text_line_end,            .type = LINEWISE           },
-	[MOVE_LINE_NEXT]           = { .txt = text_line_next,           .type = LINEWISE           },
-	[MOVE_LINE]                = { .cmd = line,                     .type = LINEWISE|IDEMPOTENT|JUMP},
-	[MOVE_COLUMN]              = { .cmd = column,                   .type = CHARWISE|IDEMPOTENT},
-	[MOVE_CHAR_PREV]           = { .win = window_char_prev                                     },
-	[MOVE_CHAR_NEXT]           = { .win = window_char_next                                     },
-	[MOVE_WORD_START_PREV]     = { .txt = text_word_start_prev,     .type = CHARWISE           },
-	[MOVE_WORD_START_NEXT]     = { .txt = text_word_start_next,     .type = CHARWISE           },
-	[MOVE_WORD_END_PREV]       = { .txt = text_word_end_prev,       .type = CHARWISE|INCLUSIVE },
-	[MOVE_WORD_END_NEXT]       = { .txt = text_word_end_next,       .type = CHARWISE|INCLUSIVE },
-	[MOVE_LONGWORD_START_PREV] = { .txt = text_longword_start_prev, .type = CHARWISE           },
-	[MOVE_LONGWORD_START_NEXT] = { .txt = text_longword_start_next, .type = CHARWISE           },
-	[MOVE_LONGWORD_END_PREV]   = { .txt = text_longword_end_prev,   .type = CHARWISE|INCLUSIVE },
-	[MOVE_LONGWORD_END_NEXT]   = { .txt = text_longword_end_next,   .type = CHARWISE|INCLUSIVE },
-	[MOVE_SENTENCE_PREV]       = { .txt = text_sentence_prev,       .type = LINEWISE           },
-	[MOVE_SENTENCE_NEXT]       = { .txt = text_sentence_next,       .type = LINEWISE           },
-	[MOVE_PARAGRAPH_PREV]      = { .txt = text_paragraph_prev,      .type = LINEWISE|JUMP      },
-	[MOVE_PARAGRAPH_NEXT]      = { .txt = text_paragraph_next,      .type = LINEWISE|JUMP      },
-	[MOVE_BRACKET_MATCH]       = { .txt = text_bracket_match,       .type = LINEWISE|INCLUSIVE|JUMP },
-	[MOVE_FILE_BEGIN]          = { .txt = text_begin,               .type = LINEWISE|JUMP      },
-	[MOVE_FILE_END]            = { .txt = text_end,                 .type = LINEWISE|JUMP      },
-	[MOVE_LEFT_TO]             = { .cmd = to_left,                  .type = LINEWISE           },
-	[MOVE_RIGHT_TO]            = { .cmd = to,                       .type = LINEWISE|INCLUSIVE },
-	[MOVE_LEFT_TILL]           = { .cmd = till_left,                .type = LINEWISE           },
-	[MOVE_RIGHT_TILL]          = { .cmd = till,                     .type = LINEWISE|INCLUSIVE },
-	[MOVE_MARK]                = { .cmd = mark_goto,                .type = LINEWISE|JUMP      },
-	[MOVE_MARK_LINE]           = { .cmd = mark_line_goto,           .type = LINEWISE|JUMP      },
-	[MOVE_SEARCH_WORD_FORWARD] = { .cmd = search_word_forward,      .type = LINEWISE|JUMP      },
-	[MOVE_SEARCH_WORD_BACKWARD]= { .cmd = search_word_backward,     .type = LINEWISE|JUMP      },
-	[MOVE_SEARCH_FORWARD]      = { .cmd = search_forward,           .type = LINEWISE|JUMP      },
-	[MOVE_SEARCH_BACKWARD]     = { .cmd = search_backward,          .type = LINEWISE|JUMP      },
-	[MOVE_WINDOW_LINE_TOP]     = { .cmd = window_lines_top,         .type = LINEWISE|JUMP      },
-	[MOVE_WINDOW_LINE_MIDDLE]  = { .cmd = window_lines_middle,      .type = LINEWISE|JUMP      },
-	[MOVE_WINDOW_LINE_BOTTOM]  = { .cmd = window_lines_bottom,      .type = LINEWISE|JUMP      },
-};
-
-/* these can be passed as int argument to textobj(&(const Arg){ .i = TEXT_OBJ_* }) */
-enum {
-	TEXT_OBJ_INNER_WORD,
-	TEXT_OBJ_OUTER_WORD,
-	TEXT_OBJ_INNER_LONGWORD,
-	TEXT_OBJ_OUTER_LONGWORD,
-	TEXT_OBJ_LINE_UP,
-	TEXT_OBJ_LINE_DOWN,
-	TEXT_OBJ_SENTENCE,
-	TEXT_OBJ_PARAGRAPH,
-	TEXT_OBJ_OUTER_SQUARE_BRACKET,
-	TEXT_OBJ_INNER_SQUARE_BRACKET,
-	TEXT_OBJ_OUTER_CURLY_BRACKET,
-	TEXT_OBJ_INNER_CURLY_BRACKET,
-	TEXT_OBJ_OUTER_ANGLE_BRACKET,
-	TEXT_OBJ_INNER_ANGLE_BRACKET,
-	TEXT_OBJ_OUTER_PARANTHESE,
-	TEXT_OBJ_INNER_PARANTHESE,
-	TEXT_OBJ_OUTER_QUOTE,
-	TEXT_OBJ_INNER_QUOTE,
-	TEXT_OBJ_OUTER_SINGLE_QUOTE,
-	TEXT_OBJ_INNER_SINGLE_QUOTE,
-	TEXT_OBJ_OUTER_BACKTICK,
-	TEXT_OBJ_INNER_BACKTICK,
-};
-
-static TextObject textobjs[] = {
-	[TEXT_OBJ_INNER_WORD]           = { text_object_word                  },
-	[TEXT_OBJ_OUTER_WORD]           = { text_object_word_outer            },
-	[TEXT_OBJ_INNER_LONGWORD]       = { text_object_longword              },
-	[TEXT_OBJ_OUTER_LONGWORD]       = { text_object_longword_outer        },
-	[TEXT_OBJ_LINE_UP]              = { text_object_line                  },
-	[TEXT_OBJ_LINE_DOWN]            = { text_object_line                  },
-	[TEXT_OBJ_SENTENCE]             = { text_object_sentence              },
-	[TEXT_OBJ_PARAGRAPH]            = { text_object_paragraph             },
-	[TEXT_OBJ_OUTER_SQUARE_BRACKET] = { text_object_square_bracket, OUTER },
-	[TEXT_OBJ_INNER_SQUARE_BRACKET] = { text_object_square_bracket, INNER },
-	[TEXT_OBJ_OUTER_CURLY_BRACKET]  = { text_object_curly_bracket,  OUTER },
-	[TEXT_OBJ_INNER_CURLY_BRACKET]  = { text_object_curly_bracket,  INNER },
-	[TEXT_OBJ_OUTER_ANGLE_BRACKET]  = { text_object_angle_bracket,  OUTER },
-	[TEXT_OBJ_INNER_ANGLE_BRACKET]  = { text_object_angle_bracket,  INNER },
-	[TEXT_OBJ_OUTER_PARANTHESE]     = { text_object_paranthese,     OUTER },
-	[TEXT_OBJ_INNER_PARANTHESE]     = { text_object_paranthese,     INNER },
-	[TEXT_OBJ_OUTER_QUOTE]          = { text_object_quote,          OUTER },
-	[TEXT_OBJ_INNER_QUOTE]          = { text_object_quote,          INNER },
-	[TEXT_OBJ_OUTER_SINGLE_QUOTE]   = { text_object_single_quote,   OUTER },
-	[TEXT_OBJ_INNER_SINGLE_QUOTE]   = { text_object_single_quote,   INNER },
-	[TEXT_OBJ_OUTER_BACKTICK]       = { text_object_backtick,       OUTER },
-	[TEXT_OBJ_INNER_BACKTICK]       = { text_object_backtick,       INNER },
-};
-
-/* if some movements are forced to be linewise, they are translated to text objects */
-static TextObject *moves_linewise[] = {
-	[MOVE_SCREEN_LINE_UP]   = &textobjs[TEXT_OBJ_LINE_UP],
-	[MOVE_SCREEN_LINE_DOWN] = &textobjs[TEXT_OBJ_LINE_DOWN],
-};
-
-/** functions to be called from keybindings */
-/* navigate jumplist either in forward (arg->i>0) or backward (arg->i<0) direction */
-static void jumplist(const Arg *arg);
-static void macro_record(const Arg *arg);
-static void macro_replay(const Arg *arg);
-/* temporarily suspend the editor and return to the shell, type 'fg' to get back */
-static void suspend(const Arg *arg);
-/* switch to mode indicated by arg->i */
-static void switchmode(const Arg *arg);
-/* set mark indicated by arg->i to current cursor position */
-static void mark_set(const Arg *arg);
-/* insert arg->s at the current cursor position */
-static void insert(const Arg *arg);
-/* insert a tab or the needed amount of spaces at the current cursor position */
-static void insert_tab(const Arg *arg);
-/* inserts a newline (either \n or \r\n depending on file type) */
-static void insert_newline(const Arg *arg);
-/* put register content either before (if arg->i < 0) or after (if arg->i > 0)
- * current cursor position */
-static void put(const Arg *arg);
-/* add a new line either before or after the one where the cursor currently is */
-static void openline(const Arg *arg);
-/* join lines from current cursor position to movement indicated by arg */
-static void join(const Arg *arg);
-/* create a new window with the filename arg->s */
-static void winnew(const Arg *arg);
-/* execute arg->s as if it was typed on command prompt */
-static void cmd(const Arg *arg);
-/* perform last action i.e. action_prev again */
-static void repeat(const Arg *arg);
-/* replace character at cursor with one read form keyboard */
-static void replace(const Arg *arg);
-/* adjust action.count by arg->i */
-static void count(const Arg *arg);
-/* move to the action.count-th line or if not given either to the first (arg->i < 0)
- *  or last (arg->i > 0) line of file */
-static void gotoline(const Arg *arg);
-/* force operator to linewise (if arg->b is set) */
-static void linewise(const Arg *arg);
-/* make the current action use the operator indicated by arg->i */
-static void operator(const Arg *arg);
-/* execute operator twice useful for synonyms (e.g. 'cc') */
-static void operator_twice(const Arg *arg);
-/* change case of a file range to upper (arg->i > 0) or lowercase (arg->i < 0) */
-static void changecase(const Arg *arg);
-/* blocks to read a key and performs movement indicated by arg->i which
- * should be one of MOVE_{RIGHT,LEFT}_{TO,TILL} */
-static void movement_key(const Arg *arg);
-/* perform the movement as indicated by arg->i */
-static void movement(const Arg *arg);
-/* let the current operator affect the range indicated by the text object arg->i */
-static void textobj(const Arg *arg);
-/* use register indicated by arg->i for the current operator */
-static void reg(const Arg *arg);
-/* perform a movement to mark arg->i */
-static void mark(const Arg *arg);
-/* perform a movement to the first non-blank on the line pointed by mark arg->i */
-static void mark_line(const Arg *arg);
-/* {un,re}do last action, redraw window */
-static void undo(const Arg *arg);
-static void redo(const Arg *arg);
-/* either part of multiplier or a movement to begin of line */
-static void zero(const Arg *arg);
-/* hange/delete from the current cursor position to the end of
- * movement as indicated by arg->i */
-static void change(const Arg *arg);
-static void delete(const Arg *arg);
-/* perform movement according to arg->i, then switch to insert mode */
-static void insertmode(const Arg *arg);
-/* insert register content indicated by arg->i at current cursor position */
-static void insert_register(const Arg *arg);
-/* show a user prompt to get input with title arg->s */
-static void prompt_search(const Arg *arg);
-static void prompt_cmd(const Arg *arg);
-/* evaluate user input at prompt, perform search or execute a command */
-static void prompt_enter(const Arg *arg);
-/* cycle through past user inputs */
-static void prompt_up(const Arg *arg);
-static void prompt_down(const Arg *arg);
-/* exit command mode if the last char is deleted */
-static void prompt_backspace(const Arg *arg);
-/* blocks to read 3 consecutive digits and inserts the corresponding byte value */
-static void insert_verbatim(const Arg *arg);
-/* scroll window content according to arg->i which can be either PAGE, PAGE_HALF,
- * or an arbitrary number of lines. a multiplier overrides what is given in arg->i.
- * negative values scroll back, positive forward. */
-static void wscroll(const Arg *arg);
-/* similar to scroll, but do only move window content not cursor position */
-static void wslide(const Arg *arg);
-/* call editor function as indicated by arg->f */
-static void call(const Arg *arg);
-/* call window function as indicated by arg->w */
-static void window(const Arg *arg);
-/* quit editor, discard all changes */
-static void quit(const Arg *arg);
-
-/** commands to enter at the ':'-prompt */
-/* set various runtime options */
-static bool cmd_set(Filerange*, const char *argv[]);
-/* goto line indicated by argv[0] */
-static bool cmd_gotoline(Filerange*, const char *argv[]);
-/* for each argument create a new window and open the corresponding file */
-static bool cmd_open(Filerange*, const char *argv[]);
-/* close current window (discard modifications if argv[0] contains '!')
- * and open argv[1], if no argv[1] is given re-read to current file from disk */
-static bool cmd_edit(Filerange*, const char *argv[]);
-/* close the current window, if argv[0] contains a '!' discard modifications */
-static bool cmd_quit(Filerange*, const char *argv[]);
-/* close all windows which show current file. if argv[0] contains a '!' discard modifications */
-static bool cmd_bdelete(Filerange*, const char *argv[]);
-/* close all windows, exit editor, if argv[0] contains a '!' discard modifications */
-static bool cmd_qall(Filerange*, const char *argv[]);
-/* for each argument try to insert the file content at current cursor postion */
-static bool cmd_read(Filerange*, const char *argv[]);
-static bool cmd_substitute(Filerange*, const char *argv[]);
-/* if no argument are given, split the current window horizontally,
- * otherwise open the file */
-static bool cmd_split(Filerange*, const char *argv[]);
-/* if no argument are given, split the current window vertically,
- * otherwise open the file */
-static bool cmd_vsplit(Filerange*, const char *argv[]);
-/* create a new empty window and arrange all windows either horizontally or vertically */
-static bool cmd_new(Filerange*, const char *argv[]);
-static bool cmd_vnew(Filerange*, const char *argv[]);
-/* save the file displayed in the current window and close it */
-static bool cmd_wq(Filerange*, const char *argv[]);
-/* save the file displayed in the current window to the name given.
- * do not change internal filname association. further :w commands
- * without arguments will still write to the old filename */
-static bool cmd_write(Filerange*, const char *argv[]);
-/* save the file displayed in the current window to the name given,
- * associate the new name with the buffer. further :w commands
- * without arguments will write to the new filename */
-static bool cmd_saveas(Filerange*, const char *argv[]);
-
-static void action_reset(Action *a);
-static void switchmode_to(Mode *new_mode);
-
+#include "vis.h"
 #include "config.h"
 
 static Key getkey(void);
diff --git a/vis.h b/vis.h
new file mode 100644
index 0000000..bad4213
--- /dev/null
+++ b/vis.h
_AT_@ -0,0 +1,486 @@
+#ifndef VIS_H
+#define VIS_H
+#include "text-motions.h"
+#include "text-objects.h"
+#include <limits.h>
+typedef union {
+	bool b;
+	int i;
+	const char *s;
+	void (*w)(Win*);    /* generic window commands */
+	void (*f)(Editor*); /* generic editor commands */
+} Arg;
+
+typedef struct {
+	char str[6]; /* UTF8 character or terminal escape code */
+	int code;    /* curses KEY_* constant */
+} Key;
+
+#define MAX_KEYS 2
+typedef Key KeyCombo[MAX_KEYS];
+
+typedef struct {
+	KeyCombo key;
+	void (*func)(const Arg *arg);
+	const Arg arg;
+} KeyBinding;
+
+typedef struct Mode Mode;
+struct Mode {
+	Mode *parent;                       /* if no match is found in this mode, search will continue there */
+	KeyBinding *bindings;               /* NULL terminated array of keybindings for this mode */
+	const char *name;                   /* descriptive, user facing name of the mode */
+	bool isuser;                        /* whether this is a user or internal mode */
+	bool common_prefix;                 /* whether the first key in this mode is always the same */
+	void (*enter)(Mode *old);           /* called right before the mode becomes active */
+	void (*leave)(Mode *new);           /* called right before the mode becomes inactive */
+	bool (*unknown)(KeyCombo);          /* called whenever a key combination is not found in this mode,
+	                                       the return value determines whether parent modes will be searched */
+	void (*input)(const char*, size_t); /* called whenever a key is not found in this mode and all its parent modes */
+	void (*idle)(void);                 /* called whenever a certain idle time i.e. without any user input elapsed */
+	time_t idle_timeout;                /* idle time in seconds after which the registered function will be called */
+	bool visual;                        /* whether text selection is possible in this mode */
+};
+
+typedef struct {
+	char *name;                    /* is used to match against argv[0] to enable this config */
+	Mode *mode;                    /* default mode in which the editor should start in */
+	void (*statusbar)(EditorWin*); /* routine which is called whenever the cursor is moved within a window */
+	bool (*keypress)(Key*);        /* called before any other keybindings are checked,
+	                                * return value decides whether key should be ignored */
+} Config;
+
+typedef struct {
+	int count;        /* how many times should the command be executed? */
+	Register *reg;    /* always non-NULL, set to a default register */
+	Filerange range;  /* which part of the file should be affected by the operator */
+	size_t pos;       /* at which byte from the start of the file should the operation start? */
+	bool linewise;    /* should the changes always affect whole lines? */
+	const Arg *arg;   /* arbitrary arguments */
+} OperatorContext;
+
+typedef struct {
+	void (*func)(OperatorContext*); /* function implementing the operator logic */
+} Operator;
+
+typedef struct {
+	size_t (*cmd)(const Arg*);        /* a custom movement based on user input from vis.c */
+	size_t (*win)(Win*);              /* a movement based on current window content from window.h */
+	size_t (*txt)(Text*, size_t pos); /* a movement form text-motions.h */
+	enum {
+		LINEWISE  = 1 << 0,
+		CHARWISE  = 1 << 1,
+		INCLUSIVE = 1 << 2,
+		EXCLUSIVE = 1 << 3,
+		IDEMPOTENT = 1 << 4,
+		JUMP = 1 << 5,
+	} type;
+	int count;
+} Movement;
+
+typedef struct {
+	Filerange (*range)(Text*, size_t pos); /* a text object from text-objects.h */
+	enum {
+		INNER,
+		OUTER,
+	} type;
+} TextObject;
+
+typedef struct {             /** collects all information until an operator is executed */
+	int count;
+	bool linewise;
+	Operator *op;
+	Movement *movement;
+	TextObject *textobj;
+	Register *reg;
+	MarkIntern mark;
+	Key key;
+	Arg arg;
+} Action;
+
+typedef struct {                         /* command definitions for the ':'-prompt */
+	const char *name;                /* regular expression pattern to match command */
+	bool (*cmd)(Filerange*, const char *argv[]);
+	                                 /* command logic called with a NULL terminated array
+	                                  * of arguments. argv[0] will be the command name,
+	                                  * as matched by the regex. */
+	bool args;                       /* whether argv should be populated with words
+	                                  * separated by spaces. if false, argv[1] will
+	                                  * contain the remaining command line unmodified */
+	regex_t regex;                   /* compiled form of the pattern in 'name' */
+} Command;
+
+/** global variables */
+static volatile bool running = true; /* exit main loop once this becomes false */
+static Editor *vis;         /* global editor instance, keeps track of all windows etc. */
+static Mode *mode;          /* currently active mode, used to search for keybindings */
+static Mode *mode_prev;     /* previsouly active user mode */
+static Mode *mode_before_prompt; /* user mode which was active before entering prompt */
+static Action action;       /* current action which is in progress */
+static Action action_prev;  /* last operator action used by the repeat '.' key */
+static Buffer buffer_repeat;/* repeat last modification i.e. insertion/replacement */
+
+/** operators */
+static void op_change(OperatorContext *c);
+static void op_yank(OperatorContext *c);
+static void op_put(OperatorContext *c);
+static void op_delete(OperatorContext *c);
+static void op_shift_right(OperatorContext *c);
+static void op_shift_left(OperatorContext *c);
+static void op_case_change(OperatorContext *c);
+static void op_join(OperatorContext *c);
+static void op_repeat_insert(OperatorContext *c);
+static void op_repeat_replace(OperatorContext *c);
+
+/* these can be passed as int argument to operator(&(const Arg){ .i = OP_*}) */
+enum {
+	OP_DELETE,
+	OP_CHANGE,
+	OP_YANK,
+	OP_PUT,
+	OP_SHIFT_RIGHT,
+	OP_SHIFT_LEFT,
+	OP_CASE_CHANGE,
+	OP_JOIN,
+	OP_REPEAT_INSERT,
+	OP_REPEAT_REPLACE,
+};
+
+static Operator ops[] = {
+	[OP_DELETE]      = { op_delete      },
+	[OP_CHANGE]      = { op_change      },
+	[OP_YANK]        = { op_yank        },
+	[OP_PUT]         = { op_put         },
+	[OP_SHIFT_RIGHT] = { op_shift_right },
+	[OP_SHIFT_LEFT]  = { op_shift_left  },
+	[OP_CASE_CHANGE] = { op_case_change },
+	[OP_JOIN]          = { op_join          },
+	[OP_REPEAT_INSERT]  = { op_repeat_insert  },
+	[OP_REPEAT_REPLACE] = { op_repeat_replace },
+};
+
+#define PAGE      INT_MAX
+#define PAGE_HALF (INT_MAX-1)
+
+/* these can be passed as int argument to movement(&(const Arg){ .i = MOVE_* }) */
+enum {
+	MOVE_SCREEN_LINE_UP,
+	MOVE_SCREEN_LINE_DOWN,
+	MOVE_SCREEN_LINE_BEGIN,
+	MOVE_SCREEN_LINE_MIDDLE,
+	MOVE_SCREEN_LINE_END,
+	MOVE_LINE_PREV,
+	MOVE_LINE_BEGIN,
+	MOVE_LINE_START,
+	MOVE_LINE_FINISH,
+	MOVE_LINE_LASTCHAR,
+	MOVE_LINE_END,
+	MOVE_LINE_NEXT,
+	MOVE_LINE,
+	MOVE_COLUMN,
+	MOVE_CHAR_PREV,
+	MOVE_CHAR_NEXT,
+	MOVE_WORD_START_NEXT,
+	MOVE_WORD_END_PREV,
+	MOVE_WORD_END_NEXT,
+	MOVE_WORD_START_PREV,
+	MOVE_LONGWORD_START_PREV,
+	MOVE_LONGWORD_START_NEXT,
+	MOVE_LONGWORD_END_PREV,
+	MOVE_LONGWORD_END_NEXT,
+	MOVE_SENTENCE_PREV,
+	MOVE_SENTENCE_NEXT,
+	MOVE_PARAGRAPH_PREV,
+	MOVE_PARAGRAPH_NEXT,
+	MOVE_BRACKET_MATCH,
+	MOVE_LEFT_TO,
+	MOVE_RIGHT_TO,
+	MOVE_LEFT_TILL,
+	MOVE_RIGHT_TILL,
+	MOVE_FILE_BEGIN,
+	MOVE_FILE_END,
+	MOVE_MARK,
+	MOVE_MARK_LINE,
+	MOVE_SEARCH_WORD_FORWARD,
+	MOVE_SEARCH_WORD_BACKWARD,
+	MOVE_SEARCH_FORWARD,
+	MOVE_SEARCH_BACKWARD,
+	MOVE_WINDOW_LINE_TOP,
+	MOVE_WINDOW_LINE_MIDDLE,
+	MOVE_WINDOW_LINE_BOTTOM,
+};
+
+/** movements which can be used besides the one in text-motions.h and window.h */
+
+/* search in forward direction for the word under the cursor */
+static size_t search_word_forward(const Arg *arg);
+/* search in backward direction for the word under the cursor */
+static size_t search_word_backward(const Arg *arg);
+/* search again for the last used search pattern */
+static size_t search_forward(const Arg *arg);
+static size_t search_backward(const Arg *arg);
+/* goto action.mark */
+static size_t mark_goto(const Arg *arg);
+/* goto first non-blank char on line pointed by action.mark */
+static size_t mark_line_goto(const Arg *arg);
+/* goto to next occurence of action.key to the right */
+static size_t to(const Arg *arg);
+/* goto to position before next occurence of action.key to the right */
+static size_t till(const Arg *arg);
+/* goto to next occurence of action.key to the left */
+static size_t to_left(const Arg *arg);
+/* goto to position after next occurence of action.key to the left */
+static size_t till_left(const Arg *arg);
+/* goto line number action.count */
+static size_t line(const Arg *arg);
+/* goto to byte action.count on current line */
+static size_t column(const Arg *arg);
+/* goto the action.count-th line from top of the focused window */
+static size_t window_lines_top(const Arg *arg);
+/* goto the start of middle line of the focused window */
+static size_t window_lines_middle(const Arg *arg);
+/* goto the action.count-th line from bottom of the focused window */
+static size_t window_lines_bottom(const Arg *arg);
+
+static Movement moves[] = {
+	[MOVE_SCREEN_LINE_UP]      = { .win = window_line_up                                       },
+	[MOVE_SCREEN_LINE_DOWN]    = { .win = window_line_down                                     },
+	[MOVE_SCREEN_LINE_BEGIN]   = { .win = window_line_begin,        .type = CHARWISE           },
+	[MOVE_SCREEN_LINE_MIDDLE]  = { .win = window_line_middle,       .type = CHARWISE           },
+	[MOVE_SCREEN_LINE_END]     = { .win = window_line_end,          .type = CHARWISE|INCLUSIVE },
+	[MOVE_LINE_PREV]           = { .txt = text_line_prev,           .type = LINEWISE           },
+	[MOVE_LINE_BEGIN]          = { .txt = text_line_begin,          .type = LINEWISE           },
+	[MOVE_LINE_START]          = { .txt = text_line_start,          .type = LINEWISE           },
+	[MOVE_LINE_FINISH]         = { .txt = text_line_finish,         .type = LINEWISE|INCLUSIVE },
+	[MOVE_LINE_LASTCHAR]       = { .txt = text_line_lastchar,       .type = LINEWISE|INCLUSIVE },
+	[MOVE_LINE_END]            = { .txt = text_line_end,            .type = LINEWISE           },
+	[MOVE_LINE_NEXT]           = { .txt = text_line_next,           .type = LINEWISE           },
+	[MOVE_LINE]                = { .cmd = line,                     .type = LINEWISE|IDEMPOTENT|JUMP},
+	[MOVE_COLUMN]              = { .cmd = column,                   .type = CHARWISE|IDEMPOTENT},
+	[MOVE_CHAR_PREV]           = { .win = window_char_prev                                     },
+	[MOVE_CHAR_NEXT]           = { .win = window_char_next                                     },
+	[MOVE_WORD_START_PREV]     = { .txt = text_word_start_prev,     .type = CHARWISE           },
+	[MOVE_WORD_START_NEXT]     = { .txt = text_word_start_next,     .type = CHARWISE           },
+	[MOVE_WORD_END_PREV]       = { .txt = text_word_end_prev,       .type = CHARWISE|INCLUSIVE },
+	[MOVE_WORD_END_NEXT]       = { .txt = text_word_end_next,       .type = CHARWISE|INCLUSIVE },
+	[MOVE_LONGWORD_START_PREV] = { .txt = text_longword_start_prev, .type = CHARWISE           },
+	[MOVE_LONGWORD_START_NEXT] = { .txt = text_longword_start_next, .type = CHARWISE           },
+	[MOVE_LONGWORD_END_PREV]   = { .txt = text_longword_end_prev,   .type = CHARWISE|INCLUSIVE },
+	[MOVE_LONGWORD_END_NEXT]   = { .txt = text_longword_end_next,   .type = CHARWISE|INCLUSIVE },
+	[MOVE_SENTENCE_PREV]       = { .txt = text_sentence_prev,       .type = LINEWISE           },
+	[MOVE_SENTENCE_NEXT]       = { .txt = text_sentence_next,       .type = LINEWISE           },
+	[MOVE_PARAGRAPH_PREV]      = { .txt = text_paragraph_prev,      .type = LINEWISE|JUMP      },
+	[MOVE_PARAGRAPH_NEXT]      = { .txt = text_paragraph_next,      .type = LINEWISE|JUMP      },
+	[MOVE_BRACKET_MATCH]       = { .txt = text_bracket_match,       .type = LINEWISE|INCLUSIVE|JUMP },
+	[MOVE_FILE_BEGIN]          = { .txt = text_begin,               .type = LINEWISE|JUMP      },
+	[MOVE_FILE_END]            = { .txt = text_end,                 .type = LINEWISE|JUMP      },
+	[MOVE_LEFT_TO]             = { .cmd = to_left,                  .type = LINEWISE           },
+	[MOVE_RIGHT_TO]            = { .cmd = to,                       .type = LINEWISE|INCLUSIVE },
+	[MOVE_LEFT_TILL]           = { .cmd = till_left,                .type = LINEWISE           },
+	[MOVE_RIGHT_TILL]          = { .cmd = till,                     .type = LINEWISE|INCLUSIVE },
+	[MOVE_MARK]                = { .cmd = mark_goto,                .type = LINEWISE|JUMP      },
+	[MOVE_MARK_LINE]           = { .cmd = mark_line_goto,           .type = LINEWISE|JUMP      },
+	[MOVE_SEARCH_WORD_FORWARD] = { .cmd = search_word_forward,      .type = LINEWISE|JUMP      },
+	[MOVE_SEARCH_WORD_BACKWARD]= { .cmd = search_word_backward,     .type = LINEWISE|JUMP      },
+	[MOVE_SEARCH_FORWARD]      = { .cmd = search_forward,           .type = LINEWISE|JUMP      },
+	[MOVE_SEARCH_BACKWARD]     = { .cmd = search_backward,          .type = LINEWISE|JUMP      },
+	[MOVE_WINDOW_LINE_TOP]     = { .cmd = window_lines_top,         .type = LINEWISE|JUMP      },
+	[MOVE_WINDOW_LINE_MIDDLE]  = { .cmd = window_lines_middle,      .type = LINEWISE|JUMP      },
+	[MOVE_WINDOW_LINE_BOTTOM]  = { .cmd = window_lines_bottom,      .type = LINEWISE|JUMP      },
+};
+
+/* these can be passed as int argument to textobj(&(const Arg){ .i = TEXT_OBJ_* }) */
+enum {
+	TEXT_OBJ_INNER_WORD,
+	TEXT_OBJ_OUTER_WORD,
+	TEXT_OBJ_INNER_LONGWORD,
+	TEXT_OBJ_OUTER_LONGWORD,
+	TEXT_OBJ_LINE_UP,
+	TEXT_OBJ_LINE_DOWN,
+	TEXT_OBJ_SENTENCE,
+	TEXT_OBJ_PARAGRAPH,
+	TEXT_OBJ_OUTER_SQUARE_BRACKET,
+	TEXT_OBJ_INNER_SQUARE_BRACKET,
+	TEXT_OBJ_OUTER_CURLY_BRACKET,
+	TEXT_OBJ_INNER_CURLY_BRACKET,
+	TEXT_OBJ_OUTER_ANGLE_BRACKET,
+	TEXT_OBJ_INNER_ANGLE_BRACKET,
+	TEXT_OBJ_OUTER_PARANTHESE,
+	TEXT_OBJ_INNER_PARANTHESE,
+	TEXT_OBJ_OUTER_QUOTE,
+	TEXT_OBJ_INNER_QUOTE,
+	TEXT_OBJ_OUTER_SINGLE_QUOTE,
+	TEXT_OBJ_INNER_SINGLE_QUOTE,
+	TEXT_OBJ_OUTER_BACKTICK,
+	TEXT_OBJ_INNER_BACKTICK,
+};
+
+static TextObject textobjs[] = {
+	[TEXT_OBJ_INNER_WORD]           = { text_object_word                  },
+	[TEXT_OBJ_OUTER_WORD]           = { text_object_word_outer            },
+	[TEXT_OBJ_INNER_LONGWORD]       = { text_object_longword              },
+	[TEXT_OBJ_OUTER_LONGWORD]       = { text_object_longword_outer        },
+	[TEXT_OBJ_LINE_UP]              = { text_object_line                  },
+	[TEXT_OBJ_LINE_DOWN]            = { text_object_line                  },
+	[TEXT_OBJ_SENTENCE]             = { text_object_sentence              },
+	[TEXT_OBJ_PARAGRAPH]            = { text_object_paragraph             },
+	[TEXT_OBJ_OUTER_SQUARE_BRACKET] = { text_object_square_bracket, OUTER },
+	[TEXT_OBJ_INNER_SQUARE_BRACKET] = { text_object_square_bracket, INNER },
+	[TEXT_OBJ_OUTER_CURLY_BRACKET]  = { text_object_curly_bracket,  OUTER },
+	[TEXT_OBJ_INNER_CURLY_BRACKET]  = { text_object_curly_bracket,  INNER },
+	[TEXT_OBJ_OUTER_ANGLE_BRACKET]  = { text_object_angle_bracket,  OUTER },
+	[TEXT_OBJ_INNER_ANGLE_BRACKET]  = { text_object_angle_bracket,  INNER },
+	[TEXT_OBJ_OUTER_PARANTHESE]     = { text_object_paranthese,     OUTER },
+	[TEXT_OBJ_INNER_PARANTHESE]     = { text_object_paranthese,     INNER },
+	[TEXT_OBJ_OUTER_QUOTE]          = { text_object_quote,          OUTER },
+	[TEXT_OBJ_INNER_QUOTE]          = { text_object_quote,          INNER },
+	[TEXT_OBJ_OUTER_SINGLE_QUOTE]   = { text_object_single_quote,   OUTER },
+	[TEXT_OBJ_INNER_SINGLE_QUOTE]   = { text_object_single_quote,   INNER },
+	[TEXT_OBJ_OUTER_BACKTICK]       = { text_object_backtick,       OUTER },
+	[TEXT_OBJ_INNER_BACKTICK]       = { text_object_backtick,       INNER },
+};
+
+/* if some movements are forced to be linewise, they are translated to text objects */
+static TextObject *moves_linewise[] = {
+	[MOVE_SCREEN_LINE_UP]   = &textobjs[TEXT_OBJ_LINE_UP],
+	[MOVE_SCREEN_LINE_DOWN] = &textobjs[TEXT_OBJ_LINE_DOWN],
+};
+
+/** functions to be called from keybindings */
+/* navigate jumplist either in forward (arg->i>0) or backward (arg->i<0) direction */
+static void jumplist(const Arg *arg);
+static void macro_record(const Arg *arg);
+static void macro_replay(const Arg *arg);
+/* temporarily suspend the editor and return to the shell, type 'fg' to get back */
+static void suspend(const Arg *arg);
+/* switch to mode indicated by arg->i */
+static void switchmode(const Arg *arg);
+/* set mark indicated by arg->i to current cursor position */
+static void mark_set(const Arg *arg);
+/* insert arg->s at the current cursor position */
+static void insert(const Arg *arg);
+/* insert a tab or the needed amount of spaces at the current cursor position */
+static void insert_tab(const Arg *arg);
+/* inserts a newline (either \n or \r\n depending on file type) */
+static void insert_newline(const Arg *arg);
+/* put register content either before (if arg->i < 0) or after (if arg->i > 0)
+ * current cursor position */
+static void put(const Arg *arg);
+/* add a new line either before or after the one where the cursor currently is */
+static void openline(const Arg *arg);
+/* join lines from current cursor position to movement indicated by arg */
+static void join(const Arg *arg);
+/* create a new window with the filename arg->s */
+static void winnew(const Arg *arg);
+/* execute arg->s as if it was typed on command prompt */
+static void cmd(const Arg *arg);
+/* perform last action i.e. action_prev again */
+static void repeat(const Arg *arg);
+/* replace character at cursor with one read form keyboard */
+static void replace(const Arg *arg);
+/* adjust action.count by arg->i */
+static void count(const Arg *arg);
+/* move to the action.count-th line or if not given either to the first (arg->i < 0)
+ *  or last (arg->i > 0) line of file */
+static void gotoline(const Arg *arg);
+/* force operator to linewise (if arg->b is set) */
+static void linewise(const Arg *arg);
+/* make the current action use the operator indicated by arg->i */
+static void operator(const Arg *arg);
+/* execute operator twice useful for synonyms (e.g. 'cc') */
+static void operator_twice(const Arg *arg);
+/* change case of a file range to upper (arg->i > 0) or lowercase (arg->i < 0) */
+static void changecase(const Arg *arg);
+/* blocks to read a key and performs movement indicated by arg->i which
+ * should be one of MOVE_{RIGHT,LEFT}_{TO,TILL} */
+static void movement_key(const Arg *arg);
+/* perform the movement as indicated by arg->i */
+static void movement(const Arg *arg);
+/* let the current operator affect the range indicated by the text object arg->i */
+static void textobj(const Arg *arg);
+/* use register indicated by arg->i for the current operator */
+static void reg(const Arg *arg);
+/* perform a movement to mark arg->i */
+static void mark(const Arg *arg);
+/* perform a movement to the first non-blank on the line pointed by mark arg->i */
+static void mark_line(const Arg *arg);
+/* {un,re}do last action, redraw window */
+static void undo(const Arg *arg);
+static void redo(const Arg *arg);
+/* either part of multiplier or a movement to begin of line */
+static void zero(const Arg *arg);
+/* hange/delete from the current cursor position to the end of
+ * movement as indicated by arg->i */
+static void change(const Arg *arg);
+static void delete(const Arg *arg);
+/* perform movement according to arg->i, then switch to insert mode */
+static void insertmode(const Arg *arg);
+/* insert register content indicated by arg->i at current cursor position */
+static void insert_register(const Arg *arg);
+/* show a user prompt to get input with title arg->s */
+static void prompt_search(const Arg *arg);
+static void prompt_cmd(const Arg *arg);
+/* evaluate user input at prompt, perform search or execute a command */
+static void prompt_enter(const Arg *arg);
+/* cycle through past user inputs */
+static void prompt_up(const Arg *arg);
+static void prompt_down(const Arg *arg);
+/* exit command mode if the last char is deleted */
+static void prompt_backspace(const Arg *arg);
+/* blocks to read 3 consecutive digits and inserts the corresponding byte value */
+static void insert_verbatim(const Arg *arg);
+/* scroll window content according to arg->i which can be either PAGE, PAGE_HALF,
+ * or an arbitrary number of lines. a multiplier overrides what is given in arg->i.
+ * negative values scroll back, positive forward. */
+static void wscroll(const Arg *arg);
+/* similar to scroll, but do only move window content not cursor position */
+static void wslide(const Arg *arg);
+/* call editor function as indicated by arg->f */
+static void call(const Arg *arg);
+/* call window function as indicated by arg->w */
+static void window(const Arg *arg);
+/* quit editor, discard all changes */
+static void quit(const Arg *arg);
+
+/** commands to enter at the ':'-prompt */
+/* set various runtime options */
+static bool cmd_set(Filerange*, const char *argv[]);
+/* goto line indicated by argv[0] */
+static bool cmd_gotoline(Filerange*, const char *argv[]);
+/* for each argument create a new window and open the corresponding file */
+static bool cmd_open(Filerange*, const char *argv[]);
+/* close current window (discard modifications if argv[0] contains '!')
+ * and open argv[1], if no argv[1] is given re-read to current file from disk */
+static bool cmd_edit(Filerange*, const char *argv[]);
+/* close the current window, if argv[0] contains a '!' discard modifications */
+static bool cmd_quit(Filerange*, const char *argv[]);
+/* close all windows which show current file. if argv[0] contains a '!' discard modifications */
+static bool cmd_bdelete(Filerange*, const char *argv[]);
+/* close all windows, exit editor, if argv[0] contains a '!' discard modifications */
+static bool cmd_qall(Filerange*, const char *argv[]);
+/* for each argument try to insert the file content at current cursor postion */
+static bool cmd_read(Filerange*, const char *argv[]);
+static bool cmd_substitute(Filerange*, const char *argv[]);
+/* if no argument are given, split the current window horizontally,
+ * otherwise open the file */
+static bool cmd_split(Filerange*, const char *argv[]);
+/* if no argument are given, split the current window vertically,
+ * otherwise open the file */
+static bool cmd_vsplit(Filerange*, const char *argv[]);
+/* create a new empty window and arrange all windows either horizontally or vertically */
+static bool cmd_new(Filerange*, const char *argv[]);
+static bool cmd_vnew(Filerange*, const char *argv[]);
+/* save the file displayed in the current window and close it */
+static bool cmd_wq(Filerange*, const char *argv[]);
+/* save the file displayed in the current window to the name given.
+ * do not change internal filname association. further :w commands
+ * without arguments will still write to the old filename */
+static bool cmd_write(Filerange*, const char *argv[]);
+/* save the file displayed in the current window to the name given,
+ * associate the new name with the buffer. further :w commands
+ * without arguments will write to the new filename */
+static bool cmd_saveas(Filerange*, const char *argv[]);
+
+static void action_reset(Action *a);
+static void switchmode_to(Mode *new_mode);
+#endif
-- 
2.2.1
Received on Sat Jan 03 2015 - 22:41:19 CET

This archive was generated by hypermail 2.3.0 : Sat Jan 03 2015 - 22:48:07 CET