diff --git a/.cargo/config.toml b/.cargo/config.toml index d47f983..4616de1 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,11 +1,11 @@ [target.x86_64-apple-darwin] -rustflags = [ - "-C", "link-arg=-undefined", - "-C", "link-arg=dynamic_lookup", -] +rustflags = ["-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup"] [target.aarch64-apple-darwin] -rustflags = [ - "-C", "link-arg=-undefined", - "-C", "link-arg=dynamic_lookup", -] +rustflags = ["-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup"] + +[target.x86_64-pc-windows-msvc] +rustflags = ["-C", "link-args=/FORCE:MULTIPLE"] + +[target.aarch64-pc-windows-msvc] +rustflags = ["-C", "link-args=/FORCE:MULTIPLE"] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d5e2cb3..cc76438 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,11 +34,16 @@ jobs: with: neovim: true version: ${{ matrix.neovim }} + - name: Install libluajit (Linux) + if: runner.os == 'Linux' + run: sudo apt-get update && sudo apt-get install -y libluajit-5.1-dev + - name: Install libluajit (macOS) + if: runner.os == 'macOS' + run: brew install luajit - name: Install latest stable `rustc` uses: dtolnay/rust-toolchain@stable - name: Run tests run: cargo test --workspace ${{ matrix.features }} - working-directory: . clippy: name: clippy diff --git a/CHANGELOG.md b/CHANGELOG.md index 936c838..d17f246 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,10 @@ - the argument of `SetHighlightOptsBuilder::link()` from `&str` to any type implementing `HlGroup`; +- `nvim_oxi::api::notify()` now takes a `&Dictionary` instead of `&NotifyOpts` + at its third parameter, and returns `Result` instead of `Result<()>` + ([#208](https://github.com/noib3/nvim-oxi/pull/208)); + ### Removed - the `SetHighlightOptsBuilder::global_link()` method. Use diff --git a/Cargo.toml b/Cargo.toml index 250539d..9b11db7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,7 +64,6 @@ cargo_metadata = { version = "0.19", optional = true } mlua = { version = "0.10", features = ["luajit"], optional = true } [dev-dependencies] -mlua = { version = "0.10", features = ["luajit", "module"] } serde = { version = "1.0", features = ["derive"] } tokio = { version = "1.0", features = ["full"] } diff --git a/crates/api/src/ffi/vim.rs b/crates/api/src/ffi/vim.rs index 3c1e282..d044896 100644 --- a/crates/api/src/ffi/vim.rs +++ b/crates/api/src/ffi/vim.rs @@ -252,6 +252,8 @@ extern "C" { msg: NonOwning, log_level: Integer, opts: NonOwning, + #[cfg(feature = "neovim-0-10")] // On 0.10 and Nightly. + arena: *mut Arena, err: *mut Error, ) -> Object; diff --git a/crates/api/src/opts/mod.rs b/crates/api/src/opts/mod.rs index 57a8670..76113fc 100644 --- a/crates/api/src/opts/mod.rs +++ b/crates/api/src/opts/mod.rs @@ -25,7 +25,6 @@ mod get_mark; #[cfg(feature = "neovim-0-10")] // On 0.10 and nightly. mod get_namespace; mod get_text; -mod notify; mod open_term; mod option; mod parse_cmd; @@ -61,7 +60,6 @@ pub use get_mark::*; #[cfg(feature = "neovim-0-10")] // On 0.10 and nightly. pub use get_namespace::*; pub use get_text::*; -pub use notify::*; pub use open_term::*; pub use option::*; pub use parse_cmd::*; diff --git a/crates/api/src/opts/notify.rs b/crates/api/src/opts/notify.rs deleted file mode 100644 index cd787a2..0000000 --- a/crates/api/src/opts/notify.rs +++ /dev/null @@ -1,28 +0,0 @@ -use types::Dictionary; - -/// Options passed to [`notify()`](crate::notify). Currently unused. -#[derive(Clone, Debug, Default)] -pub struct NotifyOpts {} - -impl NotifyOpts { - #[inline(always)] - pub fn builder() -> NotifyOptsBuilder { - NotifyOptsBuilder::default() - } -} - -#[derive(Clone, Default)] -pub struct NotifyOptsBuilder(NotifyOpts); - -impl NotifyOptsBuilder { - #[inline] - pub fn build(&mut self) -> NotifyOpts { - std::mem::take(&mut self.0) - } -} - -impl From<&NotifyOpts> for Dictionary { - fn from(_: &NotifyOpts) -> Self { - Dictionary::new() - } -} diff --git a/crates/api/src/vim.rs b/crates/api/src/vim.rs index 4ed9977..6a8d204 100644 --- a/crates/api/src/vim.rs +++ b/crates/api/src/vim.rs @@ -715,20 +715,21 @@ pub fn load_context(ctx: EditorContext) { pub fn notify( msg: &str, log_level: LogLevel, - opts: &NotifyOpts, -) -> Result<()> { + opts: &Dictionary, +) -> Result { let msg = nvim::String::from(msg); - let opts = Dictionary::from(opts); let mut err = nvim::Error::new(); - let _ = unsafe { + let obj = unsafe { nvim_notify( msg.non_owning(), log_level as Integer, opts.non_owning(), + #[cfg(feature = "neovim-0-10")] // On 0.10 and nightly. + types::arena(), &mut err, ) }; - choose!(err, ()) + choose!(err, Ok(obj)) } /// Binding to [`nvim_open_term()`][1]. diff --git a/crates/types/src/error.rs b/crates/types/src/error.rs index 9b20c5a..a6dd71d 100644 --- a/crates/types/src/error.rs +++ b/crates/types/src/error.rs @@ -2,12 +2,10 @@ use std::error::Error as StdError; use std::ffi::{c_char, CStr, CString}; use std::fmt; -use thiserror::Error as ThisError; - // https://github.com/neovim/neovim/blob/v0.9.0/src/nvim/api/private/defs.h#L64-L67 // /// Binding to the error type used by Neovim. -#[derive(Clone, ThisError, Eq, PartialEq, Hash)] +#[derive(Clone, Eq, PartialEq, Hash)] #[repr(C)] pub struct Error { r#type: ErrorType, @@ -16,6 +14,7 @@ pub struct Error { unsafe impl Send for Error {} unsafe impl Sync for Error {} +impl StdError for Error {} // https://github.com/neovim/neovim/blob/v0.9.0/src/nvim/api/private/defs.h#L27-L31 #[derive(Copy, Clone, Eq, PartialEq, Hash)] diff --git a/examples/mlua.rs b/examples/mlua.rs index 4345724..b0b1b23 100644 --- a/examples/mlua.rs +++ b/examples/mlua.rs @@ -1,11 +1,11 @@ use mlua::prelude::LuaFunction; -use nvim_oxi::{mlua::lua, print, Result}; +use nvim_oxi::{mlua, print, Result}; #[nvim_oxi::plugin] fn mlua() -> Result<()> { print!("Hello from nvim-oxi.."); - let lua = lua(); + let lua = mlua::lua(); let print: LuaFunction = lua.globals().get("print")?; - print.call("..and goodbye from mlua!")?; + print.call::<()>("..and goodbye from mlua!")?; Ok(()) } diff --git a/tests/Cargo.toml b/tests/Cargo.toml index cb0d965..fb37871 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -13,13 +13,15 @@ neovim-0-9 = ["nvim-oxi/neovim-0-9"] neovim-0-10 = ["neovim-0-9", "nvim-oxi/neovim-0-10"] neovim-nightly = ["neovim-0-10", "nvim-oxi/neovim-nightly"] -[target.'cfg(not(any(target_os = "windows", target_env = "msvc")))'.dependencies] +[dependencies] all_asserts = "2.3" -nvim-oxi = { path = "..", features = ["libuv", "test"] } +thiserror = { workspace = true } + +[target.'cfg(not(any(target_os = "windows", target_env = "msvc")))'.dependencies] +nvim-oxi = { path = "..", features = ["libuv", "mlua", "test"] } [target.'cfg(any(target_os = "windows", target_env = "msvc"))'.dependencies] -all_asserts = "2.3" -nvim-oxi = { path = "..", features = ["test"] } +nvim-oxi = { path = "..", features = ["mlua", "test", "__vendored_luajit"] } [build-dependencies] nvim-oxi = { path = "..", features = ["test"] } diff --git a/tests/src/api/global.rs b/tests/src/api/global.rs index 072cddc..c1db1d0 100644 --- a/tests/src/api/global.rs +++ b/tests/src/api/global.rs @@ -1,5 +1,9 @@ +use std::sync::Arc; + use all_asserts::*; use nvim_oxi::api::{self, opts::*, types::*, Buffer, Window}; +use nvim_oxi::mlua::{Error as LuaError, IntoLuaMulti, Lua, Table}; +use nvim_oxi::{Dictionary, Object}; #[nvim_oxi::test] fn chan_send_fail() { @@ -176,6 +180,46 @@ fn list_wins() { ); } +#[nvim_oxi::test] +fn notify() { + let opts = Dictionary::new(); + let ret = api::notify("", LogLevel::Error, &opts).unwrap(); + assert_eq!(ret, Object::nil()); +} + +// Fails on 0.9.5 on macOS and Windows. Not sure why. +#[nvim_oxi::test] +#[cfg_attr(not(any(target_os = "linux", feature = "neovim-0-10")), ignore)] +fn notify_custom() { + let message = "Notifier was called!"; + + // Set up a custom notification provider. + set_notification_provider(move |lua, _msg, _level, _opts| { + lua.create_string(message) + }); + + let opts = Dictionary::new(); + let ret = api::notify("", LogLevel::Error, &opts).unwrap(); + assert_eq!(ret, message.into()); +} + +// Fails on 0.9.5 on macOS and Windows. Not sure why. +#[nvim_oxi::test] +#[cfg_attr(not(any(target_os = "linux", feature = "neovim-0-10")), ignore)] +fn notify_custom_err() { + #[derive(Debug, thiserror::Error)] + #[error("")] + struct CustomError; + + // Set up a custom notification provider. + set_notification_provider(move |_lua, _msg, _level, _opts| { + Err::<(), _>(LuaError::ExternalError(Arc::new(CustomError))) + }); + + let opts = Dictionary::new(); + let _err = api::notify("", LogLevel::Error, &opts).unwrap_err(); +} + #[nvim_oxi::test] fn set_get_del_current_line() { let res = api::set_current_line("foo"); @@ -273,3 +317,18 @@ fn hex_to_dec(hex_color: &str) -> u32 { || ('a'..='f').contains(&c.to_ascii_lowercase()))); u32::from_str_radix(&hex_color[1..], 16).unwrap() } + +fn set_notification_provider(mut provider: P) +where + P: FnMut(&Lua, String, u32, Table) -> Result + 'static, + R: IntoLuaMulti, +{ + let lua = nvim_oxi::mlua::lua(); + let vim = lua.globals().get::("vim").unwrap(); + let notify = lua + .create_function_mut(move |lua, (msg, level, opts)| { + provider(lua, msg, level, opts) + }) + .unwrap(); + vim.set("notify", notify).unwrap(); +}