aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c6
-rw-r--r--ui-curses.c1
-rw-r--r--ui.h1
-rw-r--r--vis-core.h3
-rw-r--r--vis-modes.c12
-rw-r--r--vis.c19
-rw-r--r--vis.h208
7 files changed, 151 insertions, 99 deletions
diff --git a/main.c b/main.c
index 9d6cd10..21cc04e 100644
--- a/main.c
+++ b/main.c
@@ -1194,7 +1194,7 @@ static const char *cursors_remove(Vis *vis, const char *keys, const Arg *arg) {
static const char *replace(Vis *vis, const char *keys, const Arg *arg) {
if (!keys[0])
return NULL;
- const char *next = vis_key_next(vis, keys);
+ const char *next = vis_keys_next(vis, keys);
if (!next)
return NULL;
size_t len = next - keys;
@@ -1243,7 +1243,7 @@ static const char *movement_key(Vis *vis, const char *keys, const Arg *arg) {
if (!keys[0])
return NULL;
char key[32];
- const char *next = vis_key_next(vis, keys);
+ const char *next = vis_keys_next(vis, keys);
strncpy(key, keys, next - keys + 1);
key[sizeof(key)-1] = '\0';
vis_motion(vis, arg->i, key);
@@ -1274,7 +1274,7 @@ static const char *selection_restore(Vis *vis, const char *keys, const Arg *arg)
}
static const char *key2register(Vis *vis, const char *keys, enum VisRegister *reg) {
- *reg = VIS_REGISTER_INVALID;
+ *reg = VIS_REG_INVALID;
if (!keys[0])
return NULL;
if (keys[0] >= 'a' && keys[0] <= 'z')
diff --git a/ui-curses.c b/ui-curses.c
index ea4aac7..7c1f5b3 100644
--- a/ui-curses.c
+++ b/ui-curses.c
@@ -1024,7 +1024,6 @@ Ui *ui_curses_new(void) {
.free = ui_curses_free,
.termkey_get = ui_termkey_get,
.suspend = ui_suspend,
- .resume = ui_resize,
.resize = ui_resize,
.update = ui_update,
.window_new = ui_window_new,
diff --git a/ui.h b/ui.h
index 0549db3..8c94d51 100644
--- a/ui.h
+++ b/ui.h
@@ -47,7 +47,6 @@ struct Ui {
void (*draw)(Ui*);
void (*update)(Ui*);
void (*suspend)(Ui*);
- void (*resume)(Ui*);
const char* (*getkey)(Ui*);
bool (*haskey)(Ui*);
void (*terminal_save)(Ui*);
diff --git a/vis-core.h b/vis-core.h
index 549b817..4321a80 100644
--- a/vis-core.h
+++ b/vis-core.h
@@ -1,6 +1,7 @@
#ifndef VIS_CORE_H
#define VIS_CORE_H
+#include <setjmp.h>
#include "vis.h"
#include "text.h"
#include "text-regex.h"
@@ -123,7 +124,7 @@ struct Vis {
Win *windows; /* list of windows */
Win *win; /* currently active window */
Syntax *syntaxes; /* NULL terminated array of syntax definitions */
- Register registers[VIS_REGISTER_INVALID]; /* register used for copy and paste */
+ Register registers[VIS_REG_INVALID]; /* register used for copy and paste */
Macro macros[VIS_MACRO_INVALID]; /* recorded macros */
Macro *recording, *last_recording;/* currently and least recently recorded macro */
Macro *macro_operator;
diff --git a/vis-modes.c b/vis-modes.c
index 7d2f7e5..b53aeb7 100644
--- a/vis-modes.c
+++ b/vis-modes.c
@@ -20,13 +20,13 @@ void mode_set(Vis *vis, Mode *new_mode) {
vis->win->ui->draw_status(vis->win->ui);
}
-static bool mode_map(Mode *mode, const char *name, KeyBinding *binding) {
- return map_put(mode->bindings, name, binding);
+static bool mode_map(Mode *mode, const char *key, KeyBinding *binding) {
+ return map_put(mode->bindings, key, binding);
}
-bool vis_mode_map(Vis *vis, enum VisMode modeid, const char *name, KeyBinding *binding) {
+bool vis_mode_map(Vis *vis, enum VisMode modeid, const char *key, KeyBinding *binding) {
Mode *mode = mode_get(vis, modeid);
- return mode && map_put(mode->bindings, name, binding);
+ return mode && mode_map(mode, key, binding);
}
bool vis_mode_bindings(Vis *vis, enum VisMode modeid, KeyBinding **bindings) {
@@ -41,9 +41,9 @@ bool vis_mode_bindings(Vis *vis, enum VisMode modeid, KeyBinding **bindings) {
return success;
}
-bool vis_mode_unmap(Vis *vis, enum VisMode modeid, const char *name) {
+bool vis_mode_unmap(Vis *vis, enum VisMode modeid, const char *key) {
Mode *mode = mode_get(vis, modeid);
- return mode && map_delete(mode->bindings, name);
+ return mode && map_delete(mode->bindings, key);
}
/** mode switching event handlers */
diff --git a/vis.c b/vis.c
index 82532b6..be8f727 100644
--- a/vis.c
+++ b/vis.c
@@ -225,10 +225,6 @@ bool vis_window_split(Win *original) {
return true;
}
-void vis_resize(Vis *vis) {
- vis->ui->resize(vis->ui);
-}
-
void vis_window_next(Vis *vis) {
Win *sel = vis->win;
if (!sel)
@@ -535,7 +531,7 @@ static void action_do(Vis *vis, Action *a) {
next = view_cursors_next(cursor);
size_t pos = view_cursors_pos(cursor);
- Register *reg = a->reg ? a->reg : &vis->registers[REG_DEFAULT];
+ Register *reg = a->reg ? a->reg : &vis->registers[VIS_REG_DEFAULT];
if (multiple_cursors)
reg = view_cursors_register(cursor);
@@ -694,7 +690,7 @@ void vis_die(Vis *vis, const char *msg, ...) {
va_end(ap);
}
-const char *vis_key_next(Vis *vis, const char *keys) {
+const char *vis_keys_next(Vis *vis, const char *keys) {
TermKeyKey key;
TermKey *termkey = vis->ui->termkey_get(vis->ui);
const char *next = NULL;
@@ -727,7 +723,7 @@ static const char *vis_keys_raw(Vis *vis, Buffer *buf, const char *input) {
while (cur && *cur) {
- if (!(end = (char*)vis_key_next(vis, cur)))
+ if (!(end = (char*)vis_keys_next(vis, cur)))
goto err; // XXX: can't parse key this should never happen
char tmp = *end;
@@ -801,7 +797,7 @@ bool vis_keys_inject(Vis *vis, const char *pos, const char *input) {
return true;
}
-const char *vis_keys(Vis *vis, const char *input) {
+const char *vis_keys_push(Vis *vis, const char *input) {
if (!input)
return NULL;
@@ -958,7 +954,7 @@ int vis_run(Vis *vis, int argc, char *argv[]) {
const char *key;
while ((key = getkey(vis)))
- vis_keys(vis, key);
+ vis_keys_push(vis, key);
if (vis->mode->idle)
timeout = &idle;
@@ -1087,7 +1083,7 @@ bool vis_motion(Vis *vis, enum VisMotion motion, ...) {
case MOVE_MARK_LINE:
{
int mark = va_arg(ap, int);
- if (MARK_a <= mark && mark < VIS_MARK_INVALID)
+ if (VIS_MARK_a <= mark && mark < VIS_MARK_INVALID)
vis->action.mark = mark;
else
goto err;
@@ -1221,7 +1217,8 @@ int vis_count_get(Vis *vis) {
}
void vis_count_set(Vis *vis, int count) {
- vis->action.count = count;
+ if (count >= 0)
+ vis->action.count = count;
}
void vis_register_set(Vis *vis, enum VisRegister reg) {
diff --git a/vis.h b/vis.h
index 8e69806..01c1358 100644
--- a/vis.h
+++ b/vis.h
@@ -4,7 +4,6 @@
#include <signal.h>
#include <stddef.h>
#include <stdbool.h>
-#include <setjmp.h>
typedef struct Vis Vis;
typedef struct File File;
@@ -15,35 +14,41 @@ typedef struct Win Win;
#include "register.h"
#include "syntax.h"
-typedef union {
+typedef union { /* various types of arguments passed to key action functions */
bool b;
int i;
const char *s;
- void (*w)(View*); /* generic window commands */
- void (*f)(Vis*); /* generic editor commands */
+ void (*w)(View*);
+ void (*f)(Vis*);
} Arg;
-typedef struct {
- const char *name;
- const char *help;
+typedef struct { /* a KeyAction can be bound to a key binding */
+ const char *name; /* aliases can refer to this action by means of a pseudo key <name> */
+ const char *help; /* short (one line) human readable description, displayed by :help */
+ /* action handling function, keys refers to the next characters found in the input queue
+ * (an empty string "" indicates an empty queue). The return value of func has to point to
+ * the first non consumed key. Returning NULL indicates that not enough keys were available
+ * to complete the action. In this case the function will be called again when more input
+ * becomes available */
const char* (*func)(Vis*, const char *keys, const Arg*);
- /* returns a pointer to the first not consumed character in keys
- * or NULL if not enough input was available to complete the command */
- const Arg arg;
-
+ const Arg arg; /* additional arguments which will be passed as to func */
} KeyAction;
-typedef struct {
- const char *key;
- KeyAction *action;
- const char *alias;
+typedef struct { /* a key binding either refers to an action or an alias */
+ const char *key; /* symbolic key to trigger this binding */
+ KeyAction *action; /* action to launch upon triggering this binding */
+ const char *alias; /* replaces key with alias in the input queue */
} KeyBinding;
+/* creates a new editor instance using the specified user interface */
Vis *vis_new(Ui*);
+/* frees all resources associated with this editor instance, terminates ui */
void vis_free(Vis*);
-void vis_resize(Vis*);
+/* instructs the user interface to draw to an internal buffer */
void vis_draw(Vis*);
+/* flushes the state of the internal buffer to the output device */
void vis_update(Vis*);
+/* temporarily supsend the editor process, resumes upon receiving SIGCONT */
void vis_suspend(Vis*);
/* load a set of syntax highlighting definitions which will be associated
@@ -61,18 +66,20 @@ void vis_syntax_unload(Vis*);
bool vis_window_new(Vis*, const char *filename);
/* reload the file currently displayed in the window from disk */
bool vis_window_reload(Win*);
+/* close window, redraw user interface */
void vis_window_close(Win*);
/* split the given window. changes to the displayed text will be reflected
* in both windows */
bool vis_window_split(Win*);
+/* change file name associated with this window, affects syntax coloring */
void vis_window_name(Win*, const char *filename);
/* focus the next / previous window */
void vis_window_next(Vis*);
void vis_window_prev(Vis*);
/* display a user prompt with a certain title and default text */
void vis_prompt_show(Vis*, const char *title, const char *text);
-/* TODO: bad abstraction */
-void vis_prompt_enter(Vis*);
+/* execute current prompt content as command, as if the user had pressed <Enter> */
+void vis_prompt_enter(Vis*); /* TODO: bad abstraction */
/* hide the user prompt if it is currently shown */
void vis_prompt_hide(Vis*);
/* return the content of the command prompt in a malloc(3)-ed string
@@ -87,18 +94,29 @@ void vis_info_hide(Vis*);
/* these function operate on the currently focused window but make sure
* that all windows which show the affected region are redrawn too. */
-void vis_insert_key(Vis*, const char *data, size_t len);
-void vis_replace_key(Vis*, const char *data, size_t len);
void vis_insert(Vis*, size_t pos, const char *data, size_t len);
void vis_delete(Vis*, size_t pos, size_t len);
void vis_replace(Vis*, size_t pos, const char *data, size_t len);
+/* these functions perform their operation at the current cursor position(s) */
+void vis_insert_key(Vis*, const char *data, size_t len);
+void vis_replace_key(Vis*, const char *data, size_t len);
+/* inserts a tab (peforms tab expansion based on current editing settings),
+ * at all current cursor positions */
void vis_insert_tab(Vis*);
+/* inserts a new line sequence (depending on the file type this might be \n or
+ * \r\n) at all current cursor positions */
void vis_insert_nl(Vis*);
+/* processes the given command line arguments and starts the main loop, won't
+ * return until editing session is terminated */
int vis_run(Vis*, int argc, char *argv[]);
+/* terminate editing session, given status will be the return value of vis_run */
void vis_exit(Vis*, int status);
+/* emergency exit, print given message, perform minimal ui cleanup and exit process */
void vis_die(Vis*, const char *msg, ...);
+/* user facing modes are: NORMAL, VISUAL, VISUAL_LINE, PROMPT, INSERT, REPLACE.
+ * the others should be considered as implementation details (TODO: do not expose them?) */
enum VisMode {
VIS_MODE_BASIC,
VIS_MODE_MOVE,
@@ -116,18 +134,20 @@ enum VisMode {
};
void vis_mode_switch(Vis*, enum VisMode);
-bool vis_mode_map(Vis*, enum VisMode, const char *name, KeyBinding*);
-bool vis_mode_unmap(Vis*, enum VisMode, const char *name);
+/* in the specified mode: map a given key to a binding (binding->key is ignored),
+ * fails if key is already mapped */
+bool vis_mode_map(Vis*, enum VisMode, const char *key, KeyBinding*);
+/* in the specified mode: unmap a given key, fails if the key is not currently mapped */
+bool vis_mode_unmap(Vis*, enum VisMode, const char *key);
+/* map a NULL-terminated array of key bindings, return value indicates whether *all*
+ * bindings were succesfully performed */
bool vis_mode_bindings(Vis*, enum VisMode, KeyBinding **bindings);
+/* get the current mode's status line indicator */
const char *vis_mode_status(Vis*);
-
+/* associates the special pseudo key <keyaction->name> with the given key action.
+ * after successfull registration the pseudo key can be used key binding aliases */
bool vis_action_register(Vis*, KeyAction*);
-/* TODO: overhaul repeatable infrastructure:
- * - put is not really an operator, but should still be repeatable
- * and respect count
- " - review OP_REPEAT_{REPLACE,INSERT}
- */
enum VisOperator {
OP_DELETE,
OP_CHANGE,
@@ -140,7 +160,7 @@ enum VisOperator {
OP_REPLACE,
OP_CURSOR_SOL,
OP_CASE_SWAP,
- OP_INVALID,
+ OP_INVALID, /* denotes the end of the "real" operators */
/* pseudo operators: keep them at the end to save space in array definition */
OP_CASE_LOWER,
OP_CASE_UPPER,
@@ -150,6 +170,13 @@ enum VisOperator {
OP_PUT_BEFORE_END,
};
+/* set operator to execute, has immediate effect if
+ * - a visual mode is active
+ * - the same operator was already set (range will be the current line)
+ * otherwise waits until a range is determinded i.e.
+ * - a motion is provided (see vis_motion)
+ * - a text object is provided (vis_textobject)
+ */
bool vis_operator(Vis*, enum VisOperator);
enum VisMotion {
@@ -210,7 +237,7 @@ enum VisMotion {
MOVE_JUMPLIST_NEXT,
MOVE_JUMPLIST_PREV,
MOVE_NOP,
- MOVE_INVALID,
+ MOVE_INVALID, /* denotes the end of the "real" motions */
/* pseudo motions: keep them at the end to save space in array definition */
MOVE_TOTILL_REPEAT,
MOVE_TOTILL_REVERSE,
@@ -218,8 +245,25 @@ enum VisMotion {
MOVE_SEARCH_BACKWARD,
};
+/* set motion to perform, the following take an additional argument:
+ *
+ * - MOVE_SEARCH_FORWARD and MOVE_SEARCH_BACKWARD
+ *
+ * expect the search pattern as const char *
+ *
+ * - MOVE_{LEFT,RIGHT}_{TO,TILL}
+ *
+ * expect the character to search for as const char *
+ *
+ * - MOVE_MARK and MOVE_MARK_LINE
+ *
+ * expect a valid enum VisMark
+ */
bool vis_motion(Vis*, enum VisMotion, ...);
+/* a count of zero indicates that so far no special count was given.
+ * operators, motions and text object will always perform their function
+ * as if a minimal count of 1 was given */
int vis_count_get(Vis*);
void vis_count_set(Vis*, int count);
@@ -227,7 +271,7 @@ enum VisMotionType {
VIS_MOTIONTYPE_LINEWISE = 1 << 0,
VIS_MOTIONTYPE_CHARWISE = 1 << 1,
};
-
+/* force certain motion to behave in line or character wise mode */
void vis_motion_type(Vis *vis, enum VisMotionType);
enum VisTextObject {
@@ -261,77 +305,89 @@ enum VisTextObject {
void vis_textobject(Vis*, enum VisTextObject);
+/* macro REPEAT and INVALID should be considered as implementation details (TODO: hide them?) */
enum VisMacro {
- /* XXX: TEMPORARY */
- VIS_MACRO_LAST_RECORDED = 26,
- VIS_MACRO_REPEAT,
- VIS_MACRO_OPERATOR,
- VIS_MACRO_INVALID, /* hast to be the last enum member */
+ VIS_MACRO_a, VIS_MACRO_b, VIS_MACRO_c, VIS_MACRO_d, VIS_MACRO_e,
+ VIS_MACRO_f, VIS_MACRO_g, VIS_MACRO_h, VIS_MACRO_i, VIS_MACRO_j,
+ VIS_MACRO_k, VIS_MACRO_l, VIS_MACRO_m, VIS_MACRO_n, VIS_MACRO_o,
+ VIS_MACRO_p, VIS_MACRO_q, VIS_MACRO_r, VIS_MACRO_s, VIS_MACRO_t,
+ VIS_MACRO_u, VIS_MACRO_v, VIS_MACRO_w, VIS_MACRO_x, VIS_MACRO_y,
+ VIS_MACRO_z,
+ VIS_MACRO_OPERATOR, /* records entered keys after an operator */
+ VIS_MACRO_REPEAT, /* copy of the above macro once the recording is finished */
+ VIS_MACRO_INVALID, /* denotes the end of "real" macros */
+ VIS_MACRO_LAST_RECORDED, /* pseudo macro referring to last recorded one */
};
+/* start a macro recording, fails if a recording is already on going */
bool vis_macro_record(Vis*, enum VisMacro);
+/* stop recording, fails if there is nothing to stop */
bool vis_macro_record_stop(Vis*);
+/* check whether a recording is currently on going */
bool vis_macro_recording(Vis*);
+/* replay a macro. a macro currently being recorded can't be replayed */
bool vis_macro_replay(Vis*, enum VisMacro);
enum VisMark {
- MARK_a,
- MARK_b,
- MARK_c,
- MARK_d,
- MARK_e,
- MARK_f,
- MARK_g,
- MARK_h,
- MARK_i,
- MARK_j,
- MARK_k,
- MARK_l,
- MARK_m,
- MARK_n,
- MARK_o,
- MARK_p,
- MARK_q,
- MARK_r,
- MARK_s,
- MARK_t,
- MARK_u,
- MARK_v,
- MARK_w,
- MARK_x,
- MARK_y,
- MARK_z,
- MARK_SELECTION_START,
- MARK_SELECTION_END,
- VIS_MARK_INVALID,
+ VIS_MARK_a, VIS_MARK_b, VIS_MARK_c, VIS_MARK_d, VIS_MARK_e,
+ VIS_MARK_f, VIS_MARK_g, VIS_MARK_h, VIS_MARK_i, VIS_MARK_j,
+ VIS_MARK_k, VIS_MARK_l, VIS_MARK_m, VIS_MARK_n, VIS_MARK_o,
+ VIS_MARK_p, VIS_MARK_q, VIS_MARK_r, VIS_MARK_s, VIS_MARK_t,
+ VIS_MARK_u, VIS_MARK_v, VIS_MARK_w, VIS_MARK_x, VIS_MARK_y,
+ VIS_MARK_z,
+ MARK_SELECTION_START, /* '< */
+ MARK_SELECTION_END, /* '> */
+ VIS_MARK_INVALID, /* has to be the last enum member */
};
void vis_mark_set(Vis*, enum VisMark mark, size_t pos);
enum VisRegister {
- REG_a, REG_b, REG_c, REG_d, REG_e, REG_f, REG_g, REG_h, REG_i,
- REG_j, REG_k, REG_l, REG_m, REG_n, REG_o, REG_p, REG_q, REG_r,
- REG_s, REG_t, REG_u, REG_v, REG_w, REG_x, REG_y, REG_z,
- REG_DEFAULT,
- VIS_REGISTER_INVALID,
+ VIS_REG_a, VIS_REG_b, VIS_REG_c, VIS_REG_d, VIS_REG_e,
+ VIS_REG_f, VIS_REG_g, VIS_REG_h, VIS_REG_i, VIS_REG_j,
+ VIS_REG_k, VIS_REG_l, VIS_REG_m, VIS_REG_n, VIS_REG_o,
+ VIS_REG_p, VIS_REG_q, VIS_REG_r, VIS_REG_s, VIS_REG_t,
+ VIS_REG_u, VIS_REG_v, VIS_REG_w, VIS_REG_x, VIS_REG_y,
+ VIS_REG_z,
+ VIS_REG_DEFAULT, /* used when no other register is specified */
+ VIS_REG_INVALID, /* has to be the last enum member */
};
+/* set the register to use, if none is given the DEFAULT register is used */
void vis_register_set(Vis*, enum VisRegister);
Register *vis_register_get(Vis*, enum VisRegister);
+/* repeat last operator, possibly with a new count if one was provided in the meantime */
void vis_repeat(Vis*);
+
+/* cancel pending operator, reset count, motion, text object, register etc. */
void vis_cancel(Vis*);
-/* execute a :-command (call without without leading ':') */
+/* execute a :-command (including an optinal range specifier) */
bool vis_cmd(Vis*, const char *cmd);
-const char *vis_key_next(Vis*, const char *keys);
-const char *vis_keys(Vis*, const char *input);
+/* given the start of a key, returns a pointer to the start of the one immediately
+ * following as will be processed by the input system. skips over special keys
+ * such as <Enter> as well as pseudo keys registered via vis_action_register. */
+const char *vis_keys_next(Vis*, const char *keys);
+/* vis operates as a finite state machine (FSM), feeding keys from an input
+ * queue (or a previously recorded macro) to key handling functions (see struct
+ * KeyAction) which consume the input.
+ *
+ * this functions pushes/appends further input to the end of the input queue
+ * and immediately tries to interpret them */
+const char *vis_keys_push(Vis*, const char *input);
+/* inject new input keys at the position indicated by a pointer to a valid, not
+ * yet consumed key from the current input queue. does not try to interpret the
+ * new queue content.
+ *
+ * typically only called from within key handling functions */
bool vis_keys_inject(Vis*, const char *pos, const char *input);
+/* inform vis that a signal occured, the return value indicates whether the signal
+ * was handled by vis */
+bool vis_signal_handler(Vis*, int signum, const siginfo_t *siginfo, const void *context);
-bool vis_signal_handler(Vis*, int signum, const siginfo_t *siginfo,
- const void *context);
-
+/* TODO: expose proper API to iterate through files etc */
Text *vis_text(Vis*);
View *vis_view(Vis*);
Text *vis_file_text(File*);