-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bindeval / funcrefs / if_py, if_lua #1898
Comments
From
So this has just not been implemented yet; I don't know when this will happen, though. |
Ah, so the problem is that some plugins (like powerline) check for the version, and if the version reports >703, they assume they have access to the 7.4 API. Since the 7.4 API is not supported, does it really make sense for NeoVim to report its version as 704? |
Hm, that's a bit tricky. Neovim has been forked from Vim 7.4.160, so it does provide a 7.4 API.. in Vimscript, that is. It's only the Python API that only supports the old commands. |
I see. So NeoVim is just in an awkward situation when it comes to Python support. Is there an existing issue tracking the work to support the 7.4 Python API? I'd like to follow it to know when I might be able to try the powerline plugin again. |
There's no issue for that because it's low priority. Maybe @ZyX-I would consider adding a condition to check |
AFAIR, bindeval is the only "important" thing that is missing. Most common Python plugins out there run without problems, unless they use bindeval (which most of them don't). |
Both |
I think it's in our own interest to be as much a drop-in replacement for vim as possible. Specially for what regards plugins. Many plugin authors won't write neovim-specific code for some time yet. And one user wanting to try neovim but discovering one of his preferred plugins is not supported is one less user. So, if there's a strong reason not to support bindeval, then it's ok. But if not, then I would support it, even if non-optimal. In other words, we should try to make writing neovim-specific code something optional, as far as we can. Of course, speaking is easy. I don't really know what the obstacle for implementing bindeval is, certainly. So I don't know how much costly it would be. |
I agree with @elmart, and equally so I don't remember exactly why we don't support |
Here are some reasons for not implementing bindeval:
With that said, it may be possible to emulate bindeval without changes to the API by including some support vimscript that is called from python. For example, consider this vimscript code: let s:objects = {}
let s:id = 1
function! BindEval(str)
let id = s:id
let s:id += 1
let s:objects[id] = eval(str)
return id
endfunction
function! Unref(id)
call remove(s:objects, a:id)
endfunction
function! DictGet(id, key)
let object = s:objects[a:id]
if type(object) != type({})
throw 'Not a dict'
endif
return object[a:key]
endfunction
" Plus some other functions to manipulate dicts/lists Clearly the above approach still would have to solve problems of resource leak(when should a remote reference be freed?), but at least no changes to the C API are required. As I said, I haven't done this yet because I don't think its worth the effort(I never used any plugin that depends on bindeval), but anyone is welcome to do so. |
Input:
The second and third condition leads to the very expensive operation of dumping the data into a string coded in Python compared to
I am pretty sure that if you try Powerline in NeoVim unchanged with code for vim-7.0 (yes, this is supported) there will be greater problems then absense of bindeval: due to IPC and lots of blocking requests over it that are being made for a single &stl evaluation this is not going to work well I guess. |
@tarruda Ok. I still don't fully understand the ins and outs of this, but I'll take your word for it. @ZyX-I I'm not very sure about the meaning of your previous message. In any case: You're the main contributor to powerline. It has become a pretty popular plugin. So, having it not working with neovim is for sure taking many users away from us. You're also a very important contributor here. Then, have you got plans to add neovim support to poweline? |
Here's some background on
Is this only a guess or did you actually try it? YouCompleteMe constantly transfers the entire buffer between vim and python(not to mention to its daemon) and it still performs well even with big files such as eval.c |
Yes, yes, I know about those. The part I don't fully understand is why new neovim plugin architecture plays bad with that. I can imagine, more or less, but haven't gone into the details. |
-----BEGIN PGP SIGNED MESSAGE----- On January 28, 2015 2:13:45 PM EAT, Thiago de Arruda notifications@github.com wrote:
I have not. YCM is irrelevant because expected problem is not data transfer rate and not even the speed of (de)serializing it like it was with aurum. Expected problem is an amount of context switches made by the processor. Each request (like vim.eval('&readonly')) makes process write to a socket and then wait for result and waiting ought to trigger switching to the next task. Also neovim is going to wait for :python to complete with the same result. And all this couples with switches made by the kernel for other reasons. Given that you can count for at least twenty requests per &statusline evaluation and that &statusline is evaluated at least once each time user presses a key (with a few exceptions) I do not need tests to have strong opinion this is not going to work well. And since opinion is rather strong I never actually tried to test. Do not think this will be too problematic: correct me if I am wrong, but API from around vim-7.0.112 (this is the first version with Python support which I was able to compile; it is now used in integration tests) is fully supported. I have a machine though where I almost never experience any performance problems with powerline, even though I sometimes get reports about them. If my opinion proves right even here the only reasonable variant will be a complete rewrite of Vim bindings.
-----BEGIN PGP SIGNATURE----- iQJNBAEBCgA3BQJUyNg8MBwfMDI7PjIgHTg6PjswOSAQOzU6QTA9NEA+MjhHIDxr |
Its more a matter of not being worth the effort than limitations of the plugin architecture. The problematic part is managing the lifetime of vim objects, which could be done by using weak references(when the vimscript refcount reaches 0, release the memory and throw an exception when the python code tries to access it later) but that is not 100% compatible with the current interface, and since compatibility would be the main goal this kinda becomes pointless. The much more complex alternative would be to maintain references across the plugin host, but there are more cases to deal with(plugin host holding references is killed, for example). Both approaches would require making the C API more complex, again for the sake of compatibility with very few plugins. |
I'm not sure if I understood you correctly, but are you suggesting a rewrite of neovim remote interface as the only reasonable choice for using powerline? If so, thats a very radical thought and I couldn't disagree more. Here are a couple of more reasonable approaches that comes to mind:
Even if Another choice powerline users have is to switch to vim-airline which seems to have a lot of powerline features without the python dependency.(Not sure if its a drop-in replacement for powerline, but it seems to be more popular) Let me conclude by reminding you that while the new remote plugin infrastructure won't have the same efficiency for marshaling data from/to nvim, I say it will be fast enough for 90% of the plugins out there. It also has the following advantages which I may already have mentioned:
IMO the extra context switches and CPU cycles are heavily outweighted by these advantages. |
-----BEGIN PGP SIGNED MESSAGE----- On January 28, 2015 5:45:06 PM EAT, Thiago de Arruda notifications@github.com wrote:
NeoVim has an entity called "Vim bindings"? I have never heard of it. More details is in powerline issue tracker, powerline/powerline#1287.
-----BEGIN PGP SIGNATURE----- iQJNBAEBCgA3BQJUyRBMMBwfMDI7PjIgHTg6PjswOSAQOzU6QTA9NEA+MjhHIDxr |
I need weak reference for if_lua compatibilities. |
Let me try to recap if I can follow the conversation. To support this, something like this would be needed in the C api: /// references by external plugins (no sanity checks)
int vim_ref(oid_t id) { return objmap[id].refcount++; }
int vim_unref(oid_t id) { return objmap[id].refcount--; }
/// returns kInvalidVimObject if there was a problem with the expression
oid_t vim_bindeval(const char *expr) {
// eval expression
oid_t id = ...;
int refcnt = vim_ref(id);
assert(refcnt == 1);
return id;
} Where (this is likely horribly misguided, but I need a mental model and I'm not that well versed in our external API) A concern with this is that now plugins can "crash" neovim by referencing a lot of memory, dying (not dereferencing them) and then trying again until the OOM killer comes for neovim. Perhaps a per-plugin map is better, which could be cleaned whenever a plugin exists. Anyway, from @ZyX-I's explanation about the context switches that a socket read/write would provoke, I assume that the problem wouldn't be fixed even if Please correct me on everything. |
@aktau I understand it this way:
The idea is that objects are normally obtained using |
I tried to follow @ZyX-I explanation, but I don't see how implementing this in neovim would afford any performance benefit.
So this would provide a compatible behavior, but underneath it's still making the same msgpack calls that would otherwise be done without bindeval. It could be quite confusing to plugin authors, if |
On January 29, 2015 7:43:46 AM EAT, "Justin M. Keyes" notifications@github.com wrote:
vim.bindeval will only get rid of (de)serialization of objects required by pyeval, but at a cost of a few more msgpack calls. Benefit may be there only for long-living objects (additional calls are only needed at startup) and should be smaller then for Vim. Actually just vim.call_func(funcname, args, self=None) and vim.locals (which is something like the output of vim.bindeval('l:'), but without mechanics for keeping ref in Python, *always modifying only the current scope and returning non-binded Python objects on .getitem() or .values()/.items()) should be enough if you talk about performance: this is getting rid of unnecessary (de)serialisation (msgpack (de)serialisation stays, of course, but it will only be one, not like serialise to json then resulting string to msgpack) and is thus not more performant, but also more convenient. I was actually saying how to be compatible with bindeval, not how to increase performance. |
@Shougo I understand you need if_lua compatibility for your plugins, unfortunately I cant focus on this right now because there are higher priorities(UI refactor, terminal emulation for bang commands, windows support). If you want to improve lua-client to implement if_lua compatibility I can provide some guidance, but it may be better to write from the scratch using luvit due to the better standard library and module system. |
Thats the big issue with implementing nested_list = vim.bindeval("g:dict1['dict2']['list']")
nested_list.append(1) It is simply not worth adding a bunch of C functions and types to the API just for this. However, it just ocurred to me that it may be possible to fully implement bindeval(with proper garbage collection) in pure vimscript, all we need to do is expose a |
The lua client is very similar to the python client in how the code is organized, it has four main layers:
The big difference is that the lua client event loop can only connect to a child nvim process(used for functional tests). There are 3 transport types that the lua client doesn't support yet:
These transport types must be added in the event loop layer(the rest doesn't need to be changed) So you have two choices:
I recommend you to write from the scratch with luvi using the same code organization, its not a huge amount of work(the lua client has 600 loc, but 300 is for the libuv C bridge). If you do, read the lua/python client source code in top->bottom order:
If you have any questions, feel free to ask |
It appears that I cannot use Python client at all: it simply hangs whenever I do |
I actually need every method Vim defines for vim.List, vim.Dictionary and vim.Function in if_py_both, this is more than I have already listed. Guess this is better to be put into |
In order to provide better compatibility with the classic bindings, the API needs to provide the ability to query the number (really index) of the window/tabpage. This is needed for neovim/pynvim#87, as discussed in neovim#1898. Signed-off-by: James McCoy <jamessan@jamessan.com>
In order to provide better compatibility with the classic bindings, the API needs to provide the ability to query the number (really index) of the window/tabpage. This is needed for neovim/pynvim#87, as discussed in neovim#1898. Signed-off-by: James McCoy <jamessan@jamessan.com>
In order to provide better compatibility with the classic bindings, the API needs to provide the ability to query the number (really index) of the window/tabpage. This is needed for neovim/pynvim#87, as discussed in neovim#1898. Signed-off-by: James McCoy <jamessan@jamessan.com>
In order to provide better compatibility with the classic bindings, the API needs to provide the ability to query the number (really index) of the window/tabpage. This is needed for neovim/pynvim#87, as discussed in neovim#1898. Signed-off-by: James McCoy <jamessan@jamessan.com>
The 'vim' module exposed to python calls appears to be missing a few classes/functions/methods compared to Vim (at least) 7.4. This results in errors when attempting to use the powerline plugin for Vim.
Executing
:python import vim; print dir(vim)
gets you the following output:In ordinary Vim:
In NeoVim:
I'm not entirely sure if the need for any/all of these is obviated by some of the NeoVim changes, but at least the powerline plugin explicitly relies on "bindeval," which NeoVim does not expose.
The text was updated successfully, but these errors were encountered: