Skip to content
guillermooo edited this page Jul 26, 2014 · 7 revisions

Introduction

Vintageous implements Vim emulation on top of the Sublime Text API.

Lifecycle of Vim Commands under Vintageous

Vintageous keeps collecting user input via key bindings until it can build a runnable command. At that point, command data is passed as JSON to a command runner.

Collecting command data from the user and running collected command data are Vintageous' core tasks, but there are other support steps too (more on that later).

State

state.State: Collects user input and evaluates its runnability.

At a very high level, this would be the life-cycle of a command, starting from a clean state:

  • User presses d (to request Vim delete command).
  • [State captures the action name in its .action property.]
  • User presses 2 (to request a count on the following motion).
  • [State captures the motion count in its .motion_count property.]
  • [At this point, our command is still incomplete.]
  • User presses w (to request a 'move by words' motion).
  • [State captures the motion name in its .motion property.]

At this point, State finally holds a runnable command: d2w. It's now time to run it, but before we see how that's done, here's a couple of important notes about State:

The interaction between the user and State has been possible thanks to the key bindings defined in ./Default.sublime-keymap. Contexts play a crucial part here to provide commands with mode awareness (./vi/contexts.py).

Also, it's worth noting that the Sublime Text settings API is used to persist the vast majority of State's data. The settings abstraction for Vintageous can be found in ./vi/settings.py.

How does State know now that it must stop accepting input and run the command?

After every key press, xactions.PressKey runs State.eval().

In each call, if .eval() finds State needs further user input, it does nothing. By contrast, if it finds a runnable command, it runs it.

Therefore, a more accurate description of the program's flow is conceptually as follows (in pseudocode):

    [PressKey: d]
    State.eval()
    [PressKey: 2]
    State.eval()
    [PressKey: w]
    State.eval()

How is d2w translated into a command that deletes two words?

Parsing State's captured data is State.eval()'s job. It makes sure that the requested command receives the current state as JSON-valid data.

How is a command run?

Command implementations are in xactions.py and xmotions.py.

Warning

We've left out quite a few details, and Sublime Text imposes some rigid restrictions that Vintageous must work around. While the above should enable you to grasp the inner workings of Vintageous, it isn't the full story.

We have also not discussed how the command line works. Though similar in many respects to the rest of Vintageous, it bypasses State most of the time.