@@ -16,7 +16,7 @@ use matrix_sdk::ruma::events::room::message::{
1616} ;
1717
1818#[ derive( Clone , Debug , Default ) ]
19- enum SlashCommand {
19+ pub enum SlashCommand {
2020 /// Send an emote message.
2121 Emote ,
2222
@@ -47,6 +47,9 @@ enum SlashCommand {
4747
4848 /// Send a message with heart effects in clients that show them.
4949 SpaceInvaders ,
50+
51+ /// Send a live message that updates as you type (MSC4357)
52+ Live ,
5053}
5154
5255impl SlashCommand {
@@ -95,6 +98,11 @@ impl SlashCommand {
9598 Default :: default ( ) ,
9699 ) ?
97100 } ,
101+ SlashCommand :: Live => {
102+ // Live messages are handled specially in the chat window
103+ // This should not be called directly
104+ return Err ( anyhow:: anyhow!( "Live message" ) ) ;
105+ } ,
98106 } ;
99107
100108 Ok ( msgtype)
@@ -104,6 +112,7 @@ impl SlashCommand {
104112fn parse_slash_command_inner ( input : & str ) -> IResult < & str , SlashCommand > {
105113 let ( input, _) = space0 ( input) ?;
106114 let ( input, slash) = alt ( (
115+ // Commands that require text after them (with space)
107116 value ( SlashCommand :: Emote , tag ( "/me " ) ) ,
108117 value ( SlashCommand :: Html , tag ( "/h " ) ) ,
109118 value ( SlashCommand :: Html , tag ( "/html " ) ) ,
@@ -118,6 +127,7 @@ fn parse_slash_command_inner(input: &str) -> IResult<&str, SlashCommand> {
118127 value ( SlashCommand :: Rainfall , tag ( "/rainfall " ) ) ,
119128 value ( SlashCommand :: Snowfall , tag ( "/snowfall " ) ) ,
120129 value ( SlashCommand :: SpaceInvaders , tag ( "/spaceinvaders " ) ) ,
130+ value ( SlashCommand :: Live , tag ( "/live " ) ) ,
121131 ) ) ( input) ?;
122132 let ( input, _) = space0 ( input) ?;
123133
@@ -170,12 +180,23 @@ fn text_to_message_content(input: String) -> TextMessageEventContent {
170180 }
171181}
172182
183+ #[ allow( dead_code) ]
173184pub fn text_to_message ( input : String ) -> RoomMessageEventContent {
174- let msg = parse_slash_command ( input. as_str ( ) )
175- . and_then ( |( input, slash) | slash. to_message ( input) )
176- . unwrap_or_else ( |_| MessageType :: Text ( text_to_message_content ( input) ) ) ;
185+ text_to_message_with_command ( input) . 0
186+ }
177187
178- RoomMessageEventContent :: new ( msg)
188+ pub fn text_to_message_with_command ( input : String ) -> ( RoomMessageEventContent , Option < SlashCommand > ) {
189+ match parse_slash_command ( input. as_str ( ) ) {
190+ Ok ( ( text, slash) ) => {
191+ let msg = slash. to_message ( text)
192+ . unwrap_or_else ( |_| MessageType :: Text ( text_to_message_content ( text. to_string ( ) ) ) ) ;
193+ ( RoomMessageEventContent :: new ( msg) , Some ( slash) )
194+ } ,
195+ Err ( _) => {
196+ let msg = MessageType :: Text ( text_to_message_content ( input) ) ;
197+ ( RoomMessageEventContent :: new ( msg) , None )
198+ }
199+ }
179200}
180201
181202#[ cfg( test) ]
@@ -330,8 +351,7 @@ pub mod tests {
330351 assert_eq ! ( content. body, "<b>bold</b>" ) ;
331352 assert_eq ! ( content. formatted. unwrap( ) . body, "<b>bold</b>" ) ;
332353
333- let MessageType :: Text ( content) = text_to_message ( "/plain <b>bold</b>" . into ( ) ) . msgtype
334- else {
354+ let MessageType :: Text ( content) = text_to_message ( "/plain <b>bold</b>" . into ( ) ) . msgtype else {
335355 panic ! ( "Expected MessageType::Text" ) ;
336356 } ;
337357 assert_eq ! ( content. body, "<b>bold</b>" ) ;
@@ -343,33 +363,40 @@ pub mod tests {
343363 assert_eq ! ( content. body, "<b>bold</b>" ) ;
344364 assert ! ( content. formatted. is_none( ) , "{:?}" , content. formatted) ;
345365
346- let MessageType :: Emote ( content) = text_to_message ( "/me *bold*" . into ( ) ) . msgtype else {
366+ let ( msg, _) = text_to_message_with_command ( "/me *bold*" . into ( ) ) ;
367+ let MessageType :: Emote ( content) = msg. msgtype else {
347368 panic ! ( "Expected MessageType::Emote" ) ;
348369 } ;
349370 assert_eq ! ( content. body, "*bold*" ) ;
350371 assert_eq ! ( content. formatted. unwrap( ) . body, "<p><em>bold</em></p>\n " ) ;
351372
352- let content = text_to_message ( "/confetti hello" . into ( ) ) . msgtype ;
373+ let ( msg, _) = text_to_message_with_command ( "/confetti hello" . into ( ) ) ;
374+ let content = msg. msgtype ;
353375 assert_eq ! ( content. msgtype( ) , "nic.custom.confetti" ) ;
354376 assert_eq ! ( content. body( ) , "hello" ) ;
355377
356- let content = text_to_message ( "/fireworks hello" . into ( ) ) . msgtype ;
378+ let ( msg, _) = text_to_message_with_command ( "/fireworks hello" . into ( ) ) ;
379+ let content = msg. msgtype ;
357380 assert_eq ! ( content. msgtype( ) , "nic.custom.fireworks" ) ;
358381 assert_eq ! ( content. body( ) , "hello" ) ;
359382
360- let content = text_to_message ( "/hearts hello" . into ( ) ) . msgtype ;
383+ let ( msg, _) = text_to_message_with_command ( "/hearts hello" . into ( ) ) ;
384+ let content = msg. msgtype ;
361385 assert_eq ! ( content. msgtype( ) , "io.element.effect.hearts" ) ;
362386 assert_eq ! ( content. body( ) , "hello" ) ;
363387
364- let content = text_to_message ( "/rainfall hello" . into ( ) ) . msgtype ;
388+ let ( msg, _) = text_to_message_with_command ( "/rainfall hello" . into ( ) ) ;
389+ let content = msg. msgtype ;
365390 assert_eq ! ( content. msgtype( ) , "io.element.effect.rainfall" ) ;
366391 assert_eq ! ( content. body( ) , "hello" ) ;
367392
368- let content = text_to_message ( "/snowfall hello" . into ( ) ) . msgtype ;
393+ let ( msg, _) = text_to_message_with_command ( "/snowfall hello" . into ( ) ) ;
394+ let content = msg. msgtype ;
369395 assert_eq ! ( content. msgtype( ) , "io.element.effect.snowfall" ) ;
370396 assert_eq ! ( content. body( ) , "hello" ) ;
371397
372- let content = text_to_message ( "/spaceinvaders hello" . into ( ) ) . msgtype ;
398+ let ( msg, _) = text_to_message_with_command ( "/spaceinvaders hello" . into ( ) ) ;
399+ let content = msg. msgtype ;
373400 assert_eq ! ( content. msgtype( ) , "io.element.effects.space_invaders" ) ;
374401 assert_eq ! ( content. body( ) , "hello" ) ;
375402 }
0 commit comments