diff options
Diffstat (limited to 'src/word.rs')
-rw-r--r-- | src/word.rs | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/word.rs b/src/word.rs new file mode 100644 index 0000000..8bcabfc --- /dev/null +++ b/src/word.rs @@ -0,0 +1,130 @@ +// This file is part of Hexchat Plugin API Bindings for Rust +// Copyright (C) 2018, 2021 Soni L. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// 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/>. + +use std::ffi::CStr; +use std::ops::Deref; + +/// Arguments passed to a hook, until the next argument. +/// +/// # Examples +/// +/// ```no_run +/// 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 +/// +/// ```no_run +/// 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> +} + +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 + } +} |