// This file is part of Hexchat Plugin API Bindings for Rust // Copyright (C) 2018, 2021, 2022 Soni L. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . use std::ffi::CStr; use std::ops::Deref; /// Arguments passed to a hook, until the next argument. /// /// # Examples /// /// ```no_run /// use hexchat_unsafe_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_unsafe_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_unsafe_plugin::EAT_NONE /// } /// ``` pub struct Word<'a> { word: Vec<&'a str> } /// Arguments passed to a hook, until the end of the line. /// /// # Examples /// /// ```no_run /// use hexchat_unsafe_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_unsafe_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_unsafe_plugin::EAT_NONE /// } /// ``` pub struct WordEol<'a> { word_eol: Vec<&'a str> } impl<'a> Word<'a> { /// Creates a new Word. /// /// # Safety /// /// Uses raw pointers. pub(crate) unsafe fn new(word: *const *const libc::c_char) -> Word<'a> { let mut vec = vec![]; for i in 1..32 { let w = *word.offset(i); if !w.is_null() { vec.push(CStr::from_ptr(w).to_str().expect("non-utf8 word - broken hexchat")) } } while let Some(&"") = vec.last() { vec.pop(); } Word { word: vec } } } /// Provides access to the contents of the Word. impl<'a> Deref for Word<'a> { type Target = [&'a str]; fn deref(&self) -> &[&'a str] { &self.word } } impl<'a> WordEol<'a> { /// Creates a new WordEol. /// /// # Safety /// /// Uses raw pointers. pub(crate) unsafe fn new(word_eol: *const *const libc::c_char) -> WordEol<'a> { let mut vec = vec![]; for i in 1..32 { let w = *word_eol.offset(i); if !w.is_null() { vec.push(CStr::from_ptr(w).to_str().expect("non-utf8 word_eol - broken hexchat")) } } while let Some(&"") = vec.last() { vec.pop(); } WordEol { word_eol: vec } } } /// Provides access to the contents of the WordEol. impl<'a> Deref for WordEol<'a> { type Target = [&'a str]; fn deref(&self) -> &[&'a str] { &self.word_eol } }