@@ -13,6 +13,7 @@ mod command_history;
13
13
mod commands;
14
14
mod crates;
15
15
mod db;
16
+ mod godbolt;
16
17
mod jobs;
17
18
mod playground;
18
19
mod schema;
@@ -147,6 +148,34 @@ fn app() -> Result<(), Error> {
147
148
} ) ;
148
149
}
149
150
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
+
150
179
// Slow mode.
151
180
// 0 seconds disables slowmode
152
181
cmds. add_protected ( "?slowmode {channel} {seconds}" , api:: slow_mode, api:: is_mod) ;
@@ -201,6 +230,40 @@ fn app() -> Result<(), Error> {
201
230
Ok ( ( ) )
202
231
}
203
232
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
+
204
267
fn main_menu ( args : & Args , commands : & IndexMap < & str , ( & str , GuardFn ) > ) -> String {
205
268
let mut menu = commands. iter ( ) . fold (
206
269
"Commands:\n " . to_owned ( ) ,
0 commit comments