1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// # LobsterChat
//!
//! A Minecraft [Chat Component](https://wiki.vg/Chat) and [Adventure MiniMessage](https://docs.adventure.kyori.net/minimessage/index.html) implementation in Rust.
//!
//! ## Examples
//!
//! ### Without minimessage
//!
//! ```rust
//! use lobsterchat::component::*;
//!
//! let text_component: Component = Component::text("Hello, World! ")
//!                     .color(0xFFAAFF)
//!                     .click_event(ClickEvent::open_url("https://github.com/Maxuss/lobster"))
//!                     .append(
//!                         Component::translatable("my.translation.key")
//!                         .color(NamedColor::Gold)
//!                         .hover_event(HoverEvent::ShowText(Component::text("Click for surprise!")))
//!                         .insert_text("I love lobsterchat!")
//!                     )
//!                     .append(
//!                         Component::keybind("key.sprint")
//!                         .bold(true)
//!                         .italic(false)
//!                     );
//!
//! println!("{}", text_component.to_string());
//! ```
//!
//! ### With minimessage
//!
//! ```rust
//! use lobsterchat::message::*;
//! use lobsterchat::component::{Component, Colored, NamedColor};
//!
//! let component: Component = lobster("<gold><bold>This is some message!</bold> <blue>Some blue text <#AAFFAA>Some hex text!");
//! let placeholdered: Component = placeholder_lobster(
//!     "Some normal text. <first> And then <gold><second>.",
//!     [
//!         (
//!             "first",
//!             Component::text("Some replacement.").color(NamedColor::Gold)
//!         ),
//!         (
//!             "second",
//!             Component::translatable("translated.text.key")
//!         )
//!     ])
//! ```
//!
//! Enable minimessage with the `minimessage` crate feature
//!
//! ### Speed:
//!
//! ```text
//! running 1 test
//! test tests::benchmark_lobster ... bench:       6,335 ns/iter (+/- 147)
//! ```
//!
//! So around 6mcs to convert message into a component.
//!
// ### Features
//!
//! - #### Components:
//! - [x] Component types (literal, translatable, etc.)
//! - [x] Formatting and colors
//! - [x] Click / Hover events in components
//!
//! - #### MiniMessage
//! - [x] Named color tags (e.g. `<red>, <blue>`)
//! - [x] Hex color tags (e.g. `<#AAFFAA>`)
//! - [x] Formatting tags (e.g. `<bold>, <reset>`)
//! - [x] Placeholder tags
//! - [ ] Hover / Click Events
//! - [ ] Advanced formatting tags (e.g. `<rainbow>, <gradient>`)

#![warn(missing_docs)]

pub mod component;
#[cfg(feature = "minimessage")]
pub mod message;
#[cfg(feature = "minimessage")]
pub use message::{lobster, placeholder_lobster};

#[cfg(test)]
#[cfg(feature = "minimessage")]
mod tests {
    #![allow(soft_unstable)]

    use crate::component::{AsComponent, ClickEvent, Component, HoverEvent};
    use crate::message::tokens::{MessageToken, Parser};
    use crate::{lobster, placeholder_lobster};
    use logos::Lexer;
    use logos::Logos;

    #[test]
    fn test_components() {
        let cmp = Component::text("Text component")
            .insert_text("Some text")
            .hover_event(HoverEvent::show_text("Some text".as_component()))
            .click_event(ClickEvent::open_url("https://github.com/Maxuss/lobster"));
        println!("{}", cmp.to_string())
    }

    #[test]
    #[cfg(feature = "minimessage")]
    fn test_lexer() {
        let mut lexer: Lexer<MessageToken> =
            MessageToken::lexer("<#AABBCC>Hex text<reset>Stop hex text");

        while let Some(tk) = lexer.next() {
            println!("{:?}", tk)
        }
    }

    #[test]
    #[cfg(feature = "minimessage")]
    fn test_parser() {
        let lexer: Lexer<MessageToken> = MessageToken::lexer("<red>Red text");
        let mut parser = Parser::new(lexer);

        while let Ok(_) = parser.advance() {
            // no-op
        }
        let out = parser.finish();
        println!("{}", serde_json::to_string(&out).unwrap());
    }

    #[test]
    #[cfg(feature = "minimessage")]
    fn test_placeholders() {
        let lobster = placeholder_lobster(
            "Before placeholder, <replace_me> Stuff after placeholder. <another>",
            [
                (
                    "replace_me",
                    lobster("<aqua>This is a <dark_aqua>placeholder!<reset>"),
                ),
                ("another", lobster("<gold><bold>Another placeholder!")),
            ],
        );

        println!("{}", serde_json::to_string(&lobster).unwrap());
    }

    #[test]
    #[cfg(feature = "minimessage")]
    fn test_flattening() {
        let mut message =
            lobster("<red>Some message<blue> Even more message <green>Green message ").append(
                Component::translate::<&str, Component>("some.message.translate", None),
            );

        println!("{}", message.flatten())
    }

    // #[bench]
    // #[cfg(feature = "minimessage")]
    // fn benchmark_lobster(bencher: &mut Bencher) {
    //     bencher.iter(|| {
    //         test::black_box(lobster("<red>Red text <green>Green text <italic><yellow>Yellow italic text. <bold>BOLD. <red>Red text"))
    //     })
    // }
}