Closed ozars closed 5 years ago
Glad you see venu as being useful : ).
So, what you propose is "importing" a vim :menu into venu? That would mean venu should accept the following format: https://github.com/ozars/po.vim/blob/master/plugin/po.vim#L338-L348 ?
AFAIK, vim menu seems to be only useful in GUI mode?
I can think of two approaches to import such menus: a) Read the literal text of "amenu menuName.subMenuName command" and translate that into a venu b) or somehow access the defined ":menu"'s data object and traverse it while simultaneously translating it into venu's data structure.
I'm not great in vimscript. b) sounds like it could be the easier option as the menu would be evaluated already by vim. However, I don't know how to access the "processed" menu in vimscript (":amenu" just prints the menu entries... but how would one actually access the data object behind the menu?). a) sounds like a bit of work.
I agree that it would be great to automatically "import" these menus into venu.
AFAIK, vim menu seems to be only useful in GUI mode?
Indeed, that's the current situation. In terminal mode it's not so useful, unless menus can be navigated with a plugin like this. Personally, I would love to use menus for key bindings or commands that I infrequently use. It may even be useful for looking up associated mapping for a custom command instead of delving into vimrc.
b) or somehow access the defined ":menu"'s data object and traverse it while simultaneously translating it into venu's data structure.
I actually started parsing menu output after opening this issue. :) This is a naughty hack which might be broken if the output format changes in a newer vim version, but it does the job for now.
However, I don't know how to access the "processed" menu in vimscript (":amenu" just prints the menu entries... but how would one actually access the data object behind the menu?).
I dig into this already but unfortunately I couldn't find any interface to fetch underlying menu objects, other than parsing string outputs of *menu
commands. Moreover, there isn't any associated events fired if native menu is modified either (there is MenuPopup
event which isn't useful for our purposes). For the short-term above hack works, but for a long-term solution vim may be modified to have a native function/command to list (sub)menus (e.g. menuls
) and some native events fired when menu is modified.
I don't know if I can implement the latter, but I plan to implement the former. Shall I submit a PR in case I implement it?
I added an issue for the priority part of :*menu
as I think that's a nice feature https://github.com/Timoses/vim-venu/issues/3 .
b) or somehow access the defined ":menu"'s data object and traverse it while simultaneously translating it into venu's data structure.
I actually started parsing menu output after opening this issue. :) This is a naughty hack which might > be broken if the output format changes in a newer vim version, but it does the job for now.
Perhaps it would also be possible to define a new command like :venu-addItem
which could replace a line like
amenu &PO-Editing.&Remove\ quotes :call <SID>Unstringify()<CR>
into something like
venu-entry &PO-Editing.&Remove\ quotes :call <SID>Unstringify()<CR>
The function implementing that command could then venu#create
the menu "PO-Editing", call venu#addItem(<"PO-Editing"-menuHandle>, "Remove", <call unstringify>)
and venu#register(<"PO-Editing"-menuHandle>)
.
Perhaps it would be even better if there was a function venu#get(<menuName>)
to retrieve the menu, simply append an item (with venu#addItem
on the retrieved menu handle) and only venu#create
and venu#register
when the menu did not exist already (venu#get
returned null).
Of course this would mean that one would have to rewrite :*menu
into :venu-addItem
everywhere.
Or, is it possible to "overwrite" the command :*menu
? That would be an easy entry in .vimrc
for example (command! amenu call venu#entry()
, where I'm not so sure about the nomenclature of entry
yet).
Of course this would mean that one would have to rewrite
:*menu
into:venu-addItem
everywhere. Or, is it possible to "overwrite" the command:*menu
? That would be an easy entry in.vimrc
for example (command! amenu call venu#entry()
, where I'm not so sure about the nomenclature ofentry
yet).
Overwriting vim's commands seems not to be possible using command
. There is a workaround specified, by using cabbrev
. I made a simple experiment by placing these lines in my vimrc:
cabbrev amenu let g:amenu_replaced = 1 \| "
amenu
Unfortunately, it didn't wrap amenu
. It replaces if user types :amenu
in normal mode, but this is not useful for us.
How about adding a utility function venu#native#import
which will import native commands, possibly after filtering with an expression given by user? There can be a User
event for MenuUpdate
, which is expected to be called by other plugin developers after modifying menu entries. On User MenuUpdate
, Venu reimports native menu entries (it's hard to detect exact changes on menu entries). This can be done lazily before printing. When the event is fired a flag is set so that entries are reimported just before printing if the flag was set. This requires keeping native menu entries on a different variable than those created by user by calling venu#register
. These two dictionaries can be merged before printing.
I submitted #5. So far the implementation of parsing menu output is done. I can proceed after we decide on how to implement importing. Please let me know your feedback (on submitted PR and importing) if you think something could be done better.
I really like the idea of an importer. Would there be any more use cases for importing a menu from somewhere? Perhaps that would be an incentive to make it quite generic. Then again, I'm not sure how generic vim code can really be.
I'll have to find some time to think about it. Probably not before next weekend though.
Okay. I can implement import meanwhile. I won't implement MenuUpdate I mentioned above, instead we can rely on importing and merging every time before printing. In return other plugins won't need to depend on this plugin or a custom user event and they can just manipulate native menus. If this somehow results in some performance penalty while printing, then merging only after menu is updated can be considered.
Would there be any more use cases for importing a menu from somewhere? Perhaps that would be an incentive to make it quite generic.
FWIW, I can list a few differences between (vim's) menu and (Venu's) venu from what I understood so far.
There can be buffer specific menus :*menu <buffer>
, whereas venus (as in plural of venu :-) ) handle this by filtering wrt _filetype
field of global venu list s:menus
. Introducing configurable buffer-specific ps. I just saw examples on your prio patch.b:venu_list
and global g:venu_list
variables or adding a buffer_only
argument to venu#register
can mimic same behavior. Those two lists can be merged while merging native menus and sorting them all. Not so necessary though (at least for me).
Menus are mode-aware. I just learned and liked the idea behind :amenu
. It prepends and appends necessary characters to menu command to escape from insert mode and returning back to insert mode if the menu item is invoked while in insert mode. I don't know why there isn't an equivalent of this for mapping such as :amap
though. I have a few key bindings where I had to create imap variation manually. (Well... That's a good reason for me to write a simple Amap.vim plugin :-) )
Menus support shortcuts in a classic way: by putting an ampersand (&) before the shortcut letter in the name of menu entry. Venus uses enumeration for shortcuts. Having both of them would be best of two worlds, but not so crucial again.
One nice to have feature would be having right-aligned descriptions of a menu entry. Menus support it by setting the portion of name after
Toggle \c<space>
There is also priority feature which seems like you brought to venu, which is sweet!
Ability to use menus through Venu and sorting them wrt their priorities seems enough to me for my purposes. I listed those in case you'd like to modify venu in any of these directions.
Closed by #5.
vim has a native menu (
:menu
) feature which supports even submenus. Is there a simple way for instructing this plugin to print commands from a particular native menu?My use case: I started using an old plugin po.vim which happens to install some menu entries. I don't really want to map each menu entry to some key and there seems to be no other way for conveniently invoking menu entries (without using gvim ofc). Instead I will probably modify my fork of po.vim to depend on vim-venu by filling its entries manually, however it would be much better if vim-venu supports navigating native menu entries out-of-box.
Thanks for this great plugin!