hexchat_unsafe_plugin/
word.rs

1// This file is part of Hexchat Plugin API Bindings for Rust
2// Copyright (C) 2018, 2021, 2022 Soni L.
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as
6// published by the Free Software Foundation, either version 3 of the
7// License, or (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17use std::ffi::CStr;
18use std::ops::Deref;
19
20/// Arguments passed to a hook, until the next argument.
21///
22/// # Examples
23/// 
24/// ```no_run
25/// use hexchat_unsafe_plugin::{PluginHandle, Word, WordEol, Eat};
26///
27/// fn cmd_foo(ph: &mut PluginHandle, arg: Word, arg_eol: WordEol) -> Eat {
28///     if arg.len() < 3 {
29///         ph.print("Not enough arguments");
30///     } else {
31///         ph.print(&format!("{} {} {}", arg[0], arg[1], arg[2]));
32///     }
33///     hexchat_unsafe_plugin::EAT_ALL
34/// }
35///
36/// fn on_privmsg(ph: &mut PluginHandle, word: Word, word_eol: WordEol) -> Eat {
37///     if word.len() > 0 && word[0].starts_with('@') {
38///         ph.print("We have message tags!?");
39///     }
40///     hexchat_unsafe_plugin::EAT_NONE
41/// }
42/// ```
43pub struct Word<'a> {
44    word: Vec<&'a str>
45}
46
47/// Arguments passed to a hook, until the end of the line.
48///
49/// # Examples
50/// 
51/// ```no_run
52/// use hexchat_unsafe_plugin::{PluginHandle, Word, WordEol, Eat};
53///
54/// fn cmd_foo(ph: &mut PluginHandle, arg: Word, arg_eol: WordEol) -> Eat {
55///     if arg.len() < 3 {
56///         ph.print("Not enough arguments");
57///     } else {
58///         ph.print(&format!("{} {} {}", arg[0], arg[1], arg_eol[2]));
59///     }
60///     hexchat_unsafe_plugin::EAT_ALL
61/// }
62///
63/// fn on_privmsg(ph: &mut PluginHandle, word: Word, word_eol: WordEol) -> Eat {
64///     if word_eol.len() > 0 && word[0].starts_with('@') {
65///         ph.print("We have message tags!?");
66///     }
67///     hexchat_unsafe_plugin::EAT_NONE
68/// }
69/// ```
70pub struct WordEol<'a> {
71    word_eol: Vec<&'a str>
72}
73
74impl<'a> Word<'a> {
75    /// Creates a new Word.
76    ///
77    /// # Safety
78    ///
79    /// Uses raw pointers.
80    pub(crate) unsafe fn new(word: *const *const libc::c_char) -> Word<'a> {
81        let mut vec = vec![];
82        for i in 1..32 {
83            let w = *word.offset(i);
84            if !w.is_null() {
85                vec.push(CStr::from_ptr(w).to_str().expect("non-utf8 word - broken hexchat"))
86            }
87        }
88        while let Some(&"") = vec.last() {
89            vec.pop();
90        }
91        Word { word: vec }
92    }
93}
94
95/// Provides access to the contents of the Word.
96impl<'a> Deref for Word<'a> {
97    type Target = [&'a str];
98    fn deref(&self) -> &[&'a str] {
99        &self.word
100    }
101}
102
103impl<'a> WordEol<'a> {
104    /// Creates a new WordEol.
105    ///
106    /// # Safety
107    ///
108    /// Uses raw pointers.
109    pub(crate) unsafe fn new(word_eol: *const *const libc::c_char) -> WordEol<'a> {
110        let mut vec = vec![];
111        for i in 1..32 {
112            let w = *word_eol.offset(i);
113            if !w.is_null() {
114                vec.push(CStr::from_ptr(w).to_str().expect("non-utf8 word_eol - broken hexchat"))
115            }
116        }
117        while let Some(&"") = vec.last() {
118            vec.pop();
119        }
120        WordEol { word_eol: vec }
121    }
122}
123
124/// Provides access to the contents of the WordEol.
125impl<'a> Deref for WordEol<'a> {
126    type Target = [&'a str];
127    fn deref(&self) -> &[&'a str] {
128        &self.word_eol
129    }
130}