diff --git a/neovim_sys/src/autocmd.rs b/neovim_sys/src/autocmd.rs index 587eb3a..6bd36db 100644 --- a/neovim_sys/src/autocmd.rs +++ b/neovim_sys/src/autocmd.rs @@ -1,7 +1,7 @@ //! Functions and supporting types from `nvim/autocmd.{c,h}`. //! use crate::types::CharU; -use std::os::raw::c_int; +use std::os::raw::{c_char, c_int}; extern "C" { /// Does an `augroup` with name `name` exist? @@ -11,4 +11,28 @@ extern "C" { /// Defines an `augroup`; `:augroup {name}` or `:augroup! {name}`. /// pub fn do_augroup(name: *const CharU, del_group: c_int); + + /// Defines an `autocmd`. + /// + /// - `:h autocmd-define`: + /// - `:autocmd [group] [++once] [++nested] ` + /// - `:h autocmd-remove`: + /// - `:autocmd! [group] ` + /// - `:autocmd! [group] * ` + /// - `:autocmd! [group] ` + /// - `:autocmd! [group]` + /// - `:h autocmd-list`: + /// - `:autocmd [group] ` + /// - `:autocmd [group] * ` + /// - `:autocmd [group] ` + /// - `:autocmd [group]` + pub fn do_autocmd(arg_in: *const CharU, force_it: c_int); + + /// #Group#Event#pat + /// #Group#Event + /// #Group + /// #Event#pat + /// #Event + /// + pub fn au_exists(arg: *const c_char) -> bool; } diff --git a/nvim_api/src/autocmd.rs b/nvim_api/src/autocmd.rs index 0b00022..936fbfa 100644 --- a/nvim_api/src/autocmd.rs +++ b/nvim_api/src/autocmd.rs @@ -1,5 +1,7 @@ use std::ffi::{CString, NulError}; +use neovim_sys::api::nvim::NvimString; + pub fn augroup(name: &str) -> Result<(), NulError> { let cstring = CString::new(name)?; let api_name = cstring.into_bytes_with_nul(); @@ -18,7 +20,7 @@ pub fn remove_augroup(name: &str) -> Result<(), NulError> { Ok(()) } -pub fn augroup_defined(name: &str) -> Result { +pub fn augroup_exists(name: &str) -> Result { let cstring = CString::new(name)?; let api_name = cstring.into_bytes_with_nul(); @@ -26,3 +28,29 @@ pub fn augroup_defined(name: &str) -> Result { Ok(result) } + +pub fn autocmd(name: &str) -> Result<(), NulError> { + let cstring = CString::new(name)?; + let api_name = cstring.into_bytes_with_nul(); + + unsafe { neovim_sys::autocmd::do_autocmd(api_name.as_ptr(), 0) }; + + Ok(()) +} + +pub fn force_autocmd(name: &str) -> Result<(), NulError> { + let cstring = CString::new(name)?; + let api_name = cstring.into_bytes_with_nul(); + + unsafe { neovim_sys::autocmd::do_autocmd(api_name.as_ptr(), 1) }; + + Ok(()) +} + +pub fn autocmd_exists(name: &str) -> Result { + let cstring = NvimString::new(name)?; + + let result = unsafe { neovim_sys::autocmd::au_exists(cstring.as_ptr()) }; + + Ok(result) +} diff --git a/nvim_api/src/lua_test.rs b/nvim_api/src/lua_test.rs index 2f23082..ebd5b20 100644 --- a/nvim_api/src/lua_test.rs +++ b/nvim_api/src/lua_test.rs @@ -309,9 +309,110 @@ fn test_set_buf_noremap() { fn test_augroup() { crate::autocmd::augroup("Overkill").unwrap(); crate::autocmd::augroup("END").unwrap(); - assert!(crate::autocmd::augroup_defined("Overkill").unwrap()); - assert!(!crate::autocmd::augroup_defined("blarghOverkill").unwrap()); + assert!(crate::autocmd::augroup_exists("Overkill").unwrap()); + assert!(!crate::autocmd::augroup_exists("blarghOverkill").unwrap()); crate::autocmd::remove_augroup("Overkill").unwrap(); - assert!(!crate::autocmd::augroup_defined("Overkill").unwrap()); + assert!(!crate::autocmd::augroup_exists("Overkill").unwrap()); +} + +#[nvim_test] +fn test_autocmd() { + // Undefined event or group shouldn't exist + { + assert!(!crate::autocmd::autocmd_exists("NotAnEventOrGroup").unwrap()); + } + + // Ungrouped, built-in events... + { + crate::autocmd::autocmd("FileChangedShell *.meow,*.bobo echo hi").unwrap(); + assert!(crate::autocmd::autocmd_exists("FileChangedShell").unwrap()); + assert!(crate::autocmd::autocmd_exists("FileChangedShell *.meow").unwrap()); + assert!(crate::autocmd::autocmd_exists("FileChangedShell *.bobo").unwrap()); + assert!(crate::autocmd::autocmd_exists("FileChangedShell *.meow,*.bobo").unwrap()); + } + + // Ungrouped, user-defined events... + { + crate::autocmd::autocmd("User OverkillThing echo hi").unwrap(); + + // Any ungrouped User event will return true + assert!(crate::autocmd::autocmd_exists("User OverkillThing").unwrap()); + + // ...but one with a group will fail + assert!(!crate::autocmd::autocmd_exists("SomeGroup User NotOverkillThing").unwrap()); + } + + // Grouped, built-in events + { + crate::autocmd::augroup("OverkillBuiltIn").unwrap(); + crate::autocmd::autocmd("FileChangedShell *.meow,*.bobo echo hi").unwrap(); + crate::autocmd::augroup("END").unwrap(); + + assert!(crate::autocmd::autocmd_exists("OverkillBuiltIn#FileChangedShell#*.meow").unwrap()); + assert!(crate::autocmd::autocmd_exists("OverkillBuiltIn#FileChangedShell").unwrap()); + assert!(crate::autocmd::autocmd_exists("OverkillBuiltIn").unwrap()); + assert!(crate::autocmd::autocmd_exists("FileChangedShell#*.bobo").unwrap()); + assert!(crate::autocmd::autocmd_exists("FileChangedShell").unwrap()); + + assert!(!crate::autocmd::autocmd_exists("OverkillBuiltIn#FileChangedShell#*.txt").unwrap()); + assert!(!crate::autocmd::autocmd_exists("FileChangedShell#*.txt").unwrap()); + } + + // Grouped, user-defined events + { + crate::autocmd::augroup("OverkillUserDef").unwrap(); + crate::autocmd::autocmd("User OverkillThing echo hi").unwrap(); + crate::autocmd::augroup("END").unwrap(); + + assert!(crate::autocmd::autocmd_exists("OverkillUserDef#User OverkillThing").unwrap()); + assert!(crate::autocmd::autocmd_exists("OverkillUserDef").unwrap()); + assert!(crate::autocmd::autocmd_exists("User OverkillThing").unwrap()); + } +} + +#[nvim_test] +fn test_force_autocmd() { + // Ungrouped, built-in events... + { + crate::autocmd::autocmd("UILeave *.meow echo hi").unwrap(); + crate::autocmd::force_autocmd("UILeave *.meow echo bye").unwrap(); + + assert!(crate::autocmd::autocmd_exists("UILeave").unwrap()); + assert!(crate::autocmd::autocmd_exists("UILeave *.meow").unwrap()); + } + + // Ungrouped, user-defined events... + { + crate::autocmd::autocmd("User OverkillThing echo hi").unwrap(); + crate::autocmd::force_autocmd("User OverkillThing echo bye").unwrap(); + + assert!(crate::autocmd::autocmd_exists("User OverkillThing").unwrap()); + } + + // Grouped, built-in events + { + crate::autocmd::augroup("OverkillBuiltIn").unwrap(); + crate::autocmd::autocmd("UILeave *.meow echo hi").unwrap(); + crate::autocmd::augroup("END").unwrap(); + + crate::autocmd::augroup("OverkillBuiltIn").unwrap(); + crate::autocmd::autocmd("UILeave *.meow echo bye").unwrap(); + crate::autocmd::augroup("END").unwrap(); + + assert!(crate::autocmd::autocmd_exists("OverkillBuiltIn#UILeave#*.meow").unwrap()); + } + + // Grouped, user-defined events + { + crate::autocmd::augroup("OverkillUserDef").unwrap(); + crate::autocmd::autocmd("User OverkillThing echo hi").unwrap(); + crate::autocmd::augroup("END").unwrap(); + + crate::autocmd::augroup("OverkillUserDef").unwrap(); + crate::autocmd::force_autocmd("User OverkillThing echo bye").unwrap(); + crate::autocmd::augroup("END").unwrap(); + + assert!(crate::autocmd::autocmd_exists("OverkillUserDef#User OverkillThing").unwrap()); + } } diff --git a/tests/plenary/nvim_api_spec.lua b/tests/plenary/nvim_api_spec.lua index 8038867..3183732 100644 --- a/tests/plenary/nvim_api_spec.lua +++ b/tests/plenary/nvim_api_spec.lua @@ -16,6 +16,8 @@ ffi.cdef [[ bool test_set_buf_noremap(); bool test_augroup(); + bool test_autocmd(); + bool test_force_autocmd(); ]] local suffix = ffi.os == "OSX" and ".dylib" or ".so" @@ -98,5 +100,17 @@ describe( assert.True(lib.test_augroup()) end ) + it( + "tests autocmd::autocmd()", + function() + assert.True(lib.test_autocmd()) + end + ) + it( + "tests autocmd::force_autocmd()", + function() + assert.True(lib.test_force_autocmd()) + end + ) end )