summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/lib.rs102
1 files changed, 101 insertions, 1 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 22e7ce5..06b69c3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -148,7 +148,7 @@
  *         -[x] libdirfs
  *         -[ ] gtkwin_ptr
  *         -[ ] win_ptr
- *     -[ ] hexchat_get_prefs
+ *     -[x] hexchat_get_prefs
  *     -[ ] hexchat_list_get
  *     -[ ] hexchat_list_fields
  *     -[ ] hexchat_list_next
@@ -328,6 +328,14 @@ pub struct PluginHandle<'ph> {
     info: PluginInfo,
 }
 
+/// A setting value, returned by [`PluginHandle::get_prefs`].
+#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
+pub enum PrefValue {
+    String(String),
+    Int(i32),
+    Bool(bool),
+}
+
 mod valid_context {
     use crate::PluginHandle;
 
@@ -403,11 +411,68 @@ pub struct InvalidContextError<F>(F);
 // ***** //
 
 impl<F> InvalidContextError<F> {
+    // TODO docs
     pub fn get_closure(self) -> F {
         self.0
     }
 }
 
+impl_trait! {
+    impl PrefValue {
+        /// Projects this `PrefValue` as `&str`, if it is a `String`. Returns
+        /// `None` otherwise.
+        pub fn as_str(&self) -> Option<&str> {
+            match self {
+                &Self::String(ref s) => Some(s),
+                _ => None,
+            }
+        }
+
+        /// Projects this `PrefValue` as `i32`, if it is an `Int`. Returns
+        /// `None` otherwise.
+        pub fn as_i32(&self) -> Option<i32> {
+            match self {
+                &Self::Int(i) => Some(i),
+                _ => None,
+            }
+        }
+
+        /// Projects this `PrefValue` as `bool`, if it is a `Bool`. Returns
+        /// `None` otherwise.
+        pub fn as_bool(&self) -> Option<bool> {
+            match self {
+                &Self::Bool(b) => Some(b),
+                _ => None,
+            }
+        }
+
+        /// Consumes this `PrefValue` and attempts to take a `String` out of
+        /// it.
+        pub fn into_string(self) -> Option<String> {
+            match self {
+                Self::String(s) => Some(s),
+                _ => None,
+            }
+        }
+
+        impl trait From<String> {
+            fn from(s: String) -> Self {
+                Self::String(s)
+            }
+        }
+        impl trait From<i32> {
+            fn from(i: i32) -> Self {
+                Self::Int(i)
+            }
+        }
+        impl trait From<bool> {
+            fn from(b: bool) -> Self {
+                Self::Bool(b)
+            }
+        }
+    }
+}
+
 impl<'ph, 'f> HookHandle<'ph, 'f> where 'f: 'ph {
     /// If this is a timer hook, returns whether the hook has expired.
     ///
@@ -1187,6 +1252,9 @@ impl<'ph> PluginHandle<'ph> {
         String::from_utf8(out).unwrap()
     }
 
+    // TODO pluginprefs but see: https://developer.gimp.org/api/2.0/glib/glib-String-Utility-Functions.html#g-strescape
+    // var.len() + g_strescape(value).len() + 3 < 512
+
     // ******* //
     // PRIVATE //
     // ******* //
@@ -1212,6 +1280,7 @@ impl<'ph> PluginHandle<'ph> {
 }
 
 impl<'a> EventAttrs<'a> {
+    // TODO docs
     pub fn new() -> EventAttrs<'a> {
         EventAttrs {
             server_time: None,
@@ -1289,6 +1358,7 @@ impl<'a, 'ph: 'a> ValidContext<'a, 'ph> {
         }
     }
 
+    // TODO docs
     pub fn send_modes<'b, I: IntoIterator<Item=&'b str>>(&mut self, iter: I, mpl: i32, sign: char, mode: char) {
         let ph = &self.ph;
         assert!(sign == '+' || sign == '-', "sign must be + or -");
@@ -1303,6 +1373,36 @@ impl<'a, 'ph: 'a> ValidContext<'a, 'ph> {
         }
     }
 
+    /// Returns a client setting.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use hexchat_unsafe_plugin::ValidContext;
+    ///
+    /// /// Returns the user's configured main nick.
+    /// fn main_nick(context: ValidContext<'_, '_>) -> String {
+    ///     context.get_prefs("irc_nick1").unwrap().into_string().unwrap()
+    /// }
+    /// ```
+    pub fn get_prefs(&self, name: &str) -> Option<PrefValue> {
+        let ph = &self.ph;
+        let name = CString::new(name).unwrap();
+        let mut string = 0 as *const c_char;
+        let mut int: c_int = 0;
+        match unsafe {
+            ph_call!(hexchat_get_prefs(ph, name.as_ptr(), &mut string, &mut int))
+        } {
+            0 => None,
+            1 => Some(PrefValue::String(unsafe {
+                CStr::from_ptr(string).to_owned().into_string().unwrap()
+            })),
+            2 => Some(PrefValue::Int(int as _)),
+            3 => Some(PrefValue::Bool(int != 0)),
+            _ => panic!("unsupported type in get_prefs"),
+        }
+    }
+
     /// Executes a command.
     ///
     /// # Examples