[implementations-list] On the software design of a vi/vim core
Jon
j at ngedit.com
Wed Jun 24 18:32:57 CEST 2009
I am Jon Beltran de Heredia, the developer and vendor of the ViEmu
products (vi/vim emulators for Visual Studio, Word, Outlook and SQL
Server). See http://www.viemu.com for details.
I am not familiar with the code of viper or vimpulse, but the design of
my own vi/vim emulation core achieves great orthogonality for commands /
motions and combinations thereof, requiring only the essentially
necessary code.
Basically, I have a keypress parser that builds a "full command desc",
and then it passes this to a command executing subsystem. Commands and
motions are very orthogonal. Here are the structs that defines a command
(this is very abstract template-based C++, the same core is used in all
the ViEmus):
//----------------------------------------------------------------------------
template<class CHAR>
struct ViFullCommand
{
unsigned cmd_count;
unsigned motion_count;
ViCommand cmd;
CHAR chCmdArg;
ViMotion mot;
CHAR chMotArg;
char chRegister;
// If CHR, and the org motions is CHR, toggle EXCL-INCL. If org is
linewise, ->CHR-EXCL. Rest simple override.
bool bForceMotionType;
TextRangeType eForceMotionType;
unsigned uVirtLines;
int iVirtCols;
basic_heap_string<CHAR> strArg;
};
//----------------------------------------------------------------------------
ViCommand and ViMotion are simple enums.
A simple motion (w) involves the VI_CMD_NULL command and the
VI_MO_Word_RIGHT motion. A more complex combination (2"ad3f*) involves
the VI_OP_DEL command, the VI_MO_FORWARD motion, "*" as the motion arg,
a chRegister of 'a', a count of 2 for the command and a count of 3 for
the motion. Most commands multiply both counts together, but this
structure is designed to faithfully represent the result of parsing a vi
command, and allow orthogonal implementation.
The motion is calculated by the motion subsystem. This is purely
functional: it returns the endpoint. Actually, it returns some extra
info -- "iw" is understood as a motion that returns a new "start point",
and motions can also return a motion type, and some extra info. "Visual"
is a special motion that has pre-stored points. The parser handles this
case -- actual command implementations don't know and don't care where
the motion range came from.
Then, the command subsytem calls the given command function with the
result of the motion. If the command is null, the cursor is moved to the
endpoint. Moving in visual mode is different, etc...
With this kind of architecture, the amount of code you need to write is
minimize. From the types of bugs I often see reported for other vi/vim
implementations, I understand people are not writing orthogonal code. A
design as the above allows the cleanest implementation.
-- Jon
Marius Andersen wrote:
>> Fra: Alessandro Piras <laynor at gmail.com>
>> Emne: Re: [implementations-list] Vimpulse update
>> Til: "Vi/Vim implementations list" <implementations-list at lists.ourproject.org>
>> Dato: Mandag 22. juni 2009 13.34
>>
>> it's easy stuff actually :) It works like this:
>> I modified the viper-prefix-arg-com function to introduce 4
>> new commands: da di ca ci. These commands will read-char to get motion
>> command.
>>
>
> Yes, this is a very good way to do it. It means more objects can be easily added without any more mucking around in `viper-prefix-arg-com'.
>
> Anyway, I mailed Michael Kifer and asked if there was a way to avoid redefining `viper-prefix-arg-com', and he replied he couldn't think of one. So until the original function is redesigned, which will probably not happen any soon, I think we can hold on to the present approach. :)
>
> What now remains is copying commands, `yiw', `yas', etc., and visual commands like `viw' and `vas'. The former requires updating `viper-prefix-arg-com' with entries for `vimpulse-yi' and `vimpulse-ya', while the latter is just a matter of writing commands for moving the cursor. For example, `vas' moves the cursor one sentence forward if it's at the end of the selection, and one sentence backward if it's at the beginning.
>
> I think this illustrates another point, incidentally: the power of vi comes from the multitude of ways of combining very basic commands, but implementing those combinations requires lots and lots of code. Therefore I think building vimpulse.el on top on Viper, rather than implementing Vim emulation from scratch, is the better approach.
>
> Marius Andersen
>
>
> _________________________________________________________
> Alt i ett. Få Yahoo! Mail med adressekartotek, kalender og
> notisblokk. http://no.mail.yahoo.com
>
>
> _______________________________________________
> implementations-list mailing list
> implementations-list at lists.ourproject.org
> https://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list
>
More information about the implementations-list
mailing list