vis: respect window local mappings for child modes
[vis.git] / README.md
blob159a8ea155b627cc1a429675c1f106c3748114bb
1 Vis a vim-like text editor
2 ==========================
4 Vis aims to be a modern, legacy free, simple yet efficient vim-like editor.
6 As an universal editor it has decent Unicode support (including double width
7 and combining characters) and should cope with arbitrary files including:
9  - large (up to a few Gigabytes) ones including
10    - Wikipedia/OpenStreetMap XML / SQL / CVS dumps
11    - amalgamated source trees (e.g. SQLite)
12  - single line ones e.g. minified JavaScript
13  - binary ones e.g. ELF files
15 Efficient syntax highlighting is provided using Parsing Expression Grammars
16 which can be conveniently expressed using Lua in form of LPeg.
18 The editor core is written in a reasonable amount of clean (your mileage
19 may vary), modern and legacy free C code enabling it to run in resource
20 constrained environments. The implementation should be easy to hack on
21 and encourage experimentation (e.g. native built in support for multiple
22 cursors). There also exists a Lua API for in process extensions.
24 Vis strives to be *simple* and focuses on its core task: efficient text
25 management. As an example the file open dialog is provided by an independent
26 utility. There exist plans to use a client/server architecture, delegating
27 window management to your windowing system or favorite terminal multiplexer.
29 The intention is *not* to be bug for bug compatible with vim, instead a 
30 similar editing experience should be provided. The goal could thus be
31 summarized as "80% of vim's features implemented in roughly 1% of the code".
33 ![vis demo](https://raw.githubusercontent.com/martanne/vis/gh-pages/screencast.gif)
35 Getting started / Build instructions
36 ====================================
38 In order to build vis you will need a C99 compiler as well as:
40  * a C library, we recommend [musl](http://www.musl-libc.org/)
41  * [libcurses](http://www.gnu.org/software/ncurses/), preferably in the
42    wide-character version
43  * [libtermkey](http://www.leonerd.org.uk/code/libtermkey/)
44  * [lua](http://www.lua.org/) >= 5.2
45  * [LPeg](http://www.inf.puc-rio.br/~roberto/lpeg/) >= 0.12 (runtime
46    dependency required for syntax highlighting)
48 If you want a self contained statically linked binary you can try
49 to run `make standalone` which will attempt to download, compile
50 and install all of the above dependencies. `make local` will do
51 the same but only for libtermkey, lua and LPeg (i.e. the system
52 C and curses libraries are used).
54 To build a regular dynamically linked binary using the system
55 libraries, simply run `make` (possibly after adapting `config.mk`
56 to match your system).
58     $ $EDITOR config.mk
59     $ make
60     $ VIS_PATH=. ./vis config.h
62 Editing Features
63 ================
65 The following section gives a quick overview over the currently
66 supported features.
68 ###  Operators
70     d   (delete)
71     c   (change)
72     y   (yank)
73     p   (put)
74     >   (shift-right)
75     <   (shift-left)
76     J   (join)
77     ~   (swap case)
78     gu  (make lowercase)
79     gU  (make uppercase)
80     !   (filter)
81     =   (format using fmt(1))
83 Operators can be forced to work line wise by specifying `V`.
85 ### Movements
87     h        (char left)
88     l        (char right)
89     j        (line down)
90     k        (line up)
91     gj       (display line down)
92     gk       (display line up)
93     0        (start of line)
94     ^        (first non-blank of line)
95     g_       (last non-blank of line)
96     $        (end of line)
97     %        (match bracket)
98     b        (previous start of a word)
99     B        (previous start of a WORD)
100     w        (next start of a word)
101     W        (next start of a WORD)
102     e        (next end of a word)
103     E        (next end of a WORD)
104     ge       (previous end of a word)
105     gE       (previous end of a WORD)
106     {        (previous paragraph)
107     }        (next paragraph)
108     (        (previous sentence)
109     )        (next sentence)
110     [[       (previous start of C-like function)
111     []       (previous end of C-like function)
112     ][       (next start of C-like function)
113     ]]       (next end of C-like function)
114     gg       (begin of file)
115     g0       (begin of display line)
116     gm       (middle of display line)
117     g$       (end of display line)
118     G        (goto line or end of file)
119     |        (goto column)
120     n        (repeat last search forward)
121     N        (repeat last search backwards)
122     H        (goto top/home line of window)
123     M        (goto middle line of window)
124     L        (goto bottom/last line of window)
125     *        (search word under cursor forwards)
126     #        (search word under cursor backwards)
127     f{char}  (to next occurrence of char to the right)
128     t{char}  (till before next occurrence of char to the right)
129     F{char}  (to next occurrence of char to the left)
130     T{char}  (till before next occurrence of char to the left)
131     ;        (repeat last to/till movement)
132     ,        (repeat last to/till movement but in opposite direction)
133     /{text}  (to next match of text in forward direction)
134     ?{text}  (to next match of text in backward direction)
135     `{mark}  (go to mark)
136     '{mark}  (go to start of line containing mark)
138   An empty line is currently neither a word nor a WORD.
140   Some of these commands do not work as in vim when prefixed with a
141   digit i.e. a multiplier. As an example in vim `3$` moves to the end
142   of the 3rd line down. However vis treats it as a move to the end of
143   current line which is repeated 3 times where the last two have no
144   effect.
146 ### Text objects
148   All of the following text objects are implemented in an inner variant
149   (prefixed with `i`) and a normal variant (prefixed with `a`):
151     w  word
152     W  WORD
153     s  sentence
154     p  paragraph
155     [,], (,), {,}, <,>, ", ', `         block enclosed by these symbols
157   For sentence and paragraph there is no difference between the
158   inner and normal variants.
160     gn      matches the last used search term in forward direction
161     gN      matches the last used search term in backward direction
163   Additionally the following text objects, which are not part of stock vim
164   are also supported:
166     ae      entire file content
167     ie      entire file content except for leading and trailing empty lines
168     af      C-like function definition including immediately preceding comments
169     if      C-like function definition only function body
170     al      current line
171     il      current line without leading and trailing white spaces
173 ### Modes
175   Vis implements more or less functional normal, operator-pending, insert,
176   replace and visual (in both line and character wise variants) modes.
177   
178   Visual block mode is not implemented and there exists no immediate
179   plan to do so. Instead vis has built in support for multiple cursors.
181   Command mode is implemented as a regular file. Use the full power of the
182   editor to edit your commands / search terms.
184   Ex mode is deliberately not implemented, use `ssam(1)` if you need a
185   stream editor.
186   
187 ### Multiple Cursors / Selections
189   vis supports multiple cursors with immediate visual feedback (unlike
190   in the visual block mode of vim where for example inserts only become
191   visible upon exit). There always exists one primary cursor, additional
192   ones can be created as needed.
193   
194   To manipulate multiple cursors use in normal mode:
195   
196     CTRL-K   create a new cursor on the line above
197     CTRL-J   create a new cursor on the line below
198     CTRL-P   remove least recently added cursor
199     CTRL-N   select word the cursor is currently over, switch to visual mode
200     CTRL-A   try to align all cursor on the same column
201     ESC      if a selection is active, clear it.
202              Otherwise dispose all but the primary cursor.
204   Visual mode was enhanced to recognize:
205     
206     I        create a cursor at the start of every selected line
207     A        create a cursor at the end of every selected line
208     CTRL-N   create new cursor and select next word matching current selection
209     CTRL-X   clear (skip) current selection, but select next matching word
210     CTRL-P   remove least recently added cursor
212 ### Marks
214     [a-z] general purpose marks
215     <     start of the last selected visual area in current buffer
216     >     end of the last selected visual area in current buffer
218   No marks across files are supported. Marks are not preserved over
219   editing sessions.
221 ### Registers
223   Supported registers include:
225     "a-"z   general purpose registers
226     "A-"Z   append to corresponding general purpose register
227     "*, "+  system clipboard integration via shell scripts vis-{copy,paste}
228     "0      yank register
229     "_      black hole (/dev/null) register
231   If no explicit register is specified a default register is used.
233   Registers used for macros are currently independent.
235 ### Undo/Redo and Repeat
237   The text is currently snapshotted whenever an operator is completed as
238   well as when insert or replace mode is left. Additionally a snapshot
239   is also taken if in insert or replace mode a certain idle time elapses.
240   
241   Another idea is to snapshot based on the distance between two consecutive
242   editing operations (as they are likely unrelated and thus should be
243   individually reversible).
245   Besides the regular undo functionality, the key bindings `g+` and `g-`
246   traverse the history in chronological order. Further more the `:earlier`
247   and `:later` commands provide means to restore the text to an arbitrary
248   state.
250   The repeat command `.` works for all operators and is able to repeat
251   the last insertion or replacement.
253 ### Macros
255   `[a-z]` are recognized macro names, `q` starts a recording, `@` plays it back.
256   `@@` refers to the least recently recorded macro.
258 ### Command line prompt
260   At the `:`-command prompt only the following commands are recognized, any
261   valid unique prefix can be used:
263     :nnn          go to line nnn
264     :bdelete      close all windows which display the same file as the current one
265     :edit         replace current file with a new one or reload it from disk
266     :open         open a new window
267     :qall         close all windows, exit editor
268     :quit         close currently focused window
269     :read         insert content of another file at current cursor position
270     :split        split window horizontally
271     :vsplit       split window vertically
272     :new          open an empty window, arrange horizontally
273     :vnew         open an empty window, arrange vertically
274     :wq           write changes then close window
275     :xit          like :wq but write only when changes have been made
276     :write        write current buffer content to file
277     :saveas       save file under another name
278     :substitute   search and replace currently implemented in terms of `sed(1)`
279     :earlier      revert to older text state
280     :later        revert to newer text state
281     :map          add a global key mapping
282     :unmap        remove a global key mapping
283     :map-window   add a window local key mapping
284     :unmap-window remove a window local key mapping
285     :!            filter range through external command
286     :|            pipe range to external command and display output in a new window
287     :set          set the options below
289      tabwidth   [1-8]           default 8
291        set display width of a tab and number of spaces to use if
292        expandtab is enabled
294      expandtab  (yes|no)        default no
296        whether typed in tabs should be expanded to tabwidth spaces
298      autoindent (yes|no)        default no
300        replicate spaces and tabs at the beginning of the line when
301        starting a new line.
303      number         (yes|no)    default no
304      relativenumber (yes|no)    default no
306        whether absolute or relative line numbers are printed alongside
307        the file content
309      syntax      name           default yes
311        use syntax definition given (e.g. "c") or disable syntax
312        highlighting if no such definition exists (e.g :set syntax off)
314      show
316        show/hide special white space replacement symbols
318        newlines = [0|1]         default 0
319        tabs     = [0|1]         default 0
320        spaces   = [0|1]         default 0
322      cursorline (yes|no)        default no
324        highlight the line on which the cursor currently resides
326      colorcolumn number         default 0
328        highlight the given column
330      theme      name            default dark-16.lua | solarized.lua (16 | 256 color)
332        use the given theme / color scheme for syntax highlighting
334   Each command can be prefixed with a range made up of a start and
335   an end position as in start,end. Valid position specifiers are:
337     .          start of the current line
338     +n and -n  start of the line relative to the current line
339     'm         position of mark m
340     /pattern/  first match after current position
342   If only a start position without a command is given then the cursor
343   is moved to that position. Additionally the following ranges are
344   predefined:
346     %          the whole file, equivalent to 1,$
347     *          the current selection, equivalent to '<,'>
349   History support, tab completion and wildcard expansion are other
350   worthwhile features. However implementing them inside the editor feels
351   wrong. For now you can use the `:edit` command with a pattern or a
352   directory like this.
354     :e *.c
355     :e .
357   vis will call the `vis-open` script which invokes dmenu or slmenu
358   with the files corresponding to the pattern. The file you select in
359   dmenu/slmenu will be opened in vis.
361 ### Runtime Configurable Key Bindings
363 Vis supports run time key bindings via the `:{un,}map{,-window}` set of
364 commands. The basic syntax is:
366     :map <mode> <lhs> <rhs>
368 where mode is one of `normal`, `insert`, `replace`, `visual`,
369 `visual-line` or `operator-pending`. lhs refers to the key to map, rhs is
370 a key action or alias. An existing mapping can be overridden by appending
371 `!` to the map command.
373 Key mappings are always recursive, this means doing something like:
375     :map! normal j 2j
377 will not work because it will enter an endless loop. Instead vis uses
378 pseudo keys referred to as key actions which can be used to invoke a set
379 of available (see :help or <F1> for a list) editor functions. Hence the
380 correct thing to do would be:
382     :map! normal j 2<cursor-line-down>
384 Unmapping works as follows:
386     :unmap <lhs>
388 The commands suffixed with `-window` only affect the currently active window.
390 ### Tab <-> Space conversion and Line endings \n vs \r\n
392   Tabs can optionally be expanded to a configurable number of spaces.
393   The first line ending in the file determines what will be inserted
394   upon a line break (defaults to \n).
396 ### Jump list and change list
398   A per window, file local jump list (navigate with `CTRL+O` and `CTRL+I`)
399   and change list (navigate with `g;` and `g,`) is supported. The jump
400   list is implemented as a fixed sized ring buffer.
402 ### Mouse support
404   The mouse is currently not used at all.
406 ### Non Goals
408   Some of the features of vim which will *not* be implemented:
410    - tabs / multiple workspaces / advanced window management
411    - file and directory browser
412    - support for file archives (tar, zip, ...)
413    - support for network protocols (ftp, http, ssh ...)
414    - encryption
415    - compression
416    - GUIs (neither x11, motif, gtk, win32 ...) although the codebase
417      should make it easy to add them
418    - VimL
419    - plugins (certainly not vimscript, if anything it should be lua based)
420    - right-to-left text
421    - ex mode (if you need a stream editor use `ssam(1)`
422    - diff mode
423    - vimgrep
424    - internal spell checker
425    - compile time configurable features / `#ifdef` mess
427 Lua API for in process extension
428 ================================
430 Vis provides a simple Lua API for in process extension. At startup the
431 `visrc.lua` file is executed, this can be used to register a few event
432 callbacks which will be invoked from the editor core. While executing
433 these user scripts the editor core is blocked, hence it is intended for
434 simple short lived (configuration) tasks.
436 At this time there exists no API stability guarantees.
438  - `vis`
439    - `lexers` LPeg lexer support module
440    - `events` hooks
441      - `start()`
442      - `quit()`
443      - `win_open(win)`
444      - `win_close(win)`
445    - `files()` iterator
446    - `windows()` iterator
447    - `command(cmd)`
448    - `info(msg)`
449    - `open(filename)`
450  - `file`
451    - `insert(file, pos, data)`
452    - `delete(file, pos, len)`
453    - `lines_iterator(file)`
454    - `name`
455    - `lines[0..#lines+1]` array giving read/write access to lines
456  - `window`
457    - `file`
458    - `cursor`
459      - `line`, `col`
460      - `pos` bytes from start of file
462 Most of the exposed objects are managed by the C core. Allthough there
463 is a simple object life time management mechanism in place, it is still
464 recommended to *not* let the Lua objects escape from the event handlers
465 (e.g. by assigning to global Lua variables).
467 Text management using a piece table/chain
468 =========================================
470 The core of this editor is a persistent data structure called a piece
471 table which supports all modifications in `O(m)`, where `m` is the number
472 of non-consecutive editing operations. This bound could be further
473 improved to `O(log m)` by use of a balanced search tree, however the
474 additional complexity doesn't seem to be worth it, for now.
476 The actual data is stored in buffers which are strictly append only.
477 There exist two types of buffers, one fixed-sized holding the original
478 file content and multiple append-only ones storing the modifications.
480 A text, i.e. a sequence of bytes, is represented as a double linked
481 list of pieces each with a pointer into a buffer and an associated
482 length. Pieces are never deleted but instead always kept around for
483 redo/undo support. A span is a range of pieces, consisting of a start
484 and end piece. Changes to the text are always performed by swapping
485 out an existing, possibly empty, span with a new one.
487 An empty document is represented by two special sentinel pieces which
488 always exist:
490     /-+ --> +-\
491     | |     | |
492     \-+ <-- +-/
493      #1     #2
495 Loading a file from disk is as simple as mmap(2)-ing it into a buffer,
496 creating a corresponding piece and adding it to the double linked list.
497 Hence loading a file is a constant time operation i.e. independent of
498 the actual file size (assuming the operating system uses demand paging).
500     /-+ --> +-----------------+ --> +-\
501     | |     | I am an editor! |     | |
502     \-+ <-- +-----------------+ <-- +-/
503      #1             #3              #2
505 Insert
506 ------
508 Inserting a junk of data amounts to appending the new content to a
509 modification buffer. Followed by the creation of new pieces. An insertion
510 in the middle of an existing piece requires the creation of 3 new pieces.
511 Two of them hold references to the text before respectively after the
512 insertion point. While the third one points to the newly added text.
514     /-+ --> +---------------+ --> +----------------+ --> +--+ --> +-\
515     | |     | I am an editor|     |which sucks less|     |! |     | |
516     \-+ <-- +---------------+ <-- +----------------+ <-- +--+ <-- +-/
517      #1            #4                   #5                #6      #2
519            modification buffer content: "which sucks less"
521 During this insertion operation the old span [3,3] has been replaced
522 by the new span [4,6]. Notice that the pieces in the old span were not
523 changed, therefore still point to their predecessors/successors, and can
524 thus be swapped back in.
526 If the insertion point happens to be at a piece boundary, the old span
527 is empty, and the new span only consists of the newly allocated piece.
529 Delete
530 ------
532 Similarly a delete operation splits the pieces at appropriate places.
534     /-+ --> +-----+ --> +--+ --> +-\
535     | |     | I am|     |! |     | |
536     \-+ <-- +-----+ <-- +--+ <-- +-/
537      #1       #7         #6      #2
539 Where the old span [4,5] got replaced by the new span [7,7]. The underlying
540 buffers remain unchanged.
542 Cache
543 -----
545 Notice that the common case of appending text to a given piece is fast
546 since, the new data is simply appended to the buffer and the piece length
547 is increased accordingly. In order to keep the number of pieces down,
548 the least recently edited piece is cached and changes to it are done
549 in place (this is the only time buffers are modified in a non-append
550 only way). As a consequence they can not be undone.
552 Undo/redo
553 ---------
555 Since the buffers are append only and the spans/pieces are never destroyed
556 undo/redo functionality is implemented by swapping the required spans/pieces
557 back in.
559 As illustrated above, each change to the text is recorded by an old and
560 a new span. An action consists of multiple changes which logically belong
561 to each other and should thus also be reverted together. For example
562 a search and replace operation is one action with possibly many changes
563 all over the text.
565 The text states can be marked by means of a snapshotting operation.
566 Snapshotting saves a new node to the history graph and creates a fresh
567 Action to which future changes will be appended until the next snapshot.
569 Actions make up the nodes of a connected digraph, each representing a state
570 of the file at some time during the current editing session. The edges of the
571 digraph represent state transitions that are supported by the editor. The edges
572 are implemented as four Action pointers (`prev`, `next`, `earlier`, and `later`).
574 The editor operations that execute the four aforementioned transitions
575 are `undo`, `redo`,`earlier`, and `later`, respectively. Undo and
576 redo behave in the traditional manner, changing the state one Action
577 at a time. Earlier and later, however, traverse the states in chronological
578 order, which may occasionally involve undoing and redoing many Actions at once.
580 Marks
581 -----
583 Because we are working with a persistent data structure marks can be
584 represented as pointers into the underlying (append only) buffers.
585 To get the position of an existing mark it suffices to traverse the
586 list of pieces and perform a range query on the associated buffer
587 segments. This also nicely integrates with the undo/redo mechanism.
588 If a span is swapped out all contained marks (pointers) become invalid
589 because they are no longer reachable from the piece chain. Once an
590 action is undone, and the corresponding span swapped back in, the
591 marks become visible again. No explicit mark management is necessary.
593 Properties
594 ----------
596 The main advantage of the piece chain as described above is that all
597 operations are performed independent of the file size but instead linear
598 in the number of pieces i.e. editing operations. The original file buffer
599 never changes which means the `mmap(2)` can be performed read only which
600 makes optimal use of the operating system's virtual memory / paging system.
602 The maximum editable file size is limited by the amount of memory a process
603 is allowed to map into its virtual address space, this shouldn't be a problem
604 in practice. The whole process assumes that the file can be used as is.
605 In particular the editor assumes all input and the file itself is encoded
606 as UTF-8. Supporting other encodings would require conversion using `iconv(3)`
607 or similar upon loading and saving the document.
609 Similarly the editor has to cope with the fact that lines can be terminated
610 either by `\n` or `\r\n`. There is no conversion to a line based structure in
611 place. Instead the whole text is exposed as a sequence of bytes. All
612 addressing happens by means of zero based byte offsets from the start of
613 the file.
615 The main disadvantage of the piece chain data structure is that the text
616 is not stored contiguous in memory which makes seeking around somewhat
617 harder. This also implies that standard library calls like the `regex(3)`
618 functions can not be used as is. However this is the case for all but
619 the most simple data structures used in text editors.
621 Syntax Highlighting using Parsing Expression Grammars
622 =====================================================
624 [Parsing Expression Grammars](https://en.wikipedia.org/wiki/Parsing_expression_grammar)
625 (PEG) have the nice property that they are closed under composition.
626 In the context of an editor this is useful because lexers can be
627 embedded into each other, thus simplifying syntax highlighting
628 definitions.
630 Vis reuses the [Lua](http://www.lua.org/) [LPeg](http://www.inf.puc-rio.br/~roberto/lpeg/)
631 based lexers from the [Scintillua](http://foicica.com/scintillua/) project.
633 Future Plans / Ideas
634 ====================
636 This section contains some ideas for further architectural changes.
638 Event loop with asynchronous I/O
639 --------------------------------
641 The editor core should feature a proper main loop mechanism supporting
642 asynchronous non-blocking and always cancelable tasks which could be
643 used for all possibly long lived actions such as:
645  - `!`, `=` operators
646  - `:substitute` and `:write` commands
647  - code completion
648  - compiler integration (similar to vim's quick fix functionality)
650 Client/Server Architecture / RPC interface
651 ------------------------------------------
653 In principle it would be nice to follow a similar client/server approach
654 as [sam/samterm](http://sam.cat-v.org/) i.e. having the main editor as a
655 server and each window as a separate client process with communication
656 over a unix domain socket.
658 That way window management would be taken care of by dwm or dvtm and the
659 different client processes would still share common cut/paste registers
660 etc.
662 This would also enable a language agnostic plugin system.
664 Efficient Search and Replace
665 ----------------------------
667 Currently the editor copies the whole text to a contiguous memory block
668 and then uses the standard regex functions from libc. Clearly this is not
669 a satisfactory solution for large files.
671 The long term solution is to write our own regular expression engine or
672 modify an existing one to make use of the iterator API. This would allow
673 efficient search without having to double memory consumption.
675 The used regex engine should use a non-backtracking algorithm. Useful
676 resources include:
678  - [Russ Cox's regex page](http://swtch.com/~rsc/regexp/)
679  - [TRE](https://github.com/laurikari/tre) as
680    [used by musl](http://git.musl-libc.org/cgit/musl/tree/src/regex)
681    which uses a parallel [TNFA matcher](http://laurikari.net/ville/spire2000-tnfa.ps)
682  - [Plan9's regex library](http://plan9.bell-labs.com/sources/plan9/sys/src/libregexp/)
683    which has its root in Rob Pike's sam text editor
684  - [RE2](https://github.com/google/re2) C++ regex library
686 Developer Overview
687 ==================
689 A quick overview over the code structure to get you started:
691  File(s)             | Description
692  ------------------- | -----------------------------------------------------
693  `text.[ch]`         | low level text / marks / {un,re}do / piece table implementation
694  `text-motions.[ch]` | movement functions take a file position and return a new one
695  `text-objects.[ch]` | functions take a file position and return a file range
696  `text-regex.[ch]`   | text search functionality, designated place for regex engine
697  `text-util.[ch]`    | text related utility functions mostly dealing with file ranges
698  `view.[ch]`         | ui-independent viewport, shows part of a file, syntax highlighting, cursor placement, selection handling
699  `ui.h`              | abstract interface which has to be implemented by ui backends
700  `ui-curses.[ch]`    | a terminal / curses based user interface implementation
701  `buffer.[ch]`       | dynamically growing buffer used for registers and macros
702  `ring-buffer.[ch]`  | fixed size ring buffer used for the jump list
703  `map.[ch]`          | crit-bit tree based map supporting unique prefix lookups and ordered iteration. used to implement `:`-commands
704  `vis.h`             | vi(m) specific editor frontend library public API
705  `vis.c`             | vi(m) specific editor frontend implementation
706  `vis-core.h`        | internal header file, various structs for core editor primitives
707  `vis-cmds.c`        | vi(m) `:`-command implementation
708  `vis-modes.c`       | vi(m) mode switching, enter/leave event handling
709  `vis-motions.c`     | vi(m) cursor motion implementation
710  `vis-operators.c`   | vi(m) operator implementation
711  `vis-lua.c`         | Lua bindings, exposing core vis APIs for in process extension
712  `main.c`            | key action definitions, program entry point
713  `config.def.h`      | definition of default key bindings (mapping of key actions)
714  `visrc.lua`         | Lua startup and configuration script
715  `lexers/`           | Lua LPeg based lexers used for syntax highlighting
717 Testing infrastructure for the [low level text manipulation routines]
718 (https://github.com/martanne/vis/tree/test/test/text), [vim compatibility]
719 (https://github.com/martanne/vis/tree/test/test/vim) and [vis specific features]
720 (https://github.com/martanne/vis/tree/test/test/vis) is in place, but
721 lacks proper test cases.