diff options
Diffstat (limited to 'vis.h')
| -rw-r--r-- | vis.h | 240 |
1 files changed, 234 insertions, 6 deletions
@@ -1,13 +1,101 @@ #ifndef VIS_H #define VIS_H +#include <signal.h> +#include <stddef.h> +#include <stdbool.h> +#include <setjmp.h> + +typedef struct Vis Vis; +typedef struct File File; +typedef struct Win Win; + #include "ui.h" -#include "editor.h" +#include "view.h" +#include "register.h" +#include "macro.h" +#include "syntax.h" +#include "ring-buffer.h" +#include "map.h" +#include "text-regex.h" + + +typedef union { + bool b; + int i; + const char *s; + void (*w)(View*); /* generic window commands */ + void (*f)(Vis*); /* generic editor commands */ +} Arg; + +typedef struct { + const char *name; + const char *help; + 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; + +} KeyAction; + +typedef struct { + const char *key; + KeyAction *action; + const char *alias; +} KeyBinding; + -typedef Editor Vis; Vis *vis_new(Ui*); -#define vis_free editor_free +void vis_free(Vis*); +void vis_resize(Vis*); +void vis_draw(Vis*); +void vis_update(Vis*); +void vis_suspend(Vis*); + +/* load a set of syntax highlighting definitions which will be associated + * to the underlying window based on the file type loaded. + * + * The parameter `syntaxes' has to point to a NULL terminated array. + */ +bool vis_syntax_load(Vis*, Syntax *syntaxes); +void vis_syntax_unload(Vis*); + +/* creates a new window, and loads the given file. if filename is NULL + * an unamed / empty buffer is created. If the given file is already opened + * in another window, share the underlying text that is changes will be + * visible in both windows */ +bool vis_window_new(Vis*, const char *filename); +/* reload the file currently displayed in the window from disk */ +bool vis_window_reload(Win*); +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*); +/* 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); +/* 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 + * which the call site has to free. */ +char *vis_prompt_get(Vis*); +/* replace the current command line content with the one given */ +void vis_prompt_set(Vis*, const char *line); + +/* display a message to the user */ +void vis_info_show(Vis*, const char *msg, ...); +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); void vis_run(Vis*, int argc, char *argv[]); void vis_die(Vis*, const char *msg, ...); @@ -29,6 +117,10 @@ 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); + +bool vis_action_register(Vis*, KeyAction*); enum VisOperator { OP_DELETE, @@ -162,15 +254,45 @@ bool vis_macro_record_stop(Vis*); bool vis_macro_replay(Vis*, enum VisMacro); enum VisMark { - /* TODO: temporary */ + 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, }; void vis_mark_set(Vis*, enum VisMark mark, size_t pos); enum VisRegister { - /* TODO: temporary */ - VIS_REGISTER_INVALID = REG_LAST, + 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, }; void vis_register_set(Vis*, enum VisRegister); @@ -186,4 +308,110 @@ const char *vis_keys(Vis*, const char *input); bool vis_signal_handler(Vis*, int signum, const siginfo_t *siginfo, const void *context); +/* TODO: temporary */ +typedef struct Operator Operator; +typedef struct Movement Movement; +typedef struct TextObject TextObject; + +typedef struct { /** collects all information until an operator is executed */ + int count; + enum VisMotionType type; + const Operator *op; + const Movement *movement; + const TextObject *textobj; + Register *reg; + enum VisMark mark; + Arg arg; +} Action; + +/* 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 + * is not found in the current mode. hence the modes form a tree which is + * searched from the current mode up towards the root mode until a valid binding + * is found. + * + * if no binding is found, mode->input(...) is called and the user entered + * keys are passed as argument. this is used to change the document content. + */ +typedef struct Mode Mode; +struct Mode { + Mode *parent; /* if no match is found in this mode, search will continue there */ + Map *bindings; + KeyBinding *default_bindings; + const char *name; /* descriptive, user facing name of the mode */ + const char *status; /* name displayed in the window status bar */ + const char *help; /* short description used by :help */ + bool isuser; /* whether this is a user or internal mode */ + void (*enter)(Vis*, Mode *old); /* called right before the mode becomes active */ + void (*leave)(Vis*, Mode *new); /* called right before the mode becomes inactive */ + void (*input)(Vis*, const char*, size_t); /* called whenever a key is not found in this mode and all its parent modes */ + void (*idle)(Vis*); /* 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 */ +}; + +struct File { + Text *text; + const char *name; + volatile sig_atomic_t truncated; + bool is_stdin; + struct stat stat; + int refcount; + Mark marks[VIS_MARK_INVALID]; + File *next, *prev; +}; + +typedef struct { + time_t state; /* state of the text, used to invalidate change list */ + size_t index; /* #number of changes */ + size_t pos; /* where the current change occured */ +} ChangeList; + +struct Win { + Vis *editor; /* editor instance to which this window belongs */ + UiWin *ui; + File *file; /* file being displayed in this window */ + View *view; /* currently displayed part of underlying text */ + ViewEvent events; + RingBuffer *jumplist; /* LRU jump management */ + ChangeList changelist; /* state for iterating through least recently changes */ + Win *prev, *next; /* neighbouring windows */ +}; + +struct Vis { + Ui *ui; + File *files; + 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 */ + Macro macros[VIS_MACRO_INVALID]; /* recorded macros */ + Macro *recording, *last_recording;/* currently and least recently recorded macro */ + Win *prompt; /* 1-line height window to get user input */ + Win *prompt_window; /* window which was focused before prompt was shown */ + char prompt_type; /* command ':' or search '/','?' prompt */ + Regex *search_pattern; /* last used search pattern */ + char search_char[8]; /* last used character to search for via 'f', 'F', 't', 'T' */ + int last_totill; /* last to/till movement used for ';' and ',' */ + int tabwidth; /* how many spaces should be used to display a tab */ + bool expandtab; /* whether typed tabs should be converted to spaces */ + bool autoindent; /* whether indentation should be copied from previous line on newline */ + Map *cmds; /* ":"-commands, used for unique prefix queries */ + Map *options; /* ":set"-options */ + Buffer buffer_repeat; /* holds data to repeat last insertion/replacement */ + Buffer input_queue; /* holds pending input keys */ + + Action action; /* current action which is in progress */ + Action action_prev; /* last operator action used by the repeat '.' key */ + Mode *mode; /* currently active mode, used to search for keybindings */ + Mode *mode_prev; /* previsouly active user mode */ + Mode *mode_before_prompt; /* user mode which was active before entering prompt */ + volatile bool running; /* exit main loop once this becomes false */ + volatile sig_atomic_t cancel_filter; /* abort external command */ + volatile sig_atomic_t sigbus; + sigjmp_buf sigbus_jmpbuf; + Map *actions; /* built in special editor keys / commands */ +}; + #endif |
