summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorSoniEx2 <endermoneymod@gmail.com>2018-09-29 23:40:56 -0300
committerSoniEx2 <endermoneymod@gmail.com>2018-09-29 23:40:56 -0300
commit5bf1df10b12c95c0d6b33ccdb53f8d4caf6ee670 (patch)
tree1cc8ef59929344b6e52414f0f28528a3f0ec82ce
parentea4fc42c0ddc9b4d97b587926a0b99167778bff0 (diff)
Improved docs
-rw-r--r--src/lib.rs175
1 files changed, 170 insertions, 5 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 8519a25..2235e5b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -15,7 +15,46 @@
  * You should have received a copy of the GNU Affero General Public License
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
-//! <!-- TODO (placeholder) -->
+//! Write hexchat plugins in Rust!
+//!
+//! This library provides safe API bindings for hexchat, but doesn't attempt to fix hexchat's own
+//! bugs. It makes no effort to stop you from unloading your own code while it's still running, for
+//! example.
+//!
+//! When using this library, it's strongly recommended to avoid heap-allocated statics (static
+//! mutexes, lazy_static, etc). This is because it's currently impossible to deallocate those on
+//! plugin unload. This can be worked around by placing those statics as fields in your plugin
+//! struct.
+//!
+//! This caveat does not apply to static assets (`static FOO: &'static str`, for example), but it
+//! does apply to thread-local storage.
+//! 
+//! # Examples
+//!
+//! ```
+//! #[macro_use]
+//! extern crate hexchat_plugin;
+//!
+//! use hexchat_plugin::{Plugin, PluginHandle};
+//!
+//! #[derive(Default)]
+//! struct MyPlugin {}
+//!
+//! impl Plugin for MyPlugin {
+//!     fn init(&self, ph: &mut PluginHandle, arg: Option<&str>) -> bool {
+//!         ph.register("myplugin", "0.1.0", "my simple plugin");
+//!         ph.hook_command("hello-world", |ph, arg, arg_eol| {
+//!             ph.print("Hello, World!");
+//!             hexchat_plugin::EAT_ALL
+//!         }, 0, Some("prints 'Hello, World!'"));
+//!         true
+//!     }
+//! }
+//!
+//! hexchat_plugin!(MyPlugin);
+//!
+//! # fn main() { } // satisfy the compiler, we can't actually run the code
+//! ```
 
 /*
  * Some info about how HexChat does things:
@@ -176,7 +215,17 @@ pub trait Plugin {
 
 // Structs
 
-/// A hexchat plugin handle.
+/// A hexchat plugin handle, used to register hooks and interact with hexchat.
+///
+/// # Examples
+///
+/// ```
+/// use hexchat_plugin::{PluginHandle};
+///
+/// fn init(ph: &mut PluginHandle) {
+///     ph.register("myplug", "0.1.0", "my awesome plug");
+/// }
+/// ```
 pub struct PluginHandle {
     ph: *mut internals::Ph,
     // Used for registration
@@ -184,16 +233,62 @@ pub struct PluginHandle {
 }
 
 /// Arguments passed to a hook, until the next argument.
+///
+/// # Examples
+/// 
+/// ```
+/// use hexchat_plugin::{PluginHandle, Word, WordEol, Eat};
+///
+/// fn cmd_foo(ph: &mut PluginHandle, arg: Word, arg_eol: WordEol) -> Eat {
+///     if arg.len() < 3 {
+///         ph.print("Not enough arguments");
+///     } else {
+///         ph.print(&format!("{} {} {}", arg[0], arg[1], arg[2]));
+///     }
+///     hexchat_plugin::EAT_ALL
+/// }
+///
+/// fn on_privmsg(ph: &mut PluginHandle, word: Word, word_eol: WordEol) -> Eat {
+///     if word.len() > 0 && word[0].starts_with('@') {
+///         ph.print("We have message tags!?");
+///     }
+///     hexchat_plugin::EAT_NONE
+/// }
+/// ```
 pub struct Word<'a> {
     word: Vec<&'a str>
 }
 
 /// Arguments passed to a hook, until the end of the line.
+///
+/// # Examples
+/// 
+/// ```
+/// use hexchat_plugin::{PluginHandle, Word, WordEol, Eat};
+///
+/// fn cmd_foo(ph: &mut PluginHandle, arg: Word, arg_eol: WordEol) -> Eat {
+///     if arg.len() < 3 {
+///         ph.print("Not enough arguments");
+///     } else {
+///         ph.print(&format!("{} {} {}", arg[0], arg[1], arg_eol[2]));
+///     }
+///     hexchat_plugin::EAT_ALL
+/// }
+///
+/// fn on_privmsg(ph: &mut PluginHandle, word: Word, word_eol: WordEol) -> Eat {
+///     if word_eol.len() > 0 && word[0].starts_with('@') {
+///         ph.print("We have message tags!?");
+///     }
+///     hexchat_plugin::EAT_NONE
+/// }
+/// ```
 pub struct WordEol<'a> {
     word_eol: Vec<&'a str>
 }
 
 /// A safety wrapper to ensure you're working with a valid context.
+///
+/// This mechanism attempts to reduce the likelihood of segfaults.
 pub struct EnsureValidContext<'a> {
     ph: &'a mut PluginHandle,
 }
@@ -206,8 +301,10 @@ pub struct EventAttrs<'a> {
     _dummy: PhantomData<&'a ()>,
 }
 
-/// An status indicator for event callbacks. Indicates whether to continue processing, eat hexchat,
+/// A status indicator for event callbacks. Indicates whether to continue processing, eat hexchat,
 /// eat plugin, or eat all.
+///
+/// Returned by most hooks.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct Eat {
     do_eat: i32,
@@ -436,11 +533,21 @@ impl PluginHandle {
         }
     }
 
-    /// Registers this hexchat plugin.
+    /// Registers this hexchat plugin. This must be called exactly once when the plugin is loaded.
     ///
     /// # Panics
     ///
     /// This function panics if this plugin is already registered.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use hexchat_plugin::PluginHandle;
+    ///
+    /// fn init(ph: &mut PluginHandle) {
+    ///     ph.register("foo", "0.1.0", "my foo plugin");
+    /// }
+    /// ```
     pub fn register(&mut self, name: &str, desc: &str, ver: &str) {
         unsafe {
             let info = self.info;
@@ -574,7 +681,20 @@ impl PluginHandle {
         }
     }
 
-    /// Sets a command hook
+    /// Sets a command hook.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use hexchat_plugin::PluginHandle;
+    ///
+    /// fn register_commands(ph: &mut PluginHandle) {
+    ///     ph.hook_command("hello-world", |ph, arg, arg_eol| {
+    ///         ph.print("Hello, World!");
+    ///         hexchat_plugin::EAT_ALL
+    ///     }, 0, Some("prints 'Hello, World!'"));
+    /// }
+    /// ```
     pub fn hook_command<F>(&mut self, cmd: &str, cb: F, pri: i32, help: Option<&str>) -> CommandHookHandle where F: Fn(&mut PluginHandle, Word, WordEol) -> Eat + 'static + ::std::panic::RefUnwindSafe {
         unsafe extern "C" fn callback(word: *const *const libc::c_char, word_eol: *const *const libc::c_char, ud: *mut libc::c_void) -> libc::c_int {
             // hook may unhook itself.
@@ -609,6 +729,21 @@ impl PluginHandle {
         }
     }
     /// Sets a server hook.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use hexchat_plugin::PluginHandle;
+    ///
+    /// fn register_server_hooks(ph: &mut PluginHandle) {
+    ///     ph.hook_server("PRIVMSG", |ph, word, word_eol| {
+    ///         if word.len() > 0 && word[0].starts_with('@') {
+    ///             ph.print("We have message tags!?");
+    ///         }
+    ///         hexchat_plugin::EAT_NONE
+    ///     }, 0);
+    /// }
+    /// ```
     pub fn hook_server<F>(&mut self, cmd: &str, cb: F, pri: i32) -> ServerHookHandle where F: Fn(&mut PluginHandle, Word, WordEol) -> Eat + 'static + ::std::panic::RefUnwindSafe {
         self.hook_server_attrs(cmd, move |ph, w, we, _| cb(ph, w, we), pri)
     }
@@ -646,6 +781,23 @@ impl PluginHandle {
         }
     }
     /// Sets a print hook.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use hexchat_plugin::PluginHandle;
+    ///
+    /// fn register_print_hooks(ph: &mut PluginHandle) {
+    ///     ph.hook_print("Channel Message", |ph, arg| {
+    ///         if let Some(nick) = word.get(0) {
+    ///             if nick == "KnOwN_SpAmMeR" {
+    ///                 return hexchat_plugin::EAT_ALL
+    ///             }
+    ///         }
+    ///         hexchat_plugin::EAT_NONE
+    ///     }, 0);
+    /// }
+    /// ```
     pub fn hook_print<F>(&mut self, name: &str, cb: F, pri: i32) -> PrintHookHandle where F: Fn(&mut PluginHandle, Word) -> Eat + 'static + ::std::panic::RefUnwindSafe {
         self.hook_print_attrs(name, move |ph, w, _| cb(ph, w), pri)
     }
@@ -682,6 +834,19 @@ impl PluginHandle {
         }
     }
     /// Sets a timer hook
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use hexchat_plugin::PluginHandle;
+    ///
+    /// fn register_timers(ph: &mut PluginHandle) {
+    ///     ph.hook_timer(|ph| {
+    ///         ph.print("timer up!");
+    ///         false
+    ///     }, 2000);
+    /// }
+    /// ```
     pub fn hook_timer<F>(&mut self, timeout: i32, cb: F) -> TimerHookHandle where F: Fn(&mut PluginHandle) -> bool + 'static + ::std::panic::RefUnwindSafe {
         unsafe extern "C" fn callback(ud: *mut libc::c_void) -> libc::c_int {
             // hook may unhook itself.