noib3 / nvim-oxi Goto Github PK
View Code? Open in Web Editor NEW:link: Rust bindings to all things Neovim
Home Page: https://crates.io/crates/nvim-oxi
License: MIT License
:link: Rust bindings to all things Neovim
Home Page: https://crates.io/crates/nvim-oxi
License: MIT License
Since 0.1
release is out, there is a very simple question mentioned inside the issue's title. Is the project being put at the bug-maintenance mode? Or some features are still planned?
Sorry to bother you, again. The LuaPushable trait is not implemented for std::string::String, so Vec is still not a LuaPushable object. It seems like we need to implement this function. https://www.lua.org/manual/5.1/manual.html#lua_pushlstring
The custom completion list function require a type Function<(String, String, usize), Vec<String>>
: https://docs.rs/nvim-oxi/latest/nvim_oxi/types/enum.CommandComplete.html#variant.CustomList. However the trait LuaPushable doesn't implemented for Vec, so I can't create a new function that have return type Result<Vec<T>>
.
121 | let completion = Function::from_fn(generate_completion);
| ^^^^^^^^^^^^^^^^^ the trait `LuaPushable` is not implemented for `Vec<std::string::String>`
My function signature: fn generate_completion(arguments: (String, String, usize)) -> Result<Vec<String>>
Build with rev=e5c34c7
, which is currently the HEAD of the git repo.
It would be good to either make them public or improve the documentation everywhere they are used, so that you can have a quick look on what actually are the restrictions on the function e.g. here: https://docs.rs/nvim-oxi/latest/nvim_oxi/api/fn.create_user_command.html where you cannot click on StringOrFunction
.
from_fn_once
: if called twice, on second call, we call Box::from_raw is called on a value is that already moved in previous call.nvim-oxi/nvim-oxi/src/lua/luafun.rs
Lines 165 to 172 in 09d6934
from_fn_mut
: if called recursively, we create two mutable references to same closure.nvim-oxi/nvim-oxi/src/lua/luafun.rs
Lines 143 to 150 in 09d6934
Hey @noib3,
I've ran into an issue where a get a SIGSEGV when calling an exposed function from Nvim nightly that involves deserializing an Object
. This worked fine on Nvim stable.
Here's a simple module that reproduces the error:
use nvim_oxi::{self as oxi, object, Dictionary, Function, Object, ObjectKind, Result};
use serde::Deserialize;
#[derive(Default, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct Config {
#[serde(default)]
pub dir: String,
}
fn setup(preferences: Object) -> Result<()> {
// This works fine as long as preferences is Nil
let config = match preferences.kind() {
ObjectKind::Nil => Config::default(),
_ => {
// This will cause SIGSEGV
let deserializer = object::Deserializer::new(preferences);
Config::deserialize(deserializer)?
}
};
oxi::print!("All good! {config:?}");
Ok(())
}
#[oxi::module]
fn foobar() -> oxi::Result<Dictionary> {
Ok(Dictionary::from_iter([(
"setup",
Object::from(Function::from_fn(setup)),
)]))
}
From Nvim, calling :lua require("foobar").setup()
works fine, but :lua require("foobar").setup({ dir: "./" })
results in
'nvim $argv' terminated by signal SIGSEGV (Address boundary error)
Again, this worked fine on the latest stable Nvim. Any ideas?
For most neovim plugin, interop with Lua is crucial. mlua seems to pretty good at that. What is rationale behind reinvented the wheel here?
When calling api::get_runtime_file
I get a SIGSEV from neovim. (though calling it from lua is fine).
This is only somewhat reproducible, I added a test like this:
#[oxi::test]
fn get_runtime_file() {
api::get_runtime_file("test", true).unwrap();
panic!();
}
And it did not reach the panic, showing as "successful".
On stable neovim it worked fine.
The underlying issue might be on the neovim side and outside this repo, but the test should fail IMO.
Currently, once a Object
(string, array, ...) is created it is never freed. Object
, String
Collection
don't implement drop. We need to be more systematic about it.
# build in `nvim-oxi/examples/mlua`
cargo b -r && mkdir lua -p && mv target/release/liblua.so lua/lua.so -fn
# nvim
set_rtp=":set rtp+=$PWD"
cmd=":lua require'lua'.greetings()"
nvim -u NONE --headless +"$set_rtp" +"$cmd" +quit
And I got
Hello from Rust..
Hello from Rust.. function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
Hello from Rust.. function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18 function: builtin#18
...
If :lua require'lua'.greetings()
is run in nvim cmd, nvim just always prints them without stop.
The mlua features I use is this:
mlua = { version = "0.8", features = ["luajit", "vendored"] }
because Lua is not installed locally.
Thought you would be interested
Hey @noib3, I'm in the middle of refactoring out neovim logic from Xmas core, and I thought I might give nvim-oxi a try. Though unfortunately it isn't publish yet to crate io and current version is at 0.0.0 which a bit odd don't you think? or is it saying don't used me 🤣. Anyways I'm browse through the codebase right now, amazing progress so far, congrats
Copy the calc example and build it, then copy the .so file to lua directory, and then setup the rtp path and call the add or multiply function, got totally wrong result:
Example test script:
execute ':set rtp+=' . expand("%:p:h")
" I am testing in a crate named playground, it doesn't matter
lua =require("playground").add(1, 1)
lua =require("playground").multiply(1, 1)
Got:
1
0
Cargo.toml
[package]
name = "playground"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nvim-oxi = { git = "https://github.com/noib3/nvim-oxi", features = ["nightly"] }
[lib]
crate-type = ["cdylib"]
Just to give a little bit of context, Rust's async functions return Future
s that need an executor to drive them to completion. The usual way to achieve this is to let the async runtime, e.g. tokio, control the "main" thread. This is not a viable option in our case since it would block the UI thread, i.e. the one Neovim runs in, defeating the whole point of concurrent code.
However it should be possible (emphasis on the should) to use libuv, which Neovim uses for the event loop, as the executor. We could expose something like a Task
object that wraps an async {}
block and drives it to completion by scheduling it via libuv.
when i try to compile the plugin with nyoom
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: NvimError("\'ctermbg\' must be string or integer")', /Users/luxus/.cargo/git/checkouts/nvim-oxi-68d2fdc1d1cdbe82/15fb30d/nvim-oxi/src/lua/lua.rs:41:12
stack backtrace:
0: 0x103ecf8a0 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::he13a97dfe3ba6dc4
1: 0x103ef73e4 - core::fmt::write::hd751207b60c12d4c
2: 0x103ed9954 - std::io::Write::write_fmt::h08841cca3656c74a
3: 0x103ee4404 - std::panicking::default_hook::{{closure}}::h8d96478a0c41fbb8
4: 0x103ee40c8 - std::panicking::default_hook::haca5b586a55289c5
5: 0x103ee4918 - std::panicking::rust_panic_with_hook::h419d889b0a87beff
6: 0x103ecfcfc - std::panicking::begin_panic_handler::{{closure}}::hf9a5ae5699838d81
7: 0x103ecf9b4 - std::sys_common::backtrace::__rust_end_short_backtrace::h6248404e1e92c641
8: 0x103ee4518 - _rust_begin_unwind
9: 0x103efb92c - core::panicking::panic_fmt::ha964b6658f104372
10: 0x103efb988 - core::result::unwrap_failed::hf92687bbd06849b8
11: 0x103ec9334 - _luaopen_oxocarbon
12: 0x101246258 - <unknown>
13: 0x1012be51c - _luaL_openlibs
14: 0x101246258 - <unknown>
15: 0x10125995c - _lua_pcall
16: 0x100cdbdc4 - _nlua_require
17: 0x101246258 - <unknown>
18: 0x10125995c - _lua_pcall
19: 0x100cd94bc - _nlua_pcall
20: 0x100cda3a8 - _nlua_exec_file
21: 0x100db0fa0 - _do_source
22: 0x100dadbbc - _do_in_cached_path
23: 0x100dad140 - _source_runtime
24: 0x100cbc97c - _load_colors
25: 0x100c81ba4 - _ex_colorscheme
26: 0x100c7d33c - _execute_cmd0
27: 0x100c7d050 - _execute_cmd
28: 0x100bce964 - _nvim_cmd
29: 0x100bbc2f0 - _nlua_api_nvim_cmd
30: 0x101246258 - <unknown>
31: 0x1012be51c - _luaL_openlibs
32: 0x101246258 - <unknown>
33: 0x10125995c - _lua_pcall
34: 0x100cdbdc4 - _nlua_require
35: 0x101246258 - <unknown>
36: 0x1012be51c - _luaL_openlibs
37: 0x101246258 - <unknown>
38: 0x10125995c - _lua_pcall
39: 0x100cdbdc4 - _nlua_require
40: 0x101246258 - <unknown>
41: 0x10125995c - _lua_pcall
42: 0x100cd94bc - _nlua_pcall
43: 0x100cda3a8 - _nlua_exec_file
44: 0x100db0fa0 - _do_source
45: 0x100ce3344 - _main
fatal runtime error: Rust panics must be rethrown
fish: Job 1, 'RUST_BACKTRACE=full bin/nyoom...' terminated by signal SIGABRT (Abort)
rustc --version
rustc 1.62.1
cargo --version
cargo 1.62.0
Hi all!
Firstly, thank you for the awesome work y'all are doing to make Rust accessible for neovim plugin writers!
I'm using nvim-oxi
to write a plugin and have run into what appears to be a macos-specific issue. I only have access to an M1 mac, so I don't know for sure if this happens on intel macs or not. I do have access to a linux box, and I have confirmed the issue does not show up on linux (arch linux x86).
I'm seeing segfaults any time I try to execute a user-defined command. Here's my reproducible code snippet:
use nvim_oxi as oxi;
use nvim_oxi::types::{CommandArgs, CommandNArgs, CommandRange};
use nvim_oxi::opts::CreateCommandOpts;
use nvim_oxi::api;
#[oxi::module]
fn vim_plugin_test() -> oxi::Result<u32> {
let opts = CreateCommandOpts::builder().build();
let greetings = move |args: CommandArgs| {
api::out_write("Test");
Ok(())
};
api::create_user_command("Greetings", greetings, Some(&opts))?;
Ok(42)
}
I also have the linker arguments for macos as described in your examples directory:
# .cargo/config
[target.x86_64-apple-darwin]
rustflags = [
"-C", "link-arg=-undefined",
"-C", "link-arg=dynamic_lookup",
]
[target.aarch64-apple-darwin]
rustflags = [
"-C", "link-arg=-undefined",
"-C", "link-arg=dynamic_lookup",
]
My project builds with no issues, and I can confirm the user-defined command is accessible from neovim-- it shows up in tab completion. However, when I actually run :Greetings<CR>
, neovim dies with Segmentation fault: 11
.
I don't think this is an issue with code signing-- I got a different error (Killed: 9
) when that was the case. I am now running codesign
on the produced libraries and that seems to work just fine.
Any advice you have on next investigation steps would be much appreciated. Unfortunately GDB does not work on M1 architectures, but I have run neovim through lldb
and got the following stack trace on the error:
:GreetingsProcess 44524 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xa)
frame #0: 0x0000000196c53274 libsystem_platform.dylib`_platform_memmove + 420
libsystem_platform.dylib`_platform_memmove:
-> 0x196c53274 <+420>: ldr x6, [x1], #0x8
0x196c53278 <+424>: str x6, [x3], #0x8
0x196c5327c <+428>: subs x2, x2, #0x8 ; =0x8
0x196c53280 <+432>: b.hs 0x196c53274 ; <+420>
Target 0: (nvim) stopped.
(lldb) bt
error: need to add support for DW_TAG_base_type '()' encoded with DW_ATE = 0x7, bit_size = 0
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xa)
* frame #0: 0x0000000196c53274 libsystem_platform.dylib`_platform_memmove + 420
frame #1: 0x0000000103d31eec vim_plugin_test.so`core::ptr::read::h9e01436829227460(src=0x000000000000000a) at mod.rs:1115:9
frame #2: 0x0000000103d3843c vim_plugin_test.so`_$LT$nvim_types..dictionary..DictIterator$u20$as$u20$core..iter..traits..iterator..Iterator$GT$::next::hc4c389472e824fba(self=0x000000016fdfc560) at dictionary.rs:128:52
frame #3: 0x0000000103d2e550 vim_plugin_test.so`_$LT$nvim_oxi..object..de..MapDeserializer$u20$as$u20$serde..de..MapAccess$GT$::next_key_seed::h36af9d336687008b(self=0x000000016fdfc560, seed=PhantomData<nvim_oxi::api::types::command_args::_::{impl#0}::deserialize::__Field> @ 0x000000016fdfb15f) at de.rs:242:39
frame #4: 0x0000000103d28ed0 vim_plugin_test.so`serde::de::MapAccess::next_key::ha2ac654861086e10(self=0x000000016fdfc560) at mod.rs:1854:9
frame #5: 0x0000000103d28a70 vim_plugin_test.so`_$LT$$RF$mut$u20$A$u20$as$u20$serde..de..MapAccess$GT$::next_key::hf70525b52654ea59(self=0x000000016fdfb3a8) at mod.rs:1944:9
frame #6: 0x0000000103d38d78 vim_plugin_test.so`_$LT$nvim_oxi..api..types..command_args.._..$LT$impl$u20$serde..de..Deserialize$u20$for$u20$nvim_oxi..api..types..command_args..CommandArgs$GT$..deserialize..__Visitor$u20$as$u20$serde..de..Visitor$GT$::visit_map::h778579db4598e380(self=(marker = core::marker::PhantomData<nvim_oxi::api::types::command_args::CommandArgs> @ 0x000000016fdfc43e, lifetime = core::marker::PhantomData<void *> @ 0x000000016fdfc43e), __map=0x000000016fdfc560) at command_args.rs:12:45
frame #7: 0x0000000103d2e1b4 vim_plugin_test.so`_$LT$nvim_oxi..object..de..Deserializer$u20$as$u20$serde..de..Deserializer$GT$::deserialize_map::hbb41dd910ef1931e(self=Deserializer @ 0x000000016fdfc730, visitor=(marker = core::marker::PhantomData<nvim_oxi::api::types::command_args::CommandArgs> @ 0x000000016fdfc67f, lifetime = core::marker::PhantomData<void *> @ 0x000000016fdfc67f)) at de.rs:171:17
frame #8: 0x0000000103d2e270 vim_plugin_test.so`_$LT$nvim_oxi..object..de..Deserializer$u20$as$u20$serde..de..Deserializer$GT$::deserialize_struct::h1c7c2cd4a8b36d84(self=<unavailable>, _name=(data_ptr = "CommandArgsreg", length = 11), _fields=&[&str] @ 0x000000016fdfc768, visitor=(marker = core::marker::PhantomData<nvim_oxi::api::types::command_args::CommandArgs> @ 0x000000016fdfc77f, lifetime = core::marker::PhantomData<void *> @ 0x000000016fdfc77f)) at de.rs:191:9
frame #9: 0x0000000103d3853c vim_plugin_test.so`nvim_oxi::api::types::command_args::_::_$LT$impl$u20$serde..de..Deserialize$u20$for$u20$nvim_oxi..api..types..command_args..CommandArgs$GT$::deserialize::ha3ed7f8afb11d764(__deserializer=<unavailable>) at command_args.rs:12:45
frame #10: 0x0000000103d384e0 vim_plugin_test.so`_$LT$nvim_oxi..api..types..command_args..CommandArgs$u20$as$u20$nvim_oxi..object..from_object..FromObject$GT$::from_obj::h8776a94f554c1fc3(obj=<unavailable>) at command_args.rs:53:9
frame #11: 0x0000000103d265c4 vim_plugin_test.so`_$LT$A$u20$as$u20$nvim_oxi..lua..poppable..LuaPoppable$GT$::pop::ha691d818a34416d5(lstate=0x000000010070c380) at poppable.rs:46:9
frame #12: 0x0000000103d27f94 vim_plugin_test.so`nvim_oxi::lua::fun::Function$LT$A$C$R$GT$::from_fn::_$u7b$$u7b$closure$u7d$$u7d$::_$u7b$$u7b$closure$u7d$$u7d$::h1f0421eb4ed04d2f(l=0x000000010070c380) at fun.rs:104:45
frame #13: 0x0000000103d30fbc vim_plugin_test.so`nvim_oxi::lua::fun::Function$LT$A$C$R$GT$::from_fn::c_fun::hdd04c61c9bcb723d(lstate=0x000000010070c380) at fun.rs:100:13
frame #14: 0x0000000100734238 libluajit-5.1.2.dylib`___lldb_unnamed_symbol96$$libluajit-5.1.2.dylib + 44
frame #15: 0x0000000100740d80 libluajit-5.1.2.dylib`lua_pcall + 148
frame #16: 0x000000010012c368 nvim`nlua_pcall + 120
frame #17: 0x000000010012decc nvim`nlua_do_ucmd + 1368
frame #18: 0x000000010024109c nvim`do_ucmd + 208
frame #19: 0x00000001000d578c nvim`execute_cmd0 + 140
frame #20: 0x00000001000d261c nvim`do_cmdline + 12264
frame #21: 0x00000001001761c0 nvim`nv_colon + 416
frame #22: 0x0000000100173be8 nvim`normal_execute + 4172
frame #23: 0x000000010020ad44 nvim`state_enter + 360
frame #24: 0x0000000100137b60 nvim`main + 10716
frame #25: 0x000000010039508c dyld`start + 520
(lldb)
My best parse of this is that it's related to argument parsing or handling during the processing of the user-defined command. Perhaps relatedly, I noticed that using CommandNArgs::One
in the creation of the command caused an immediate crash of neovim on launch with the following error:
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: NvimError("Invalid value for \'nargs\'")', /Users/reecestevens/.cargo/registry/src/github.com-1ecc6299db9ec823/nvim-oxi-0.1.3/src/lua/lua.rs:42:12
stack backtrace:
0: rust_begin_unwind
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/std/src/panicking.rs:584:5
1: core::panicking::panic_fmt
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/panicking.rs:142:14
2: core::result::unwrap_failed
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/result.rs:1814:5
3: core::result::Result<T,E>::unwrap
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/result.rs:1107:23
4: nvim_oxi::lua::lua::module_entrypoint
at /Users/reecestevens/.cargo/registry/src/github.com-1ecc6299db9ec823/nvim-oxi-0.1.3/src/lua/lua.rs:42:5
5: luaopen_vim_plugin_test
at ./src/lib.rs:6:1
6: <unknown>
7: _luaL_openlibs
8: <unknown>
9: _lua_pcall
10: _nlua_pcall
11: _nlua_typval_exec
12: _ex_lua
13: _execute_cmd0
14: _do_cmdline
15: _do_source
16: _cmd_source
17: _execute_cmd0
18: _do_cmdline
19: _source_using_linegetter
20: _nvim_exec
21: _nlua_api_nvim_exec
22: <unknown>
23: _lua_pcall
24: _nlua_pcall
25: _nlua_typval_exec
26: _ex_lua
27: _execute_cmd0
28: _do_cmdline
29: _do_source
30: _main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
fatal runtime error: Rust panics must be rethrown
If you have any bandwidth to review these stack traces and let me know what you think, I would really appreciate it. Thanks again!
Trying to set up my CI on an nvim-oxi plugin, but linking fails: https://github.com/ModProg/config.nvim/actions/runs/3302333877
I see you have removed windows building from the CI in this repo. But do you know what the requirements for building for windows are?
good day to you!
im trying to compile some part of api example, but keep receiveing errors in build
lib.rs:
use nvim_oxi::api::{self, opts::*, types::*, Window};
use nvim_oxi::{self as oxi, print, Dictionary, Function};
#[oxi::module]
fn api() -> oxi::Result<i32> {
api::set_keymap(Mode::Insert, "hi", "hello", Default::default())?;
Ok(42)
}
unwrap_unchecked
is used in with_state
https://github.com/noib3/nvim-oxi/blob/master/crates/luajit-bindings/src/state.rs#L21. with_state
is used in a bunch of safe functions such as schedule
. So isn't it unsafe to call functions like schedule
from other threads? I think the normal unwrap
should be used here. The same thing happens in libuv-bindings
Maybe it's just me overlooking something but both traits in nvim_types::conversion
are just a specialized version of TryFrom
/TryInto
.
Is there a technical reason?
Else I suggest to rewrite conversion.rs to use TryFrom
instead or delete it all together.
I'm currently exploring nvim-oxi and while toying around with it I wrote a bunch of TryFrom<Object>
implementations before I realized FromObject is a thing, if it's down to development time needed I could do the conversion and create a PR.
Is it possible to support nightly neovim as well, or is that something that can just break very easily due to the ffi interface?
I got an error for nvim_get/set_option_value
with invalid value for key: scope
on neovim nightly.
I looked at the API and don't really see the reason why it would break, as they only removed win and buf, but kept scope the same:
nvim_get_option_value({name}, {*opts}) *nvim_get_option_value()*
Gets the value of an option. The behavior of this function
matches that of |:set|: the local value of an option is
returned if it exists; otherwise, the global value is
returned. Local values always correspond to the current buffer
or window. To get a buffer-local or window-local option for a
specific buffer or window, use |nvim_buf_get_option()| or
|nvim_win_get_option()|.
Parameters: ~
{name} Option name
{opts} Optional parameters
• scope: One of 'global' or 'local'. Analogous to
|:setglobal| and |:setlocal|, respectively.
Return: ~
Option value
Is this a cause of a change in memory layout, so to say?
It doesn't add null terminator.
nvim-oxi/nvim-types/src/string.rs
Lines 119 to 124 in ba9cd8d
After loading the .so library and call it from neovim, the neovim crash and report that:
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: NvimError("keepscript is not a boolean")'
My neovim version:
NVIM v0.8.0-dev-1146-g7a70e9587c
Build type: RelWithDebInfo
LuaJIT 2.1.0-beta3
Example code: https://github.com/Avimitin/cargo-add-cmp.nvim/blob/master/src/lib.rs#L123-L137
Hey 👋🏾
First of all, thank you very much for all the effort and time you put into this project. I really appreciate it and it gave the necessary motivation to start working on NeoVim plugins again.
I'm now in need to make some calls to functions that are globally defined in Lua by NeoVim. Means I want to access vim.lsp
, vim.diagnostic
, ... Unfortunately I don't see how this should be possible right now. But maybe I'm blind. 🙈
I took a look into your noib3/nvim-compleet project to checkout how you do it there. But it seems like this includes a huge amount of boilerplate code with a bridge etc. pp. completely independent of this library here. I'm not sure if there is any better way to do it, because I honestly have no clue about this topic. But in any case, do you plan to integrate this feature into nvim-oxi
too? It looks like you did already all the work for it in the other project, so it would be just a matter of putting it here too and wrap it nicely. Am I wrong?
Looking forward to hear what you think. 🙃
Some people like me would like to contribute, but sadly, I dont know what to start with. Having somekind of a todo/gh project/roadmap would be great, so more people would contribute.
Hello! Looking for a bit of help (or advice). I'm not sure if this is a bug or just me not understanding how API bindings in Rust works. I'm trying to use list_bufs
and list_wins
, but neither appear to be demonstrating the same behaviour as vim.api.nvim_list_bufs
or vim.api.nvim_list_wins
. For list_bufs
, no buffers are ever found. For list_wins
, I keep hitting a segfault.
Please let me know if I'm doing anything wrong. This is on Neovim 0.8.0 and I've made sure to point to master
with the neovim-0-8
feature flag.
Thanks!
List buffers
:lua =vim.api.nvim_list_bufs()
{ 1, 2, 3 }
List windows
:lua =vim.api.nvim_list_wins()
{ 1000 }
List buffers
:lua =require("nvim_open").buffers()
"[]"
List windows
:lua =require("nvim_open").windows()
fish: Job 1, 'nvim' terminated by signal SIGSEGV (Address boundary error))
lib.rs
use std::convert::Infallible;
use nvim_oxi as oxi;
use oxi::{
api::{list_bufs, Buffer, Window, list_wins},
Function, Dictionary, Object
};
#[oxi::module]
fn nvim_open() -> oxi::Result<oxi::Dictionary> {
let buffers = Function::from_fn(|()| {
let open_buffers: Vec<Buffer> = list_bufs().collect();
Ok::<_, Infallible>(oxi::String::from(format!("{:?}", open_buffers)))
});
let windows = Function::from_fn(|()| {
let open_windows: Vec<Window> = list_wins().collect();
Ok::<_, Infallible>(oxi::String::from(format!("{:?}", open_windows)))
});
Ok(Dictionary::from_iter([
("buffers", Object::from(buffers)),
("windows", Object::from(windows)),
]))
}
Cargo.toml
[dependencies.nvim-oxi]
git = "https://github.com/noib3/nvim-oxi"
branch = "master"
features = [ "neovim-0-8" ]
This allows to get back a "dynamic" object from functions that return <T: FromObject>.
My workaround is to do:
#[derive(Deref)]
struct Object(oxi::Object);
impl FromObject for Object {
fn from_object(object: oxi::Object) -> Result<Self, conversion::Error> {
Ok(Self(object))
}
}
but this would be nice to have in the library, especially as it would be a 4 line implementation
It would be nice to allow returning mlua
objects from the lua module, for example userdata or coroutines. I think you could either make the mlua
value pushable or use the mlua
module macro
It should be possible to pass a Rust closure everywhere one would pass a Lua function when using the Lua API.
Just as an example, something like
local print_current_modified = function()
local buf = vim.api.nvim_get_current_buf()
local is_modified = vim.api.nvim_buf_call(buf, function()
return vim.api.nvim_buf_get_option(0, "modified")
end)
print(is_modified)
end
should become
use nvim_oxi as nvim;
fn print_current_modified() -> nvim::Result<()> {
let buf = nvim::api::get_current_buf();
let is_modified = buf.call(|| {
nvim::Buffer::from(0).get_option::<bool>("modified")
})?;
nvim::print!("{is_modified}");
Ok(())
}
Functions should accept FnOnce
or FnMut
closures on a case-by-case basis, but always with a 'static
bound.
I'm not sure whether it is possible to implement this in here as it is only part of the lua API if I understand correctly, but they have a really convenient way to interact with option values using e.g. append
, prepend
...
I want to migrate from my own nvim plugin library, which was purely based on the lua api, which had these features therefor, to nvim-oxi
as it seems to provide way better ergonomics.
But I would be glad if I could somehow get access to the vim.opts
that is available from lua: example in my API.
Inspired by your crate, I want to use Rust to provide completion list for the cargo add
command so that user can easily get available version when they type @
and get available features when they input -F
through the neovim command line.
I have wrote some simple code to get crate information from crates.io, but now I stuck at not knowing how to return result from async function.
Here is my current implementation: https://github.com/Avimitin/cargo-add-cmp.nvim/blob/master/src/lib.rs#L99. I don't know how to await it and return the list of result as Lua api.
Currently CI does not show us the fact that tests are failing because oxi-tests is excluded from cargo workspace. I will create a PR that fixes this behavior by cding into oxi-tests dir, although the better approach would be extracting tests from a crate and moving to actual tests dir.
One great thing to have would be https://neovim.io/doc/user/lua.html#lua-ui
Sadly they are only usable with callbacks, but with #38 this could maybe be made to be async instead.
Especially because they can be overridden using plugins like telescope.
Currently tests are broken because there is no nvim
binary in PATH.
Rustc: rustc 1.59.0 (9d1b2106e 2022-02-23)
Cargo: cargo 1.59.0 (49d8809dc 2022-02-10)
NeoVim: NVIM v0.8.0-dev+296-g307c5c63e
Error:
Translation of some parts of error message:
ссылка на неразрешённый внешний символ -> link to forbidden external symbol
в функции -> in function
неразрешенных внешних элементов -> forbidden external elements
создается библиотека -> creating a library
Im trying to handle the complete function in the nvim-cmp, in mlua i made it works with the same signature, here i have a double free error. maybe i create Array incorrectly or i do something weird in the func?
Im trying to create something like that
arr = { { "label" = "Jan"} } where it is in index 0.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.