aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/index.rst1
-rw-r--r--doc/vis.rst187
-rw-r--r--main.c2
-rw-r--r--vis-cmds.c4
-rw-r--r--vis-motions.c3
-rw-r--r--vis-text-objects.c3
-rw-r--r--vis.c9
-rw-r--r--vis.h698
8 files changed, 731 insertions, 176 deletions
diff --git a/doc/index.rst b/doc/index.rst
index c7f8b10..ef53ca8 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -4,6 +4,7 @@ Vis Editor API Documenation
.. toctree::
:maxdepth: 2
+ vis
text
buffer
array
diff --git a/doc/vis.rst b/doc/vis.rst
new file mode 100644
index 0000000..1774552
--- /dev/null
+++ b/doc/vis.rst
@@ -0,0 +1,187 @@
+Vis
+===
+
+The core Vis API.
+
+Lifecycle
+---------
+
+.. doxygengroup:: vis_lifecycle
+ :content-only:
+
+Draw
+----
+
+.. doxygengroup:: vis_draw
+ :content-only:
+
+Windows
+-------
+
+.. doxygengroup:: vis_windows
+ :content-only:
+
+Input
+-----
+
+The editor core processes input through a sequences of symbolic keys:
+
+ * Special keys such as ``<Enter>``, ``<Tab>`` or ``<Backspace>`` as reported by
+ `termkey_strfkey <http://www.leonerd.org.uk/code/libtermkey/doc/termkey_strfkey.3.html>`_.
+
+ .. note:: The prefixes ``C-``, ``S-`` and ``M-`` are used to denote the ``Ctrl``,
+ ``Shift`` and ``Alt`` modifiers, respectively.
+
+ * Key action names as registered with `vis_action_register`.
+
+ .. note:: By convention they are prefixed with ``vis-`` as in ``<vis-nop>``.
+
+ * Regular UTF-8 encoded input.
+
+.. note:: An exhaustive list of the first two types is displayed in the ``:help`` output.
+
+.. doxygengroup:: vis_keys
+ :content-only:
+
+Key Map
+-------
+
+The key map is used to translate keys in non-input modes, *before* any key
+bindings are evaluated. It is intended to facilitate usage of non-latin keyboard
+layouts.
+
+.. doxygengroup:: vis_keymap
+ :content-only:
+
+Key Binding
+-----------
+
+Each mode has a set of key bindings. A key binding maps a key to either
+another key (referred to as an alias) or a key action (implementing an
+editor operation).
+
+If a key sequence is ambiguous (i.e. it is a prefix of multiple mappings)
+more input is awaited, until a unique mapping can be resolved.
+
+.. warning:: Key aliases are always evaluated recursively.
+
+.. doxygengroup:: vis_keybind
+ :content-only:
+
+Key Action
+----------
+
+A key action is invoked by a key binding and implements a certain editor function.
+
+The editor operates like a finite state machine with key sequences as
+transition labels. Once a prefix of the input queue uniquely refers to a
+key action, it is invoked with the remainder of the input queue passed as argument.
+
+.. note:: A triggered key action currently does not know through which key binding
+ it was invoked. TODO: change that?
+
+.. doxygengroup:: vis_action
+ :content-only:
+
+Modes
+-----
+
+A mode defines *enter*, *leave* and *idle* actions and captures a set of
+key bindings.
+
+Modes are hierarchical, key bindings are searched recursively towards
+the top of the hierarchy stopping at the first match.
+
+.. doxygenenum:: VisMode
+.. doxygengroup:: vis_modes
+ :content-only:
+
+Count
+-----
+
+Dictates how many times a motion or text object is evaluated. If none
+is specified, a minimal count of 1 is assumed.
+
+.. doxygengroup:: vis_count
+ :content-only:
+
+Operators
+---------
+
+.. doxygengroup:: vis_operators
+ :content-only:
+
+Motions
+-------
+
+.. doxygengroup:: vis_motions
+ :content-only:
+
+Text Objects
+------------
+
+.. doxygengroup:: vis_textobjs
+ :content-only:
+
+Marks
+-----
+
+Marks keep track of a given text position.
+
+.. note:: Marks are currently file local.
+
+.. doxygengroup:: vis_marks
+ :content-only:
+
+Registers
+---------
+
+.. doxygengroup:: vis_registers
+ :content-only:
+
+Macros
+------
+
+Macros are a sequence of keys stored in a Register which can be reprocessed
+as if entered by the user.
+
+.. warning:: Macro support is currently half-baked. If you do something stupid
+ (e.g. use mutually recursive macros), you will likely encounter
+ stack overflows.
+
+.. doxygengroup:: vis_macros
+ :content-only:
+
+Commands
+--------
+
+.. doxygengroup:: vis_cmds
+ :content-only:
+
+Options
+-------
+
+.. doxygengroup:: vis_options
+ :content-only:
+
+Modification
+------------
+
+These function operate on the currently focused window but ensure that
+all windows which show the affected region are redrawn too.
+
+.. doxygengroup:: vis_changes
+ :content-only:
+
+Interaction
+-----------
+
+.. doxygengroup:: vis_info
+ :content-only:
+
+Miscellaneous
+-------------
+
+.. doxygengroup:: vis_misc
+ :content-only:
+
diff --git a/main.c b/main.c
index 5c9cc9f..3fec735 100644
--- a/main.c
+++ b/main.c
@@ -2167,7 +2167,7 @@ int main(int argc, char *argv[]) {
vis_prompt_cmd(vis, cmd);
}
- int status = vis_run(vis, argc, argv);
+ int status = vis_run(vis);
vis_free(vis);
return status;
}
diff --git a/vis-cmds.c b/vis-cmds.c
index 093c694..ec70231 100644
--- a/vis-cmds.c
+++ b/vis-cmds.c
@@ -6,7 +6,7 @@
// FIXME: avoid this redirection?
typedef struct {
CommandDef def;
- CmdFunc *func;
+ VisCommandFunction *func;
void *data;
} CmdUser;
@@ -18,7 +18,7 @@ static void cmdfree(CmdUser *cmd) {
free(cmd);
}
-bool vis_cmd_register(Vis *vis, const char *name, const char *help, void *data, CmdFunc *func) {
+bool vis_cmd_register(Vis *vis, const char *name, const char *help, void *data, VisCommandFunction *func) {
if (!name)
return false;
if (!vis->usercmds && !(vis->usercmds = map_new()))
diff --git a/vis-motions.c b/vis-motions.c
index 92ab995..9917ce5 100644
--- a/vis-motions.c
+++ b/vis-motions.c
@@ -293,8 +293,7 @@ void vis_motion_type(Vis *vis, enum VisMotionType type) {
vis->action.type = type;
}
-int vis_motion_register(Vis *vis, enum VisMotionType type, void *data,
- size_t (*motion)(Vis*, Win*, void*, size_t pos)) {
+int vis_motion_register(Vis *vis, enum VisMotionType type, void *data, VisMotionFunction *motion) {
Movement *move = calloc(1, sizeof *move);
if (!move)
diff --git a/vis-text-objects.c b/vis-text-objects.c
index 467c101..446ac6d 100644
--- a/vis-text-objects.c
+++ b/vis-text-objects.c
@@ -2,8 +2,7 @@
#include "text-objects.h"
#include "util.h"
-int vis_textobject_register(Vis *vis, int type, void *data,
- Filerange (*textobject)(Vis*, Win*, void*, size_t pos)) {
+int vis_textobject_register(Vis *vis, int type, void *data, VisTextObjectFunction *textobject) {
TextObject *obj = calloc(1, sizeof *obj);
if (!obj)
diff --git a/vis.c b/vis.c
index cfbd291..ba10fc3 100644
--- a/vis.c
+++ b/vis.c
@@ -558,6 +558,10 @@ void vis_suspend(Vis *vis) {
vis->ui->suspend(vis->ui);
}
+void vis_resume(Vis *vis) {
+ vis->ui->resume(vis->ui);
+}
+
bool vis_window_new(Vis *vis, const char *filename) {
File *file = file_new(vis, filename);
if (!file)
@@ -1298,7 +1302,7 @@ bool vis_signal_handler(Vis *vis, int signum, const siginfo_t *siginfo, const vo
return false;
}
-int vis_run(Vis *vis, int argc, char *argv[]) {
+int vis_run(Vis *vis) {
if (!vis->windows)
return EXIT_SUCCESS;
if (vis->exit_status != -1)
@@ -1347,9 +1351,10 @@ int vis_run(Vis *vis, int argc, char *argv[]) {
}
if (vis->resume) {
- vis->ui->resume(vis->ui);
+ vis_resume(vis);
vis->resume = false;
}
+
if (vis->need_resize) {
vis->ui->resize(vis->ui);
vis->need_resize = false;
diff --git a/vis.h b/vis.h
index 62b207a..60cbb12 100644
--- a/vis.h
+++ b/vis.h
@@ -39,6 +39,9 @@ typedef struct Win Win;
/* maximum bytes needed for string representation of a (pseudo) key */
#define VIS_KEY_LENGTH_MAX 64
+/**
+ * Editor event handlers.
+ */
typedef struct {
void (*init)(Vis*);
void (*start)(Vis*);
@@ -55,7 +58,8 @@ typedef struct {
void (*win_status)(Vis*, Win*);
} VisEvent;
-typedef union { /* various types of arguments passed to key action functions */
+/** Union used to pass arguments to key action functions. */
+typedef union {
bool b;
int i;
const char *s;
@@ -64,145 +68,298 @@ typedef union { /* various types of arguments passed to key action functions */
void (*f)(Vis*);
} Arg;
-/* 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 */
+/**
+ * Key action handling function.
+ * @param keys Input queue content *after* the binding which invoked this function.
+ * @rst
+ * .. note:: An empty string ``""`` indicates that no further input is available.
+ * @endrst
+ * @return Pointer to first non-cosumed key.
+ * @rst
+ * .. warning:: Must be in range ``[keys, keys+strlen(keys)]`` or ``NULL`` to
+ * indicate that not enough input was available. In the latter case
+ * the function will be called again once more input has been received.
+ * @endrst
+ * @ingroup vis_action
+ */
typedef const char *KeyActionFunction(Vis*, const char *keys, const Arg*);
-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> */
- VIS_HELP_DECL(const char *help;) /* short (one line) human readable description, displayed by :help */
- KeyActionFunction *func; /* action implementation */
- Arg arg; /* additional arguments which will be passed as to func */
+/** Key action definition. */
+typedef struct {
+ const char *name; /**< Name of a pseudo key ``<name>`` which can be used in mappings. */
+ VIS_HELP_DECL(const char *help;) /**< One line human readable description, displayed by ``:help``. */
+ KeyActionFunction *func; /**< Key action implementation function. */
+ Arg arg; /**< Options passes as last argument to ``func``. */
} KeyAction;
-typedef struct { /* a key binding either refers to an action or an alias */
- const char *key; /* symbolic key to trigger this binding */
- const KeyAction *action; /* action to launch upon triggering this binding */
- const char *alias; /* replaces key with alias in the input queue */
+/**
+ * A key binding, refers to an action or an alias
+ * @rst
+ * .. note:: Either ``action`` or ``alias`` must be ``NULL``.
+ * @endrst
+ */
+typedef struct {
+ const char *key; /**< Symbolic key to trigger this binding. */
+ const KeyAction *action; /**< Action to invoke when triggering this binding. */
+ const char *alias; /**< Replaces ``key`` with ``alias`` at the front of the input queue. */
} KeyBinding;
-/* creates a new editor instance using the specified user interface */
+/**
+ * @defgroup vis_lifecycle
+ * @{
+ */
+/** Create a new editor instance using the given user interface and event handlers. */
Vis *vis_new(Ui*, VisEvent*);
-/* frees all resources associated with this editor instance, terminates ui */
+/** Free all resources associated with this editor instance, terminates UI. */
void vis_free(Vis*);
-/* instructs the user interface to draw to an internal buffer */
+/**
+ * Enter main loop, start processing user input.
+ * @return The editor exit status code.
+ */
+int vis_run(Vis*);
+/** Terminate editing session, the 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.
+ * @rst
+ * .. note:: This function does not return.
+ * @endrst
+ */
+void vis_die(Vis*, const char *msg, ...) __attribute__((noreturn,format(printf, 2, 3)));
+
+/**
+ * Temporarily supsend the editor process.
+ * @rst
+ * .. note:: This function will generate a ``SIGTSTP`` signal.
+ * @endrst
+ **/
+void vis_suspend(Vis*);
+/**
+ * Resume editor process.
+ * @rst
+ * .. note:: This function is usually called in response to a ``SIGCONT`` signal.
+ * @endrst
+ */
+void vis_resume(Vis*);
+/**
+ * Inform the editor core that a signal occured.
+ * @return Whether the signal was handled.
+ * @rst
+ * .. note:: Being designed as a library the editor core does *not* register any
+ * signal handlers on its own.
+ * .. note:: The remaining arguments match the prototype of ``sa_sigaction`` as
+ * specified in `sigaction(2)`.
+ * @endrst
+ */
+bool vis_signal_handler(Vis*, int signum, const siginfo_t *siginfo, const void *context);
+/**
+ * @}
+ * @defgroup vis_draw
+ * @{
+ */
+/** Draw user interface. */
void vis_draw(Vis*);
+/** Completely redraw user interface. */
void vis_redraw(Vis*);
-/* flushes the state of the internal buffer to the output device */
+/** Blit user interface state to output device. */
void vis_update(Vis*);
-/* temporarily supsend the editor process, resumes upon receiving SIGCONT */
-void vis_suspend(Vis*);
-void vis_resume(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 */
+/**
+ * @}
+ * @defgroup vis_windows
+ * @{
+ */
+/**
+ * Create a new window and load the given file.
+ * @param filename If ``NULL`` a unamed, empty buffer is created.
+ * @rst
+ * .. note:: If the given file name is already opened in another window,
+ * the underlying File object is shared.
+ * .. warning:: This duplication detection is currently based on normalized,
+ * absolute file names. TODO: compare inodes instead.
+ * @endrst
+ */
bool vis_window_new(Vis*, const char *filename);
-/* Creates a new window and underlying file object associated with the
- * given output file descriptor. No data is read from `fd`, but write
- * commands without an explicit filename will instead write to the file
- * descriptor */
+/**
+ * Create a new window associated with a file descriptor.
+ * @rst
+ * .. note:: No data is read from `fd`, but write commands without an
+ * explicit filename will instead write to the file descriptor.
+ * @endrst
+ */
bool vis_window_new_fd(Vis*, int fd);
-/* reload the file currently displayed in the window from disk */
+/** Reload the file currently displayed in the window from disk. */
bool vis_window_reload(Win*);
-/* check whether closing the window would loose unsaved changes */
+/** Check whether closing the window would loose unsaved changes. */
bool vis_window_closable(Win*);
-/* close window, redraw user interface */
+/** 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 */
+/** Split the window, shares the underlying file object. */
bool vis_window_split(Win*);
-/* change status message of this window */
+/** Change status message of this window. */
void vis_window_status(Win*, const char *status);
void vis_window_draw(Win*);
void vis_window_invalidate(Win*);
-/* focus the next / previous window */
+/** Focus next window. */
void vis_window_next(Vis*);
+/** Focus previous window. */
void vis_window_prev(Vis*);
-/* change currently focused window, receiving user input */
+/** Change currently focused window, receiving user input. */
void vis_window_focus(Win*);
-/* swap location of two windows */
+/** Swap location of two windows. */
void vis_window_swap(Win*, Win*);
-
+/** Query window dimension. */
int vis_window_width_get(const Win*);
+/** Query window dimension. */
int vis_window_height_get(const Win*);
-
-/* take an undo snaphost to which we can later revert to */
-void vis_file_snapshot(Vis*, File*);
-
-/* display a user prompt with a certain title and default text */
+/**
+ * @}
+ * @defgroup vis_info
+ * @{
+ */
+/**
+ * Display a user prompt with a certain title.
+ * @rst
+ * .. note:: The prompt is currently implemented as a single line height window.
+ * @endrst
+ */
void vis_prompt_show(Vis*, const char *title);
-/* display a one line message to the user, will be hidden upon keypress */
+/**
+ * Display a single line message.
+ * @rst
+ * .. note:: The message will automatically be hidden upon next input.
+ * @endrst
+ */
void vis_info_show(Vis*, const char *msg, ...) __attribute__((format(printf, 2, 3)));
+/** Hide informational message. */
void vis_info_hide(Vis*);
-/* display an arbitrary long message in a special window/file */
+/** Display arbitrary long message in a dedicated window. */
void vis_message_show(Vis*, const char *msg);
+/** Close message window. */
void vis_message_hide(Vis*);
-
-/* these function operate on the currently focused window but make sure
- * that all windows which show the affected region are redrawn too. */
+/**
+ * @}
+ * @defgroup vis_changes
+ * @{
+ */
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) */
+/** Perform insertion at all cursor positions. */
void vis_insert_key(Vis*, const char *data, size_t len);
+/**
+ * Perform character subsitution at all cursor positions.
+ * @rst
+ * .. note:: Does not replace new line characters.
+ * @endrst
+ */
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 */
+/**
+ * Insert a tab at all cursor positions.
+ * @rst
+ * .. note:: Performs tab expansion according to current settings.
+ * @endrst
+ */
void vis_insert_tab(Vis*);
-/* inserts a \n character at every cursor position */
+/**
+ * Inserts a new line character at every cursor position.
+ * @rst
+ * .. note:: Performs auto indentation according to current settings.
+ * @endrst
+ */
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, ...) __attribute__((noreturn,format(printf, 2, 3)));
-
-KeyBinding *vis_binding_new(Vis*);
-void vis_binding_free(Vis*, KeyBinding*);
-
+/** @} */
+/** Mode specifiers. */
enum VisMode {
VIS_MODE_NORMAL,
VIS_MODE_OPERATOR_PENDING,
VIS_MODE_VISUAL,
- VIS_MODE_VISUAL_LINE,
+ VIS_MODE_VISUAL_LINE, /**< Sub mode of `VIS_MODE_VISUAL`. */
VIS_MODE_INSERT,
- VIS_MODE_REPLACE,
+ VIS_MODE_REPLACE, /**< Sub mode of `VIS_MODE_INSERT`. */
VIS_MODE_INVALID,
};
+/**
+ * @defgroup vis_modes
+ * @{
+ */
+/**
+ * Switch mode.
+ * @rst
+ * .. note:: Will first trigger the leave event of the currently active
+ * mode, followed by an enter event of the new mode.
+ * No events are emitted, if the specified mode is already active.
+ * @endrst
+ */
void vis_mode_switch(Vis*, enum VisMode);
+/** Get currently active mode. */
enum VisMode vis_mode_get(Vis*);
+/** Translate human readable mode name to constant. */
enum VisMode vis_mode_from(Vis*, const char *name);
-/* In the specified mode: map a given key to a binding (binding->key is ignored).
- * Fails if a prefix of `key' is already mapped and `force' is false. Otherwise
- * all such prefixes are unmapped. */
+
+/**
+ * @}
+ * @defgroup vis_keybind
+ * @{
+ */
+KeyBinding *vis_binding_new(Vis*);
+void vis_binding_free(Vis*, KeyBinding*);
+
+/**
+ * Set up a key binding.
+ * @param force Whether an existing mapping should be discarded.
+ * @param key The symbolic key to map.
+ * @param binding The binding to map.
+ * @rst
+ * .. note:: ``binding->key`` is always ignored in favor of ``key``.
+ * @endrst
+ */
bool vis_mode_map(Vis*, enum VisMode, bool force, const char *key, const KeyBinding*);
+/** Analogous to `vis_mode_map`, but window specific. */
bool vis_window_mode_map(Win*, enum VisMode, bool force, const char *key, const KeyBinding*);
-/* in the specified mode: unmap a given key, fails if the key is not currently mapped */
+/** Unmap a symbolic key in a given mode. */
bool vis_mode_unmap(Vis*, enum VisMode, const char *key);
+/** Analogous to `vis_mode_unmap`, but window specific. */
bool vis_window_mode_unmap(Win*, enum VisMode, const char *key);
-
+/**
+ * @}
+ * @defgroup vis_action
+ * @{
+ */
+/**
+ * Create new key action.
+ * @param name The name to be used as symbolic key when registering.
+ * @param help Optional single line help text.
+ * @param func The function implementing the key action logic.
+ * @param arg Argument passed to function.
+ */
KeyAction *vis_action_new(Vis*, const char *name, const char *help, KeyActionFunction*, Arg);
void vis_action_free(Vis*, KeyAction*);
-/* associates the special pseudo key <keyaction->name> with the given key action.
- * after successfull registration the pseudo key can be used key binding aliases */
+/**
+ * Register key action.
+ * @rst
+ * .. note:: Makes the key action available under the pseudo key name specified
+ * in ``keyaction->name``.
+ * @endrst
+ */
bool vis_action_register(Vis*, const KeyAction*);
-/* add a key mapping which is applied for all modes except insert/replace
- * before any key bindings are evaluated */
+
+/**
+ * @}
+ * @defgroup vis_keymap
+ * @{
+ */
+
+/** Add a key translation. */
bool vis_keymap_add(Vis*, const char *key, const char *mapping);
-/* disable the keymap for the next key press */
+/** Temporarily disable the keymap for the next key press. */
void vis_keymap_disable(Vis*);
+/** @} */
+/** Operator specifiers. */
enum VisOperator {
VIS_OP_DELETE,
VIS_OP_CHANGE,
@@ -227,26 +384,57 @@ enum VisOperator {
VIS_OP_LAST, /* has to be last enum member */
};
-/* 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)
+/**
+ * @defgroup vis_operators
+ * @{
+ */
+typedef struct OperatorContext OperatorContext;
+
+/**
+ * An operator performs a certain function on a given text range.
+ * @rst
+ * .. note:: The operator must return the new cursor position or ``EPOS`` if
+ * the cursor should be disposed.
+ * .. note:: The last used operator can be repeated using `vis_repeat`.
+ * @endrst
+ */
+typedef size_t (VisOperatorFunction)(Vis*, Text*, OperatorContext*);
+
+/**
+ * Register an operator.
+ * @return Operator ID. Negative values indicate an error, positive ones can be
+ * used with `vis_operator`.
+ */
+int vis_operator_register(Vis*, VisOperatorFunction*, void *context);
+
+/**
+ * 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).
*
- * the expected varying arguments are as follows:
+ * Otherwise the operator will be executed on the range determinded by:
+ * - A motion (see `vis_motion`).
+ * - A text object (`vis_textobject`).
*
- * - VIS_OP_FILTER a char pointer referring to the command to run
- * - VIS_OP_JOIN a char pointer referring to the text to insert between lines
- * - VIS_OP_MODESWITCH a enum VisMode constant indicating the mode to switch to
- * - VIS_OP_REPLACE a char pointer reffering to the replacement character
+ * The expected varying arguments are:
+ *
+ * - `VIS_OP_FILTER` a char pointer referring to the command to run.
+ * - `VIS_OP_JOIN` a char pointer referring to the text to insert between lines.
+ * - `VIS_OP_MODESWITCH` an ``enum VisMode`` indicating the mode to switch to.
+ * - `VIS_OP_REPLACE` a char pointer reffering to the replacement character.
*/
bool vis_operator(Vis*, enum VisOperator, ...);
-typedef struct OperatorContext OperatorContext;
-typedef size_t (VisOperatorFunction)(Vis*, Text*, OperatorContext*);
-int vis_operator_register(Vis*, VisOperatorFunction*, void *context);
+/** 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*);
+/** @} */
+/** Motion specifiers. */
enum VisMotion {
VIS_MOVE_LINE_DOWN,
VIS_MOVE_LINE_UP,
@@ -328,28 +516,65 @@ enum VisMotion {
VIS_MOVE_LAST, /* denotes the end of all motions */
};
-/* set motion to perform, the following take an additional argument:
+/**
+ * @defgroup vis_motions
+ * @{
+ */
+/**
+ * Set motion to perform.
+ *
+ * The following motions take an additional argument:
*
- * - VIS_MOVE_SEARCH_FORWARD and VIS_MOVE_SEARCH_BACKWARD
+ * - `VIS_MOVE_SEARCH_FORWARD` and `VIS_MOVE_SEARCH_BACKWARD`
*
- * expect the search pattern as const char *
+ * The search pattern as ``const char *``.
*
- * - VIS_MOVE_{LEFT,RIGHT}_{TO,TILL}
+ * - ``VIS_MOVE_{LEFT,RIGHT}_{TO,TILL}``
*
- * expect the character to search for as const char *
+ * The character to search for as ``const char *``.
*
- * - VIS_MOVE_MARK and VIS_MOVE_MARK_LINE
+ * - `VIS_MOVE_MARK` and `VIS_MOVE_MARK_LINE`
*
- * expect a valid enum VisMark
+ * A valid ``enum VisMark``.
*/
bool vis_motion(Vis*, enum VisMotion, ...);
-/* If no count is explicitly specified, operators, motions and
- * text object will always perform their function as if a minimal
- * count of 1 was given */
+enum VisMotionType {
+ VIS_MOTIONTYPE_LINEWISE = 1 << 0,
+ VIS_MOTIONTYPE_CHARWISE = 1 << 1,
+};
+
+/** Force currently specified motion to behave in line or character wise mode. */
+void vis_motion_type(Vis *vis, enum VisMotionType);
+
+/**
+ * Motions take a starting position and transform it to an end position.
+ * @rst
+ * .. note:: Should a motion not be possible, the original position must be returned.
+ * TODO: we might want to change that to ``EPOS``?
+ * @endrst
+ */
+typedef size_t (VisMotionFunction)(Vis*, Win*, void *context, size_t pos);
+
+/**
+ * Register a motion function.
+ * @return Motion ID. Negative values indicate an error, positive ones can be
+ * used with `vis_motion`.
+ */
+int vis_motion_register(Vis*, enum VisMotionType, void *context, VisMotionFunction*);
+
+/**
+ * @}
+ * @defgroup vis_count
+ * @{
+ */
+/** No count was specified. */
#define VIS_COUNT_UNKNOWN (-1)
+/** Get count, might return `VIS_COUNT_UNKNOWN`. */
int vis_count_get(Vis*);
+/** Get count, if none was specified, return ``def``. */
int vis_count_get_default(Vis*, int def);
+/** Set a count. */
void vis_count_set(Vis*, int count);
typedef struct {
@@ -358,23 +583,22 @@ typedef struct {
int count;
} VisCountIterator;
+/** Get iterator initialized with current count or ``def`` if not specified. */
VisCountIterator vis_count_iterator_get(Vis*, int def);
+/** Get iterator initialized with a count value. */
VisCountIterator vis_count_iterator_init(Vis*, int count);
+/**
+ * Increment iterator counter.
+ * @return Whether iteration should continue.
+ * @rst
+ * .. note:: Terminates iteration if the edtior was
+ * `interrupted <vis_interrupt>`_ in the meantime.
+ * @endrst
+ */
bool vis_count_iterator_next(VisCountIterator*);
-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);
-
-/* register a motion function, if positive the return value can be used
- * as an id for the vis_motion funntion. A negative return value indicates
- * an error */
-int vis_motion_register(Vis*, enum VisMotionType, void *data,
- size_t (*motion)(Vis*, Win*, void*, size_t pos));
-
+/** @} */
+/** Text object specifier. */
enum VisTextObject {
VIS_TEXTOBJECT_INNER_WORD,
VIS_TEXTOBJECT_OUTER_WORD,
@@ -408,14 +632,32 @@ enum VisTextObject {
VIS_TEXTOBJECT_INVALID,
};
-bool vis_textobject(Vis*, enum VisTextObject);
+/**
+ * @defgroup vis_textobjs
+ * @{
+ */
+
+/**
+ * Text objects take a starting position and return a text range.
+ * @rst
+ * .. note:: The originating position does not necessarily have to be contained in
+ * the resulting range.
+ * @endrst
+ */
+typedef Filerange (VisTextObjectFunction)(Vis*, Win*, void *context, size_t pos);
-/* register a new text object, if successful the returned id is positive
- * and can be used as argument for the vis_textobject function. */
-int vis_textobject_register(Vis*, int type, void *data,
- Filerange (*textobject)(Vis*, Win*, void*, size_t pos));
+/**
+ * Register a new text object.
+ * @return Text object ID. Negative values indicate an error, positive ones can be
+ * used with `vis_textobject`.
+ */
+int vis_textobject_register(Vis*, int type, void *data, VisTextObjectFunction*);
+/** Set text object to use. */
+bool vis_textobject(Vis*, enum VisTextObject);
+/** @} */
+/** Mark specifiers. */
enum VisMark {
VIS_MARK_SELECTION_START, /* '< */
VIS_MARK_SELECTION_END, /* '> */
@@ -428,9 +670,23 @@ enum VisMark {
VIS_MARK_INVALID, /* has to be the last enum member */
};
+/**
+ * @}
+ * @defgroup vis_marks
+ * @{
+ */
+/** Translate single character mark name to corresponding constant. */
enum VisMark vis_mark_from(Vis*, char mark);
+/**
+ * Set a mark.
+ * @rst
+ * .. note:: The same semantics as for `text_mark_set` apply.
+ * @endrst
+ */
void vis_mark_set(Vis*, enum VisMark mark, size_t pos);
+/** @} */
+/** Register specifiers. */
enum VisRegister {
VIS_REG_DEFAULT, /* used when no other register is specified */
VIS_REG_ZERO, /* yank register */
@@ -469,41 +725,82 @@ enum VisRegister {
VIS_MACRO_LAST_RECORDED, /* pseudo macro referring to last recorded one */
};
+/**
+ * @defgroup vis_registers
+ * @{
+ */
+/** Translate single character register name to corresponding constant. */
enum VisRegister vis_register_from(Vis*, char reg);
-/* set the register to use, if none is given the DEFAULT register is used */
+/**
+ * Specify register to use.
+ * @rst
+ * .. note:: If none is specified `VIS_REG_DEFAULT` will be used.
+ * @endrst
+ */
void vis_register(Vis*, enum VisRegister);
-/* get register content */
+/** Get register content. */
const char *vis_register_get(Vis*, enum VisRegister, size_t *len);
const char *vis_register_slot_get(Vis*, enum VisRegister, size_t slot, size_t *len);
+/** Set register content. */
bool vis_register_put(Vis*, enum VisRegister, const char *data, size_t len);
bool vis_register_slot_put(Vis*, enum VisRegister, size_t slot, const char *data, size_t len);
-
-/* start a macro recording, fails if a recording is already on going */
+/**
+ * @}
+ * @defgroup vis_macros
+ * @{
+ */
+/**
+ * Start recording a macro.
+ * @rst
+ * .. note:: Fails if a recording is already ongoing.
+ * @endrst
+ */
bool vis_macro_record(Vis*, enum VisRegister);
-/* stop recording, fails if there is nothing to stop */
+/** Stop recording, fails if there is nothing to stop. */
bool vis_macro_record_stop(Vis*);
-/* check whether a recording is currently on going */
+/** Check whether a recording is currently ongoing. */
bool vis_macro_recording(Vis*);
-/* replay a macro. a macro currently being recorded can't be replayed */
+/**
+ * Replay a macro.
+ * @rst
+ * .. note:: A macro currently being recorded can not be replayed.
+ * @endrst
+ */
bool vis_macro_replay(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*);
+/**
+ * @}
+ * @defgroup vis_cmds
+ * @{
+ */
-/* execute a :-command (including an optinal range specifier) */
+/** Execute a ``:``-command. */
bool vis_cmd(Vis*, const char *cmd);
-/* type of user defined function which can be registered */
-typedef bool (CmdFunc)(Vis*, Win*, void *data, bool force,
+/** Command handler function. */
+typedef bool (VisCommandFunction)(Vis*, Win*, void *data, bool force,
const char *argv[], Cursor*, Filerange*);
-/* the function will be invoked whenever a command which matches a
- * unique prefix of the given name is executed */
-bool vis_cmd_register(Vis*, const char *name, const char *help, void *data, CmdFunc*);
+/**
+ * Register new ``:``-command.
+ * @param name The command name.
+ * @param help Optional single line help text.
+ * @param context User supplied context pointer passed to the handler function.
+ * @param func The function implementing the command logic.
+ * @rst
+ * .. note:: Any unique prefix of the command name will invoke the command.
+ * @endrst
+ */
+bool vis_cmd_register(Vis*, const char *name, const char *help, void *context, VisCommandFunction*);
+
+/** Unregister ``:``-command. */
bool vis_cmd_unregister(Vis*, const char *name);
+/**
+ * @}
+ * @defgroup vis_options
+ * @{
+ */
+/** Option properties. */
enum VisOption {
VIS_OPTION_TYPE_BOOL = 1 << 0,
VIS_OPTION_TYPE_STRING = 1 << 1,
@@ -512,62 +809,129 @@ enum VisOption {
VIS_OPTION_NEED_WINDOW = 1 << 4,
};
+/**
+ * Option handler function.
+ * @param win The window to which option should apply, might be ``NULL``.
+ * @param context User provided context pointer as given to `vis_option_register`.
+ * @param force Whether the option was specfied with a bang ``!``.
+ * @param name Name of option which was set.
+ * @param arg The new option value.
+ */
typedef bool (VisOptionFunction)(Vis*, Win*, void *context, bool toggle,
enum VisOption, const char *name, Arg *value);
+
+/**
+ * Register a new ``:set`` option.
+ * @param names A ``NULL`` terminated array of option names.
+ * @param option Option properties.
+ * @param func The function handling the option.
+ * @param context User supplied context pointer passed to the handler function.
+ * @param help Optional single line help text.
+ * @rst
+ * .. note:: Fails if any of the given option names is already registered.
+ * @endrst
+ */
bool vis_option_register(Vis*, const char *names[], enum VisOption,
VisOptionFunction*, void *context, const char *help);
+/**
+ * Unregister an existing ``:set`` option.
+ * @rst
+ * .. note:: Also unregisters all aliases as given to `vis_option_register`.
+ * @endrst
+ */
bool vis_option_unregister(Vis*, const char *name);
-/* execute any kind (:,?,/) of prompt command */
+/** Execute any kind (``:``, ``?``, ``/``) of prompt command */
bool vis_prompt_cmd(Vis*, const char *cmd);
-/* pipe a given file range to an external process
+/**
+ * Pipe a given file range to an external process.
*
- * if the range is invalid 'interactive' mode is enabled, meaning that
+ * If the range is invalid 'interactive' mode is enabled, meaning that
* stdin and stderr are passed through the underlying command, stdout
* points to vis' stderr.
*
- * if argv contains only one non-NULL element the command is executed using
- * /bin/sh -c (i.e. argument expansion is performed by the shell). In contrast
- * if argv contains more than one non-NULL element execvp(argv[0], argv); will
- * be used.
+ * If ``argv`` contains only one non-NULL element the command is executed
+ * through an intermediate shell (using ``/bin/sh -c argv[0]``) that is
+ * argument expansion is performed by the shell. Otherwise the argument
+ * list will be passed unmodified to ``execvp(argv[0], argv)``.
+ *
+ * If the ``read_stdout`` and ``read_stderr`` callbacks are non-NULL they
+ * will be invoked when output from the forked process is available.
*
- * if read_std{out,err} are non-NULL they will be called when output from
- * the forked process is available.
+ * @rst
+ * .. warning:: The editor core is blocked until this function returns.
+ * @endrst
+ *
+ * @return The exit status of the forked process.
*/
int vis_pipe(Vis*, File*, Filerange*, const char *argv[],
void *stdout_context, ssize_t (*read_stdout)(void *stdout_context, char *data, size_t len),
void *stderr_context, ssize_t (*read_stderr)(void *stderr_context, char *data, size_t len));
-/* pipe a range to an external application, return its exit status and store
- * everything that is written to stdout/stderr in the gitven char pointers
- * which have to be free(3)-ed by the caller */
+/**
+ * Pipe a Filerange to an external process, return its exit status and capture
+ * everything that is written to stdout/stderr.
+ * @param argv Argument list, must be ``NULL`` terminated.
+ * @param out Data written to ``stdout``, will be ``NUL`` terminated.
+ * @param err Data written to ``stderr``, will be ``NUL`` terminated.
+ * @rst
+ * .. warning:: The pointers stored in ``out`` and ``err`` need to be `free(3)`-ed
+ * by the caller.
+ * @endrst
+ */
int vis_pipe_collect(Vis*, File*, Filerange*, const char *argv[], char **out, char **err);
-/* 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. */
+/**
+ * @}
+ * @defgroup vis_keys
+ * @{
+ */
+/**
+ * Advance to the start of the next symbolic key.
+ *
+ * Given the start of a symbolic key, returns a pointer to the start of the one
+ * immediately following it.
+ */
const char *vis_keys_next(Vis*, const char *keys);
-/* Tries to convert next symbolic key to a raw code point, returns -1 for unknown keys */
+/** Convert next symbolic key to an Unicode code point, returns ``-1`` for unknown keys. */
long vis_keys_codepoint(Vis*, const char *keys);
-/* Tries to convert next symbolic key to a UTF-8 sequence. Returns false for unknown keys
- * and leaves `utf8` untouched. Guarantees that `utf8` is NUL terminated on success */
+/**
+ * Convert next symbolic key to a UTF-8 sequence.
+ * @return Whether conversion was successful, if not ``utf8`` is left unmodified.
+ * @rst
+ * .. note:: Guarantees that ``utf8`` is NUL terminated on success.
+ * @endrst
+ */
bool vis_keys_utf8(Vis*, const char *keys, char utf8[static UTFmax+1]);
-/* 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 interprets them as if they were entered by a user. */
+/** Process symbolic keys as if they were user originated input. */
void vis_keys_feed(Vis*, const char *keys);
+/**
+ * @}
+ * @defgroup vis_misc
+ * @{
+ */
-/* 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);
-
-/* remember last search pattern, freeing the regex is the callers responsibility */
+/**
+ * Get a regex object matching pattern.
+ * @param regex The regex pattern to compile, if ``NULL`` the most recently used
+ * one is substituted.
+ * @return A Regex object or ``NULL`` in case of an error.
+ * @rst
+ * .. warning:: The caller must free the regex object using `text_regex_free`.
+ * @endrst
+ */
Regex *vis_regex(Vis*, const char *pattern);
+/**
+ * Take an undo snaphost to which we can later revert to.
+ * @rst
+ * .. note:: Does nothing when invoked while replaying a macro.
+ * @endrst
+ */
+void vis_file_snapshot(Vis*, File*);
+/** @} */
+
/* TODO: expose proper API to iterate through files etc */
Text *vis_text(Vis*);
View *vis_view(Vis*);