Architecture Overview
Architecture
Onivim 2 is a Revery application built with ReasonML.
Even though it is new technology, if you're coming from a web background - it should be easy to get started! The syntax of ReasonML is similar to JavaScript, and the core ideas are very similar to React, Redux, and the Elm Architecture - just used in a way that lets us compile to native code.
We want to have a functional lean to our codebase... and ReasonML / OCaml are the perfect fit for that. OCaml is highly optimized - even down to its garbage collector implementation - for building functional applications in a performant way.
Key concepts
- Action: A payload of information to describe a state change. Just like an action in redux.
- State and Model: used interchangeably to describe the application state.
- Reducer: A function of (
state
,action
) that returns a newstate
. - Updater: A function of (
state
,action
) that returns a tuple of (state
,effects
). Similar to a reducer, but also handles side-effects. Inspired by the Elm Architecture - Store Connector: Loosely akin to a middleware in Redux.
- Store: A State, Updater, and Store Connectors. Similar to a store in Redux.
One additional concept is the idea of our UI as a pure function of state
- this will be familiar for anyone coming from React.
The state management (actions, state, reducers, updaters, store) are facilitated by a reason-native library called `isolinear.
Source Code Overview
Overview:
src
- editor source codesrc/editor
- the source code for Onivim 2 (primarily Reason)src/editor/Core
- Core types used across the applicationsrc/editor/Extensions
- Modules relating to the extension host or syntax highlightingsrc/editor/Model
- description of the state of the application. The most important modules here are:State.re
- type definition for the application state.Reducer.re
- top-level reducer function.Actions.re
- type definition for all actions.
src/editor/Store
- connects the state of the application with external effects.- StoreThread.re is the entry point - creating a store and initializing all the store connectors.
src/editor/UI
- the user interface for the application.- Root.re is the top-level UI
- EditorSurface.re is where the buffer rendering happens.
src/editor/bin_editor
- The 'main' entry point ofOni2_editor.exe
.
src/textmate_service
- the source for our textmate syntax highlighting (JavaScript)
Vim
Vim is at the heart of Onivim 2. There are a few moving parts:
- libvim - A fork of Vim that is platform and terminal agnostic. It is the core buffer editing engine exposed via a simple API.
- reason-libvim - Reason bindings for
libvim
. Glance at the rei to get a feel for the API.
Onivim 2 integrates with reason-libvim
via a store connector: VimStoreConnector.re
.
Revery
Revery was built to support Onivim 2. It is a new UI framework that is intended to build fast, native, cross-platform applications with the ergonomics of React & Redux.
It manages the lifecycle of the application - it provides the App.start
, App.createWindow
, and UI.start
methods we use to kick-off the application: Oni2_editor.re
Extension Host
Coming soon!
Testing
For a cross-platform project built & maintained by a small team - test coverage is so important!
We have two classes of tests - unit tests and integration tests.
Unit Tests
Unit tests live in the test
folder and be can be run via esy '@test' run
, but remember to run esy '@test' install
initially to install the test dependencies.
We organize our tests 1-to-1 with the src
code - for example, test cases for src/editor/Core/LineNumber.re
would live in test/Core/LineNumberTests.re
.
Unit tests verify a particular piece of code in isolation, and should have minimal dependencies.
Integration Tests
Unit tests help us verify that individual modules work as expected - it's also important for an application like Onivim 2 to verify that things work when all these pieces come together.
We use integration tests to help us verify this - integration tests live in the integration_test
folder.
integration tests are each stand-alone executables that initialize an entire Store - just like the Onivim 2 app does! The only difference is that integration tests are headless (no UI).
integration tests can be run in one of two ways:
- They all can be run via
esy '@integrationtest' run
- Individual tests can be run via
esy '@integrationtest' x Test-Name.exe
Learning Resources
If you're interested in learning about ReasonML, we recommend the following:
For learning more about the architectural ideas, we recommend: