Page MenuHomePhabricator

Eovim Design Document
Updated 1,796 Days AgoPublic

This document explains how Eovim is designed: how the various parts interact together. It intends for a newcomer to quickly get the basics and better understand where to start scrapping the surface.

WARNING: This is work-in-progress

Build System

Eovim is built with CMake. There is one main CMakeLists.txt in the top source directory that does most of the job. Tests, plugins and the man page are handled by dedicated files. Useful CMake functions and macros reside in the cmake/ directory.

Sources and Headers

The sources of Eovim are all stored in the src/ directory. C source files are all placed directly there, without hierarchy. Headers are put in src/include/ and are decomposed into three categories:

  1. the headers in src/include/eovim/ are the ones owned by Eovim. This hierarchy allows C sources to include the headers by doing #include "eovim/HEADER.H". This is a namespacing.
  2. the headers in src/include/contrib/ are the ones that are scrapped from other projects, and as such are not original creations. Eovim's license does not apply to those files.
  3. the special header src/include/Eovim.h is used by plugins only.

As a rule of thumb, every C source has its counterpart header, but this may not always be the case.

Overview of the sources

Source NameDescription
config.cEovim's configuration: how to store its parameters
contrib.cCode srapped from foreign places
gui.cGUI implementation
keymap.cSpecial keys association
main.cEntry point
mode.cNeovim modes
nvim_api.cImplementation of message passing from Eovim to Neovim
nvim.cManagement of the neovim process and its communication with Eovim
nvim_event.cImplementation of Neovim hooks (events) that trigger Eovim code
nvim_helper.cHelpers to use the neovim API in specific cases
options.cArgument parser implementation
plugin.cDynamic code loading
prefs.cGUI dedicated to Eovim' settings
termcolors.xIncluded by termview.c. 256-colors palette (used by terminals).
termview.cTerminal widget used to render the text content of Neovim

Lifetime of Eovim

Eovim spawns a process that runs neovim with at least the --embed and --headless options, to make sure neovim is controlled by Eovim entirely. A window is created and binded to the neovim instance. During the execution of Eovim's main loop, the following events can be triggered:

  • GUI event: the user did interact with the grahical interface (e.g. move the mouse, press a key, resize the window, ...). When they require to be passed to neovim, data will be wrote in its standard input.
  • Neovim stderr event: neovim wrote data on its standard error. This usually predates a crash.
  • Neovim exit event: the neovim process was terminated. It can either be normal (e.g. exit 0) or abnormal (segfault). When neovim quits, eovim does the same.
  • Neovim stdout event: neovim wrote data on its standard output. This is how neovim signals Eovim what to display or what specific actions must be performed.

The communication interface between neovim and a client is described more into details there:

Sending data to neovim

The code responsible for providing data from Eovim to Neovim resides in src/nvim_api.c. It implements the MsgPack RPC. Eovim send requests to Neovim, which consists in the following elements:

  • a unique identifier for the request (generated by nvim_next_uid_get() in src/nvim.c), which will be used to find out the response message to the request;
  • the API method (a string);
  • the arguments to the method.

The unique identifier is currently on 32-bits. Integer overflow is assumed to let the request system in a nominal state.

Some requests are allowed to call back code when Eovim receives a response message. Callbacks are optional, and not available to all the APIs. The requests that have been sent, but have not received a response yet are kept around.

Analyzing main.c

As one can expect, src/main.c is where the main entry point of Eovim is defined. Since Eovim uses Elementary, main is actually elm_main. Eovim uses the EFL main loop. As such, modules have three states:

  1. initialization, where preliminary calculations/allocations can be performed. Init functions are suffixed by _init and are all of type Eina_Bool (*)(void).
  2. loop, where code will be code upon receiving events,
  3. shutdown, where the counterpart of the initialization will be performed. Shutdown functions are suffixed by _shutdown and are all of type void (*)(void).

elm_main itself does the following:

  1. initialization of the logger. This allows modules to use the macros CRI(), ERR(), WRN(), INF() and DBG(), as defined in src/include/eovim/log.h;
  2. command-line arguments parsing,
  3. initialization of Eovim's modules,
  4. plug-ins loading,
  5. creation of the neovim instance,
  6. run the mainloop,
  7. clean-up was has been initialized upon the mainloop termination,
  8. return the exit status of Eovim.
Last Author
Last Edited
Feb 26 2018, 2:51 AM