Vis

The core Vis API.

Lifecycle

Vis *vis_new(Ui*, VisEvent*)

Create a new editor instance using the given user interface and event handlers.

void vis_free(Vis*)

Free all resources associated with this editor instance, terminates UI.

int vis_run(Vis*)

Enter main loop, start processing user input.

Return

The editor exit status code.

void vis_exit(Vis*, int status)

Terminate editing session, the given status will be the return value of vis_run.

void vis_die(Vis*, const char *msg, ...)

Emergency exit, print given message, perform minimal UI cleanup and exit process.

Note

This function does not return.

void format(printf, 2, 3)
void vis_suspend(Vis*)

Temporarily supsend the editor process.

Note

This function will generate a SIGTSTP signal.

void vis_resume(Vis*)

Resume editor process.

Note

This function is usually called in response to a SIGCONT signal.

bool vis_signal_handler(Vis*, int signum, const siginfo_t *siginfo, const void *context)

Inform the editor core that a signal occured.

Return

Whether the signal was handled.

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).

void vis_interrupt(Vis*)

Interrupt long running operation.

Warning

There is no guarantee that a long running operation is actually interrupted. It is analogous to cooperative multitasking where the operation has to voluntarily yield control.

Note

It is invoked from vis_signal_handler() when receiving SIGINT.

bool vis_interrupt_requested(Vis*)

Check whether interruption was requested.

Draw

void vis_draw(Vis*)

Draw user interface.

void vis_redraw(Vis*)

Completely redraw user interface.

void vis_update(Vis*)

Blit user interface state to output device.

Windows

bool vis_window_new(Vis*, const char *filename)

Create a new window and load the given file.

Parameters
  • filename: If NULL a unamed, empty buffer is created.

    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.

bool vis_window_new_fd(Vis*, int fd)

Create a new window associated with a file descriptor.

Note

No data is read from fd, but write commands without an explicit filename will instead write to the file descriptor.

bool vis_window_reload(Win*)

Reload the file currently displayed in the window from disk.

bool vis_window_closable(Win*)

Check whether closing the window would loose unsaved changes.

void vis_window_close(Win*)

Close window, redraw user interface.

bool vis_window_split(Win*)

Split the window, shares the underlying file object.

void vis_window_status(Win*, const char *status)

Change status message of this window.

void vis_window_draw(Win*)
void vis_window_invalidate(Win*)
void vis_window_next(Vis*)

Focus next window.

void vis_window_prev(Vis*)

Focus previous window.

void vis_window_focus(Win*)

Change currently focused window, receiving user input.

void vis_window_swap(Win*, Win*)

Swap location of two windows.

int vis_window_width_get(const Win*)

Query window dimension.

int vis_window_height_get(const Win*)

Query window dimension.

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.

    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.

const char *vis_keys_next(Vis*, const char *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.

long vis_keys_codepoint(Vis*, const char *keys)

Convert next symbolic key to an Unicode code point, returns -1 for unknown keys.

bool vis_keys_utf8(Vis*, const char *keys, char utf8[static UTFmax+1])

Convert next symbolic key to a UTF-8 sequence.

Return

Whether conversion was successful, if not utf8 is left unmodified.

Note

Guarantees that utf8 is NUL terminated on success.

void vis_keys_feed(Vis*, const char *keys)

Process symbolic keys as if they were user originated input.

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.

bool vis_keymap_add(Vis*, const char *key, const char *mapping)

Add a key translation.

void vis_keymap_disable(Vis*)

Temporarily disable the keymap for the next key press.

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.

KeyBinding *vis_binding_new(Vis*)
void vis_binding_free(Vis*, KeyBinding*)
bool vis_mode_map(Vis*, enum VisMode, bool force, const char *key, const KeyBinding*)

Set up a key binding.

Parameters
  • force: Whether an existing mapping should be discarded.

  • key: The symbolic key to map.

  • binding: The binding to map.

    Note

    binding->key is always ignored in favor of key.

bool vis_window_mode_map(Win*, enum VisMode, bool force, const char *key, const KeyBinding*)

Analogous to vis_mode_map, but window specific.

bool vis_mode_unmap(Vis*, enum VisMode, const char *key)

Unmap a symbolic key in a given mode.

bool vis_window_mode_unmap(Win*, enum VisMode, const char *key)

Analogous to vis_mode_unmap, but window specific.

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?

typedef const char *KeyActionFunction(Vis*, const char *keys, const Arg*)

Key action handling function.

Return

Pointer to first non-cosumed key.

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.

Parameters
  • keys: Input queue content after the binding which invoked this function.

    Note

    An empty string "" indicates that no further input is available.

KeyAction *vis_action_new(Vis*, const char *name, const char *help, KeyActionFunction*, Arg)

Create new key action.

Parameters
  • name: The name to be used as symbolic key when registering.

  • help: Optional single line help text.

  • func: The function implementing the key action logic.

  • arg: Argument passed to function.

void vis_action_free(Vis*, KeyAction*)
bool vis_action_register(Vis*, const KeyAction*)

Register key action.

Note

Makes the key action available under the pseudo key name specified in keyaction->name.

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.

enum VisMode

Mode specifiers.

Values:

VIS_MODE_NORMAL
VIS_MODE_OPERATOR_PENDING
VIS_MODE_VISUAL
VIS_MODE_VISUAL_LINE

Sub mode of VIS_MODE_VISUAL.

VIS_MODE_INSERT
VIS_MODE_REPLACE

Sub mode of VIS_MODE_INSERT.

VIS_MODE_INVALID
void vis_mode_switch(Vis*, enum VisMode)

Switch mode.

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.

enum VisMode vis_mode_get(Vis*)

Get currently active mode.

enum VisMode vis_mode_from(Vis*, const char *name)

Translate human readable mode name to constant.

Count

Dictates how many times a motion or text object is evaluated. If none is specified, a minimal count of 1 is assumed.

int vis_count_get(Vis*)

Get count, might return VIS_COUNT_UNKNOWN.

int vis_count_get_default(Vis*, int def)

Get count, if none was specified, return def.

void vis_count_set(Vis*, int count)

Set a count.

VisCountIterator vis_count_iterator_get(Vis*, int def)

Get iterator initialized with current count or def if not specified.

VisCountIterator vis_count_iterator_init(Vis*, int count)

Get iterator initialized with a count value.

bool vis_count_iterator_next(VisCountIterator*)

Increment iterator counter.

Return

Whether iteration should continue.

Note

Terminates iteration if the edtior was interrupted in the meantime.

VIS_COUNT_UNKNOWN

No count was specified.

Operators

typedef size_t() VisOperatorFunction(Vis *, Text *, OperatorContext *)

An operator performs a certain function on a given text range.

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().

int vis_operator_register(Vis*, VisOperatorFunction*, void *context)

Register an operator.

Return

Operator ID. Negative values indicate an error, positive ones can be used with vis_operator.

bool vis_operator(Vis*, enum VisOperator, ...)

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 the operator will be executed on the range determinded by:

  • A motion (see vis_motion).

  • A text object (vis_textobject).

The expected varying arguments are:

  • 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.

void vis_repeat(Vis*)

Repeat last operator, possibly with a new count if one was provided in the meantime.

void vis_cancel(Vis*)

Cancel pending operator, reset count, motion, text object, register etc.

Motions

enum VisMotionType

Values:

VIS_MOTIONTYPE_LINEWISE = 1 << 0
VIS_MOTIONTYPE_CHARWISE = 1 << 1
typedef size_t() VisMotionFunction(Vis *, Win *, void *context, size_t pos)

Motions take a starting position and transform it to an end position.

Note

Should a motion not be possible, the original position must be returned. TODO: we might want to change that to EPOS?

bool vis_motion(Vis*, enum VisMotion, ...)

Set motion to perform.

The following motions take an additional argument:

  • VIS_MOVE_SEARCH_FORWARD and VIS_MOVE_SEARCH_BACKWARD

    The search pattern as const char *.

  • VIS_MOVE_{LEFT,RIGHT}_{TO,TILL}

    The character to search for as const char *.

void vis_motion_type(Vis *vis, enum VisMotionType)

Force currently specified motion to behave in line or character wise mode.

int vis_motion_register(Vis*, enum VisMotionType, void *context, VisMotionFunction*)

Register a motion function.

Return

Motion ID. Negative values indicate an error, positive ones can be used with vis_motion.

Text Objects

typedef Filerange() VisTextObjectFunction(Vis *, Win *, void *context, size_t pos)

Text objects take a starting position and return a text range.

Note

The originating position does not necessarily have to be contained in the resulting range.

int vis_textobject_register(Vis*, int type, void *data, VisTextObjectFunction*)

Register a new text object.

Return

Text object ID. Negative values indicate an error, positive ones can be used with vis_textobject.

bool vis_textobject(Vis*, enum VisTextObject)

Set text object to use.

Marks

Marks keep track of a given text position.

Note

Marks are currently file local.

enum VisMark vis_mark_from(Vis*, char mark)

Translate single character mark name to corresponding constant.

void vis_mark(Vis*, enum VisMark)

Specify mark to use.

Note

If none is specified VIS_MARK_DEFAULT will be used.

enum VisMark vis_mark_used(Vis*)
void vis_mark_set(Win*, enum VisMark id, Array *sel)

Store a set of Fileranges in a mark.

Parameters
  • id: The register to use.

  • sel: The array containing the file ranges.

Array vis_mark_get(Win*, enum VisMark id)

Get an array of file ranges stored in the mark.

Warning

The caller must eventually free the Array by calling array_release.

void vis_mark_normalize(Array*)

Normalize an Array of Fileranges.

Removes invalid ranges, merges overlapping ones and sorts according to the start position.

bool vis_jumplist_save(Vis*)

Add selections of focused window to jump list.

bool vis_jumplist_prev(Vis*)

Navigate jump list backwards.

bool vis_jumplist_next(Vis*)

Navigate jump list forwards.

Registers

enum VisRegister vis_register_from(Vis*, char reg)

Translate single character register name to corresponding constant.

void vis_register(Vis*, enum VisRegister)

Specify register to use.

Note

If none is specified VIS_REG_DEFAULT will be used.

enum VisRegister vis_register_used(Vis*)
Array vis_register_get(Vis*, enum VisRegister)

Get register content.

Return

An array of TextString structs.

Warning

The caller must eventually free the array ressources using array_release.

bool vis_register_set(Vis*, enum VisRegister, Array *data)

Set register content.

Parameters
  • data: The array comprised of TextString structs.

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.

bool vis_macro_record(Vis*, enum VisRegister)

Start recording a macro.

Note

Fails if a recording is already ongoing.

bool vis_macro_record_stop(Vis*)

Stop recording, fails if there is nothing to stop.

bool vis_macro_recording(Vis*)

Check whether a recording is currently ongoing.

bool vis_macro_replay(Vis*, enum VisRegister)

Replay a macro.

Note

A macro currently being recorded can not be replayed.

Commands

typedef bool() VisCommandFunction(Vis *, Win *, void *data, bool force, const char *argv[], Selection *, Filerange *)

Command handler function.

bool vis_cmd(Vis*, const char *cmd)

Execute a :-command.

bool vis_cmd_register(Vis*, const char *name, const char *help, void *context, VisCommandFunction*)

Register new :-command.

Parameters
  • name: The command name.

  • help: Optional single line help text.

  • context: User supplied context pointer passed to the handler function.

  • func: The function implementing the command logic.

    Note

    Any unique prefix of the command name will invoke the command.

bool vis_cmd_unregister(Vis*, const char *name)

Unregister :-command.

Options

enum VisOption

Option properties.

Values:

VIS_OPTION_TYPE_BOOL = 1 << 0
VIS_OPTION_TYPE_STRING = 1 << 1
VIS_OPTION_TYPE_NUMBER = 1 << 2
VIS_OPTION_VALUE_OPTIONAL = 1 << 3
VIS_OPTION_NEED_WINDOW = 1 << 4
typedef bool() VisOptionFunction(Vis *, Win *, void *context, bool toggle, enum VisOption, const char *name, Arg *value)

Option handler function.

Parameters
  • win: The window to which option should apply, might be NULL.

  • context: User provided context pointer as given to vis_option_register.

  • force: Whether the option was specfied with a bang !.

  • name: Name of option which was set.

  • arg: The new option value.

bool vis_option_register(Vis*, const char *names[], enum VisOption, VisOptionFunction*, void *context, const char *help)

Register a new :set option.

Parameters
  • names: A NULL terminated array of option names.

  • option: Option properties.

  • func: The function handling the option.

  • context: User supplied context pointer passed to the handler function.

  • help: Optional single line help text.

    Note

    Fails if any of the given option names is already registered.

bool vis_option_unregister(Vis*, const char *name)

Unregister an existing :set option.

Note

Also unregisters all aliases as given to vis_option_register().

bool vis_prompt_cmd(Vis*, const char *cmd)

Execute any kind (:, ?, /) of prompt command.

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 given file range to an external process.

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 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.

Warning

The editor core is blocked until this function returns.

Return

The exit status of the forked process.

int vis_pipe_collect(Vis*, File*, Filerange*, const char *argv[], char **out, char **err)

Pipe a Filerange to an external process, return its exit status and capture everything that is written to stdout/stderr.

Parameters
  • argv: Argument list, must be NULL terminated.

  • out: Data written to stdout, will be NUL terminated.

  • err: Data written to stderr, will be NUL terminated.

    Warning

    The pointers stored in out and err need to be free(3)-ed by the caller.

Modification

These function operate on the currently focused window but ensure that all windows which show the affected region are redrawn too.

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_insert_key(Vis*, const char *data, size_t len)

Perform insertion at all cursor positions.

void vis_replace_key(Vis*, const char *data, size_t len)

Perform character subsitution at all cursor positions.

Note

Does not replace new line characters.

void vis_insert_tab(Vis*)

Insert a tab at all cursor positions.

Note

Performs tab expansion according to current settings.

void vis_insert_nl(Vis*)

Inserts a new line character at every cursor position.

Note

Performs auto indentation according to current settings.

Interaction

void vis_prompt_show(Vis*, const char *title)

Display a user prompt with a certain title.

Note

The prompt is currently implemented as a single line height window.

void vis_info_show(Vis*, const char *msg, ...)

Display a single line message.

Note

The message will automatically be hidden upon next input.

void void vis_info_hide(Vis *)

Hide informational message.

void vis_message_show(Vis*, const char *msg)

Display arbitrary long message in a dedicated window.

void vis_message_hide(Vis*)

Close message window.

Miscellaneous

Regex *vis_regex(Vis*, const char *pattern)

Get a regex object matching pattern.

Return

A Regex object or NULL in case of an error.

Warning

The caller must free the regex object using text_regex_free.

Parameters
  • regex: The regex pattern to compile, if NULL the most recently used one is substituted.

void vis_file_snapshot(Vis*, File*)

Take an undo snaphost to which we can later revert to.

Note

Does nothing when invoked while replaying a macro.