1//! Provides the [`IntoText`] trait and implementations.
23use std::borrow::Cow;
45use super::{ClickEvent, Color, Font, HoverEvent, Text};
67/// Trait for any data that can be converted to a [`Text`] object.
8///
9/// Also conveniently provides many useful methods for modifying a [`Text`]
10/// object.
11///
12/// # Usage
13///
14/// ```
15/// # use valence_text::{IntoText, color::NamedColor};
16/// let mut my_text = "".into_text();
17/// my_text = my_text.color(NamedColor::Red).bold();
18/// my_text = my_text.add_child("CRABBBBB".obfuscated());
19pub trait IntoText<'a>: Sized {
20/// Converts to a [`Text`] object, either owned or borrowed.
21fn into_cow_text(self) -> Cow<'a, Text>;
2223/// Converts to an owned [`Text`] object.
24fn into_text(self) -> Text {
25self.into_cow_text().into_owned()
26 }
2728/// Sets the color of the text.
29fn color(self, color: impl Into<Color>) -> Text {
30let mut value = self.into_text();
31 value.color = Some(color.into());
32 value
33 }
34/// Clears the color of the text. Color of parent [`Text`] object will be
35 /// used.
36fn clear_color(self) -> Text {
37let mut value = self.into_text();
38 value.color = None;
39 value
40 }
4142/// Sets the font of the text.
43fn font(self, font: Font) -> Text {
44let mut value = self.into_text();
45 value.font = Some(font);
46 value
47 }
48/// Clears the font of the text. Font of parent [`Text`] object will be
49 /// used.
50fn clear_font(self) -> Text {
51let mut value = self.into_text();
52 value.font = None;
53 value
54 }
5556/// Makes the text bold.
57fn bold(self) -> Text {
58let mut value = self.into_text();
59 value.bold = Some(true);
60 value
61 }
62/// Makes the text not bold.
63fn not_bold(self) -> Text {
64let mut value = self.into_text();
65 value.bold = Some(false);
66 value
67 }
68/// Clears the `bold` property of the text. Property of the parent [`Text`]
69 /// object will be used.
70fn clear_bold(self) -> Text {
71let mut value = self.into_text();
72 value.bold = None;
73 value
74 }
7576/// Makes the text italic.
77fn italic(self) -> Text {
78let mut value = self.into_text();
79 value.italic = Some(true);
80 value
81 }
82/// Makes the text not italic.
83fn not_italic(self) -> Text {
84let mut value = self.into_text();
85 value.italic = Some(false);
86 value
87 }
88/// Clears the `italic` property of the text. Property of the parent
89 /// [`Text`] object will be used.
90fn clear_italic(self) -> Text {
91let mut value = self.into_text();
92 value.italic = None;
93 value
94 }
9596/// Makes the text underlined.
97fn underlined(self) -> Text {
98let mut value = self.into_text();
99 value.underlined = Some(true);
100 value
101 }
102/// Makes the text not underlined.
103fn not_underlined(self) -> Text {
104let mut value = self.into_text();
105 value.underlined = Some(false);
106 value
107 }
108/// Clears the `underlined` property of the text. Property of the parent
109 /// [`Text`] object will be used.
110fn clear_underlined(self) -> Text {
111let mut value = self.into_text();
112 value.underlined = None;
113 value
114 }
115116/// Adds a strikethrough effect to the text.
117fn strikethrough(self) -> Text {
118let mut value = self.into_text();
119 value.strikethrough = Some(true);
120 value
121 }
122/// Removes the strikethrough effect from the text.
123fn not_strikethrough(self) -> Text {
124let mut value = self.into_text();
125 value.strikethrough = Some(false);
126 value
127 }
128/// Clears the `strikethrough` property of the text. Property of the parent
129 /// [`Text`] object will be used.
130fn clear_strikethrough(self) -> Text {
131let mut value = self.into_text();
132 value.strikethrough = None;
133 value
134 }
135136/// Makes the text obfuscated.
137fn obfuscated(self) -> Text {
138let mut value = self.into_text();
139 value.obfuscated = Some(true);
140 value
141 }
142/// Makes the text not obfuscated.
143fn not_obfuscated(self) -> Text {
144let mut value = self.into_text();
145 value.obfuscated = Some(false);
146 value
147 }
148/// Clears the `obfuscated` property of the text. Property of the parent
149 /// [`Text`] object will be used.
150fn clear_obfuscated(self) -> Text {
151let mut value = self.into_text();
152 value.obfuscated = None;
153 value
154 }
155156/// Adds an `insertion` property to the text. When shift-clicked, the given
157 /// text will be inserted into chat box for the client.
158fn insertion(self, insertion: impl Into<Cow<'static, str>>) -> Text {
159let mut value = self.into_text();
160 value.insertion = Some(insertion.into());
161 value
162 }
163/// Clears the `insertion` property of the text. Property of the parent
164 /// [`Text`] object will be used.
165fn clear_insertion(self) -> Text {
166let mut value = self.into_text();
167 value.insertion = None;
168 value
169 }
170171/// On click, opens the given URL. Has to be `http` or `https` protocol.
172fn on_click_open_url(self, url: impl Into<Cow<'static, str>>) -> Text {
173let mut value = self.into_text();
174 value.click_event = Some(ClickEvent::OpenUrl(url.into()));
175 value
176 }
177/// On click, sends a command. Doesn't actually have to be a command, can be
178 /// a simple chat message.
179fn on_click_run_command(self, command: impl Into<Cow<'static, str>>) -> Text {
180let mut value = self.into_text();
181 value.click_event = Some(ClickEvent::RunCommand(command.into()));
182 value
183 }
184/// On click, copies the given text to the chat box.
185fn on_click_suggest_command(self, command: impl Into<Cow<'static, str>>) -> Text {
186let mut value = self.into_text();
187 value.click_event = Some(ClickEvent::SuggestCommand(command.into()));
188 value
189 }
190/// On click, turns the page of the opened book to the given number.
191 /// Indexing starts at `1`.
192fn on_click_change_page(self, page: impl Into<i32>) -> Text {
193let mut value = self.into_text();
194 value.click_event = Some(ClickEvent::ChangePage(page.into()));
195 value
196 }
197/// On click, copies the given text to clipboard.
198fn on_click_copy_to_clipboard(self, text: impl Into<Cow<'static, str>>) -> Text {
199let mut value = self.into_text();
200 value.click_event = Some(ClickEvent::CopyToClipboard(text.into()));
201 value
202 }
203/// Clears the `click_event` property of the text. Property of the parent
204 /// [`Text`] object will be used.
205fn clear_click_event(self) -> Text {
206let mut value = self.into_text();
207 value.click_event = None;
208 value
209 }
210211/// On mouse hover, shows the given text in a tooltip.
212fn on_hover_show_text(self, text: impl IntoText<'static>) -> Text {
213let mut value = self.into_text();
214 value.hover_event = Some(HoverEvent::ShowText(text.into_text()));
215 value
216 }
217/// Clears the `hover_event` property of the text. Property of the parent
218 /// [`Text`] object will be used.
219fn clear_hover_event(self) -> Text {
220let mut value = self.into_text();
221 value.hover_event = None;
222 value
223 }
224225/// Adds a child [`Text`] object.
226fn add_child(self, text: impl IntoText<'static>) -> Text {
227let mut value = self.into_text();
228 value.extra.push(text.into_text());
229 value
230 }
231}
232233impl<'a> IntoText<'a> for Text {
234fn into_cow_text(self) -> Cow<'a, Text> {
235 Cow::Owned(self)
236 }
237}
238impl<'a> IntoText<'a> for &'a Text {
239fn into_cow_text(self) -> Cow<'a, Text> {
240 Cow::Borrowed(self)
241 }
242}
243impl<'a> From<&'a Text> for Text {
244fn from(value: &'a Text) -> Self {
245 value.clone()
246 }
247}
248249impl<'a> IntoText<'a> for Cow<'a, Text> {
250fn into_cow_text(self) -> Cow<'a, Text> {
251self
252}
253}
254impl<'a> From<Cow<'a, Text>> for Text {
255fn from(value: Cow<'a, Text>) -> Self {
256 value.into_owned()
257 }
258}
259impl<'a> IntoText<'a> for &'a Cow<'_, Text> {
260fn into_cow_text(self) -> Cow<'a, Text> {
261self.clone()
262 }
263}
264impl<'a, 'b> From<&'a Cow<'b, Text>> for Text {
265fn from(value: &'a Cow<'b, Text>) -> Self {
266 value.clone().into_owned()
267 }
268}
269270impl<'a> IntoText<'a> for String {
271fn into_cow_text(self) -> Cow<'a, Text> {
272 Cow::Owned(Text::text(self))
273 }
274}
275impl From<String> for Text {
276fn from(value: String) -> Self {
277 value.into_text()
278 }
279}
280impl<'b> IntoText<'b> for &String {
281fn into_cow_text(self) -> Cow<'b, Text> {
282 Cow::Owned(Text::text(self.clone()))
283 }
284}
285impl<'a> From<&'a String> for Text {
286fn from(value: &'a String) -> Self {
287 value.into_text()
288 }
289}
290291impl<'a> IntoText<'a> for Cow<'static, str> {
292fn into_cow_text(self) -> Cow<'a, Text> {
293 Cow::Owned(Text::text(self))
294 }
295}
296impl From<Cow<'static, str>> for Text {
297fn from(value: Cow<'static, str>) -> Self {
298 value.into_text()
299 }
300}
301impl IntoText<'static> for &Cow<'static, str> {
302fn into_cow_text(self) -> Cow<'static, Text> {
303 Cow::Owned(Text::text(self.clone()))
304 }
305}
306impl<'a> From<&'a Cow<'static, str>> for Text {
307fn from(value: &'a Cow<'static, str>) -> Self {
308 value.into_text()
309 }
310}
311312impl<'a> IntoText<'a> for &'static str {
313fn into_cow_text(self) -> Cow<'a, Text> {
314 Cow::Owned(Text::text(self))
315 }
316}
317impl From<&'static str> for Text {
318fn from(value: &'static str) -> Self {
319 value.into_text()
320 }
321}
322323impl<'a, 'b, T: IntoText<'a>, const N: usize> IntoText<'b> for [T; N] {
324fn into_cow_text(self) -> Cow<'b, Text> {
325let mut txt = Text::text("");
326327for child in self {
328 txt = txt.add_child(child.into_cow_text().into_owned());
329 }
330331 Cow::Owned(txt)
332 }
333}
334335impl<'a, 'c, T: IntoText<'a> + Clone, const N: usize> IntoText<'c> for &[T; N] {
336fn into_cow_text(self) -> Cow<'c, Text> {
337let mut txt = Text::text("");
338339for child in self {
340 txt = txt.add_child(child.clone().into_cow_text().into_owned());
341 }
342343 Cow::Owned(txt)
344 }
345}
346347macro_rules! impl_primitives {
348 ($($primitive:ty),+) => {
349 $(
350impl<'a> IntoText<'a> for $primitive {
351fn into_cow_text(self) -> Cow<'a, Text> {
352 Cow::Owned(Text::text(self.to_string()))
353 }
354 }
355 )+
356 };
357}
358impl_primitives! {char, bool, f32, f64, isize, usize, i8, i16, i32, i64, i128, u8, u16, u32, u64, u128}
359360#[cfg(test)]
361mod tests {
362use super::*;
363364#[test]
365 #[allow(clippy::needless_borrows_for_generic_args)]
366fn intotext_trait() {
367fn is_borrowed<'a>(value: impl IntoText<'a>) -> bool {
368matches!(value.into_cow_text(), Cow::Borrowed(..))
369 }
370371assert!(is_borrowed(&"this should be borrowed".into_text()));
372assert!(is_borrowed(&"this should be borrowed too".bold()));
373assert!(!is_borrowed("this should be owned?".bold()));
374assert!(!is_borrowed("this should be owned"));
375assert!(!is_borrowed(465));
376assert!(!is_borrowed(false));
377 }
378}