@@ -13,6 +13,7 @@ mod command_history;
1313mod commands;
1414mod crates;
1515mod db;
16+ mod godbolt;
1617mod jobs;
1718mod playground;
1819mod schema;
@@ -147,6 +148,34 @@ fn app() -> Result<(), Error> {
147148 } ) ;
148149 }
149150
151+ cmds. add ( "?godbolt ```\n code```" , |args| {
152+ let code = args
153+ . params
154+ . get ( "code" )
155+ . ok_or ( "Unable to retrieve param: code" ) ?;
156+ let ( lang, text) = match godbolt:: compile_rust_source ( args. http , code) ? {
157+ godbolt:: Compilation :: Success { asm } => ( "x86asm" , asm) ,
158+ godbolt:: Compilation :: Error { stderr } => ( "rust" , stderr) ,
159+ } ;
160+
161+ reply_potentially_long_text (
162+ & args,
163+ & format ! ( "```{}\n {}" , lang, text) ,
164+ "\n ```" ,
165+ "Note: the output was truncated" ,
166+ ) ?;
167+
168+ Ok ( ( ) )
169+ } ) ;
170+ cmds. help ( "?godbolt" , "View assembly using Godbolt" , |args| {
171+ api:: send_reply (
172+ & args,
173+ "Compile Rust code using https://rust.godbolt.org. Full optimizations are applied. \
174+ ```?godbolt ``\u{200B} `code``\u{200B} ` ```",
175+ ) ?;
176+ Ok ( ( ) )
177+ } ) ;
178+
150179 // Slow mode.
151180 // 0 seconds disables slowmode
152181 cmds. add_protected ( "?slowmode {channel} {seconds}" , api:: slow_mode, api:: is_mod) ;
@@ -201,6 +230,40 @@ fn app() -> Result<(), Error> {
201230 Ok ( ( ) )
202231}
203232
233+ /// Send a Discord reply message and truncate the message with a given truncation message if the
234+ /// text is too long.
235+ ///
236+ /// Only `text_body` is truncated. `text_end` will always be appended at the end. This is useful
237+ /// for example for large code blocks. You will want to truncate the code block contents, but the
238+ /// finalizing \`\`\` should always stay - that's what `text_end` is for.
239+ fn reply_potentially_long_text (
240+ args : & Args ,
241+ text_body : & str ,
242+ text_end : & str ,
243+ truncation_msg : & str ,
244+ ) -> Result < ( ) , Error > {
245+ let msg = if text_body. len ( ) + text_end. len ( ) > 2000 {
246+ // This is how long the text body may be at max to conform to Discord's limit
247+ let available_space = 2000 - text_end. len ( ) - truncation_msg. len ( ) ;
248+
249+ let mut cut_off_point = available_space;
250+ while !text_body. is_char_boundary ( cut_off_point) {
251+ cut_off_point -= 1 ;
252+ }
253+
254+ format ! (
255+ "{}{}{}" ,
256+ & text_body[ ..cut_off_point] ,
257+ text_end,
258+ truncation_msg
259+ )
260+ } else {
261+ format ! ( "{}{}" , text_body, text_end)
262+ } ;
263+
264+ api:: send_reply ( args, & msg)
265+ }
266+
204267fn main_menu ( args : & Args , commands : & IndexMap < & str , ( & str , GuardFn ) > ) -> String {
205268 let mut menu = commands. iter ( ) . fold (
206269 "Commands:\n " . to_owned ( ) ,
0 commit comments