-
Notifications
You must be signed in to change notification settings - Fork 262
The traditional vi is barely usable once you have become accustomed to the improvements introduced by vim.
However, we think vim can be improved further both in concepts and quality of implementation. Over the years it has accumulated a lot of cruft and support for now obsolete systems, many features have been added without a seemingly coherent design. By now it weights in at over 300K lines of C code of varying quality. We think this is unacceptable and off by at least an order of magnitude. It not only is a maintenance burden but also discourages experimentation with new ideas.
We decided this was beyond fixing and instead started from scratch:
-
incorporating the good ideas (e.g. modal editing, basic grammar: operators, motions + text objects)
-
combining them with multiple cursors/selections and a structural regular expression based command language
-
dropping the bad ones (e.g. custom regex syntax, vim script) and all the legacy cruft and feature creep
with a focus on a simple, clean, modular and efficient design as well as implementation. The result is quite different from vim.
Besides all that, it is fun (well most of the time anyway).
Some people
argue that vim has no need for multiple cursors/selections
because the text objects gn
and gN
combined with the repeat command .
,
macros and visual block mode are more powerful.
While it is true that these features work for some cases (and are also supported
up to an extent by vis), they are often inconvenient because they lack interactivity.
More advanced operations like alignment (<S-Tab>
) or rotations (+
,-
)
where multiple selections depend on each other are simply not possible.
For some things that is to be expected, for others it might be an oversight or simply a bug. In general the intention is not to be bug for bug compatible with vi(m), instead we aim to provide more powerful editing features based on an elegant design and clean implementation.
Yes that is true. In general we are proponents of a workflow involving many editor agnostic tools rather than one all encompassing monolith.
Furthermore, having no legacy baggage gives us the opportunity to revisit how a plugin interface for a modal editor should look like.
While we applaud them for trying to modernize a horrible codebase, their endeavour seems ultimately futile. They have accumulated so much technical debt and are still dealing with a 247K LOC monster. In a way they are caught between two worlds. They chose to remain backward compatible with vim and thus actively merge upstream patches. That of course not only discourages experimentation with new ideas and breaking changes, but also conflicts or at the very least makes the badly needed code refactorings much harder.
The Neovim project also has some worthwhile goals e.g. first class async support (which we hope to address in the future) only for the parent project to implement it in an incompatible way.
A concept introduced by Rob Pike in 1987
for his text editor sam(1)
. The main insight is that text editing
should not be artificially limited by the concept of a line. Most text editors
treat a file as an array of lines. Sam (and vis) instead use a byte stream
as underlying abstraction and let the user specify arbitrarily structured
regions using regular expressions.
As an example suppose you have the following simple file opened in vim with
[
and ]
denoting the selection boundaries in visual mode:
foo bar [foo bar]
When you now try to enter an ex command, vim already adds :'<,'>
to the command
prompt. That is by default it will not only operate on the given selection,
but on the whole lines covered by it. If you now perform a substitution like
:'<,'>s/foo/---/
you will notice that the first (not second) occurrence of
foo
is replaced. In contrast :x/foo/c/---/
in vis extracts all foo
from the given selection and changes them to ---
.
Sam's command language
applies these concepts to text editing and vis combines them with modal editing
and multiple selections to provide a more interactive variation
(check the vis(1)
manual page
for the supported syntax).
We like the power of modal editing.
If the world were a better place we would all be using Plan 9 and 9P, but unfortunately it is not and we are stuck with Unix boxes connected through SSH. In such an environment an editor needs to work in the TTY world.
Moreover the hardware has evolved over time. Acme, Sam (to a lesser extent) and Oberon all make extensive use of the mouse for selection and action purposes. This works best with a 3-button mouse but is cumbersome on small form factor touchpads (e.g. netbooks). While we recognize that a suitable mouse is a powerful tool, it doesn't work in all environments and a lot of it comes down to personal preference. We cater to a keyboard driven workflow where the fingers best stay on the home row and avoid unnecessary context switches to the mouse.
No. We reuse existing work where appropriate. Consider syntax highlighting, instead of designing our own custom solution we build on the work of the Scintillua project.
As a result of our modular design we also try to make individual components available
for others to use where appropriate. Examples include
vis-menu(1)
,
vis-digraph(1)
and
vis-clipboard(1)
.
Check the build instructions in the main README.
This is most likely due to a stale config.h
file. If you have no local
modifications you can simply remove it and restart the build which will
regenerate it based on config.def.h
:
rm config.h && ./configure && make
Otherwise you will have to manually merge the two C header files.
The original design relied on
mmap(2)
to provide efficient large file support. Using the operating system's virtual
memory subsystem instead of an editor internal block/caching layer.
Furthermore, we consider an editor a core system component. It is probably the tool that (system) programmers spend most of their time with. As such it should be easy to bootstrap onto new systems and facilitate self-hosted development. For this reason heavy dependencies (e.g. C++, boost etc.) should be avoided. Using C ensures maximal portability to resource-constrained architectures and environments. The editor should be usable in scenarios where one would normally find busybox vi such as in rescue systems, routers, phones and embedded devices.
These days the general public seems to think that C applications are automatically
riddled with memory bugs and security issues. We try to proactively prevent them
by making extensive use of static analysis (Coverity Scan),
runtime instrumentation (asan, msan, ubsan)
dynamic analysis (valgrind), runtime interpretation
(tis-interpreter) and fuzzing
(american fuzzy lop). Additionally we
enable hardening features
such as _FORTIFY_SOURCE
, stack protector, relro
, PIE and BIND_NOW
by default.
Besides that, the relatively small editor core written in C can be extended using Lua.
Lua was explicitly designed for this purpose. Like vis itself it has a reasonably clean design coupled with a portable, efficient implementation based on a small set of core primitives (tables) enabling powerful features (e.g. closures) and different usage paradigms (e.g. OOP).
It does not make sense to invent an editor specific extension language. Unlike for example Vimscript, Lua was designed as a general purpose programming language. As such it supports proper scoping rules and first class functions, it provides a rich set of existing libraries and easy integration through its C API. Unlike ELisp it does not need special hacks to make it performant.
In the distant future we might adopt a multi process architecture and expose a RPC API thereby enabling a language agnostic extension mechanism.
We might care about some architectures not supported by LuaJIT. More importantly, it would further expand our testing matrix with yet another build configuration. Plugin authors would have to be careful to only use the supported common subset of Lua 5.2 compatible with all implementations.
More generally we think that the tasks where Lua is used are not hugely performance critical (maybe with the exception of syntax highlighting). So far the standard Lua implementation was plenty fast enough. Should this ever become a serious bottleneck we will most likely have to re-evaluate our design decisions rather than simply switching to a faster implementation.
Having said that, there might be other reasons (e.g. the FFI) why one would like to reconsider LuaJIT.
We do not have a custom configuration file syntax, but instead use the regular
Lua API for configuration purposes.
Assuming your binary has been compiled with Lua support enabled (check the
output of vis -v
), you have the power of a full fledged programming language
at your disposal.
During startup vis
will attempt to source a visrc.lua
file from a set
of predefined locations.
Plugins are loaded using require
. Subscribe to one of the exposed events
and execute your commands
as desired. The default visrc.lua
should get you started.
If your configuration has no effect check the :help "Lua paths"
section to
see the exact paths being used by your binary. Alternatively use a tool like
strace(1)
to log all open(2)
syscalls:
strace -o log -e open vis +q && grep visrc.lua log
Try the :map
command.
Beware that all mappings are always evaluated recursively. Hence, the
right hand side must not contain the left hand side (neither directly nor
indirectly). As an example the following attempt to auto close braces
will not work:
:map! insert ( ()<Left>
instead use
:map! insert ( <C-v>u0028)<Left>
See :help
for a list of usable symbolic keys as well as editor pseudo keys.
You might also be interested in keyboard layout specific mappings.
This is because terminal input handling is a mess.
The representation of both <M-${key}>
and <Escape>${key}
are the same, the distinguishing
property is only the delay between the two key presses. This threshold can be configured using
the :set escdelay
option, which
has a default value of 50ms and is analogous to vim's
ttimeoutlen
setting.
If the keys arrive within that time frame, they are interpreted as the former otherwise
as the latter variant.
Terminal multiplexers will also affect this delay because they intercept the
original input and then forward it. In tmux this is can be configured using the
escape-time
setting.
For ncurses applications the $ESCDELAY
environment variable applies. This is also the case for dvtm. Furthermore, the used delay
can also be specified using with the -d
command line argument.
Syntax highlighting needs both Lua support (check vis -v
) and
LPeg. The latter can either be
statically compiled into the binary (in which case it will be reported as
+lpeg
in the above version query) or dynamically loaded at runtime using
the standard Lua module system (based on dlopen(3)
). The considered runtime
paths ending with .so
are also listed in the :help "Lua paths"
section.
If you are using the dynamic LPeg module, then make sure it is compiled against the same Lua version as vis itself.
We currently use terminal color palette changes to support 24bit True colors, if the terminal description indicates support for it. Otherwise we fall back to the closest color from the default 256 color cube which means some colors will not be displayed properly. If even 256 colors are not available, we fall back further to 16 colors according to this transition.
For 256-color fallback, we assume that the bottom 240 colors of the
palette are set up like
this.
The fallback color is chosen as the one which has the smallest
Euclidean distance from the target color, treating (R, G, B)
triples as values in ℝ³. This does not strictly align with human
perception (see CIEDE2000),
but is close enough.
Some terminals (e.g. Apple's Terminal.app) incorrectly advertise
the "can change color" ccc
(seeterminfo(5)
) capability, even
though they are incapable of performing the requested change. As a
result terminal colors end mixed up. Since we start replacing just
after the initial 16 colors, this usually has the symptom of the
editor appearing in dark blues and greens.
You have a couple of options to fix the issue:
- Use a base color scheme which does not rely on 24 bit colors (e.g.
dark-16
). - Fix your terminal description to match its actual capabilities. This is usually
accomplished by use of
infocmp(1M)
andtic(1M)
. - Add
:set change-256colors false
to yourvisrc.lua
configuration. Colors will be approximated and the option is an ugly workaround which might be removed in future versions.
There exist a number of distribution packages.
We want to avoid platform dependent code as much as possible. As a consequence we do not support native Windows binaries, but instead rely on Cygwin (or in the future midipix) to provide a POSIX environment.
Windows based continuous integration using AppVeyor is set up and allows build artifacts to be downloaded.
Modern machines have lots of resources available (e.g. memory or at least virtual address space) and we should use it to handle arbitrary files. We want to use the same tool to inspect and/or edit:
- large files (limited by the available virtual address space) including
- Wikipedia/OpenStreetMap XML / SQL / CSV dumps / Logs
- amalgamated source trees (e.g. SQLite)
- single line ones (e.g. minified JavaScript)
- binary ones (e.g. ELF files)
As a special case the editor should also be usable for regular editing tasks.
This is still work in progress.
We believe all text should be stored in UTF-8
which is the only encoding supported by vis. Should you have a need to edit
files in legacy encodings use iconv(1)
to convert it to UTF-8 and back.
For binary files you can try the motions go
(move to an absolute byte position)
as well as gh
and gl
which move to relative byte offsets in either backward
or forward direction, respectively. The %
motion which moves to a percentage
of the whole file content can be used to get a quick overview of a large file.
Only \n
is treated as a line break and Enter will always insert it. This is in line with
POSIX
and simplifies the implementation. If this is a problem, use e.g. dos2unix(1)
/ unix2dos(1)
for external conversion - or you could change the line endings by typing :x/\r\n/c/\n/
in vis
.