Re: [implementations-list] Vimpulse update
Fra: Alessandro Piras <[email protected]> Emne: Re: [implementations-list] Vimpulse update Til: "Vi/Vim implementations list" <[email protected]> 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
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 <[email protected]> Emne: Re: [implementations-list] Vimpulse update Til: "Vi/Vim implementations list" <[email protected]> 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 [email protected] https://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list
Hi Jon, I don't know the details of the design of ViEmu either, but from what you're saying it seems a good design, thanks for sharing some details. I will take into account your suggestions when and if I decide to design and implement a new vi clone, maybe for emacs. Now I can only partially follow them, as most of the emulation is already implemented in viper, and I'm working on top of it, so I have to cope with its design. Furthermore, I don't have a very deep knowledge of viper, as vimpulse was born in a rush, out of frustration of having to cope with emacs "nice" bindings. I began working again on it last week, after two years in which I didn't use or contribute to its development. One of my objectives with vimpulse is changing viper's code only when strictly needed, as it was in the case of di ci da ca kind of commands. For example, vimpulse doesn't support commands of the form d2aw. Supporting them would require major changes to a viper function, because basically, viper works like this: it checks if the character after command (in the case of 2d3w, the character '3') is numeric, if it is, reads a numeric argument, and executes the command following 3. So basically, what it does in a d2w command is moving the cursor 2 words, and deletes the range identified by the old and the new position. At least, that's what I understood looking at the code. As a result of this, it reacts in a stupid way to nonsense commands like 4d2x, that is equivalent to 2x. Another side effect is that d2iw results in viper entering insert mode and inseerting 'w' in the buffer, and when it returns to vi mode, the text inserted is inserted again as a result of the '2' in d2iw. I really don't know which changes to viper are needed to get correct behavior, but it seems to me that the design is not as clean as yours, in that motions and commands are not as orthogonal. about my text objects implementation, my motions return a range (start end), and my commands operate on such ranges. :) You made me think more about the issue though, thank you, I'll try to keep things clean at least for what concerns my code. Alessandro 2009/6/24 Jon <[email protected]>
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 <[email protected]>
Emne: Re: [implementations-list] Vimpulse update Til: "Vi/Vim implementations list" < [email protected]> 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 [email protected] https://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list
_______________________________________________ implementations-list mailing list [email protected] https://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list
Alessandro, you're very welcome. ViEmu is closed source and commercial, so the design is not really publicly available. I hope the short summary can be helpful if anyone is curious. I am not very familiar with viper or vimpulse internally, I understand the context may make some design decisions impossible. Good luck with your project. -- Jon Alessandro Piras wrote:
Hi Jon, I don't know the details of the design of ViEmu either, but from what you're saying it seems a good design, thanks for sharing some details. I will take into account your suggestions when and if I decide to design and implement a new vi clone, maybe for emacs. Now I can only partially follow them, as most of the emulation is already implemented in viper, and I'm working on top of it, so I have to cope with its design. Furthermore, I don't have a very deep knowledge of viper, as vimpulse was born in a rush, out of frustration of having to cope with emacs "nice" bindings. I began working again on it last week, after two years in which I didn't use or contribute to its development. One of my objectives with vimpulse is changing viper's code only when strictly needed, as it was in the case of di ci da ca kind of commands. For example, vimpulse doesn't support commands of the form d2aw. Supporting them would require major changes to a viper function, because basically, viper works like this: it checks if the character after command (in the case of 2d3w, the character '3') is numeric, if it is, reads a numeric argument, and executes the command following 3. So basically, what it does in a d2w command is moving the cursor 2 words, and deletes the range identified by the old and the new position. At least, that's what I understood looking at the code. As a result of this, it reacts in a stupid way to nonsense commands like 4d2x, that is equivalent to 2x. Another side effect is that d2iw results in viper entering insert mode and inseerting 'w' in the buffer, and when it returns to vi mode, the text inserted is inserted again as a result of the '2' in d2iw. I really don't know which changes to viper are needed to get correct behavior, but it seems to me that the design is not as clean as yours, in that motions and commands are not as orthogonal.
about my text objects implementation, my motions return a range (start end), and my commands operate on such ranges. :) You made me think more about the issue though, thank you, I'll try to keep things clean at least for what concerns my code.
Alessandro
2009/6/24 Jon <[email protected]>
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 <[email protected]>
Emne: Re: [implementations-list] Vimpulse update Til: "Vi/Vim implementations list" < [email protected]> 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 [email protected] https://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list
_______________________________________________ implementations-list mailing list [email protected] https://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list
_______________________________________________ implementations-list mailing list [email protected] https://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list
Yeah :) I didn't think about yi/ya, as i never use it. It's very easy stuff to add I think :) By the way, the approach is a little different now, the code is more polished, shorter, and, in one word, better :) take a look at the latest version, that also enables repetition of those commands ^^ 2009/6/24 Marius Andersen <[email protected]>
Fra: Alessandro Piras <[email protected]> Emne: Re: [implementations-list] Vimpulse update Til: "Vi/Vim implementations list" < [email protected]> 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 [email protected] https://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list
participants (3)
-
Alessandro Piras -
Jon -
Marius Andersen