aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/commands/discocaml.rs79
-rw-r--r--src/commands/mod.rs2
2 files changed, 64 insertions, 17 deletions
diff --git a/src/commands/discocaml.rs b/src/commands/discocaml.rs
index 93ddfaa..4aaa695 100644
--- a/src/commands/discocaml.rs
+++ b/src/commands/discocaml.rs
@@ -6,7 +6,7 @@ use serenity::{
CommandDataOptionValue, CommandInteraction, CommandOptionType, CommandType, Member, RoleId,
},
builder::{
- CreateCommand, CreateCommandOption, CreateInteractionResponse,
+ CreateButton, CreateCommand, CreateCommandOption, CreateInteractionResponse,
CreateInteractionResponseMessage,
},
client::Context,
@@ -25,23 +25,53 @@ pub struct DiscocamlConfig {
pub role: RoleId,
}
-#[derive(Debug, Serialize)]
-struct DiscocamlRequest {
- expr: String,
- command: DiscocamlCommand,
+#[derive(Debug, PartialEq, Serialize)]
+pub struct DiscocamlRequest {
+ pub expr: String,
+ pub command: DiscocamlCommand,
}
-#[derive(Debug, Serialize)]
-enum DiscocamlCommand {
+#[derive(Debug, PartialEq, Serialize)]
+pub enum DiscocamlCommand {
Roundtrip,
}
-#[derive(Debug, Deserialize)]
+/// A response outputted by the discocaml subprocess as a JSON string.
+///
+/// ```
+/// # use lambo::{commands::discocaml::*, utils::EnumAsArray};
+/// # use serde::Deserialize;
+/// # use serde_json::Deserializer;
+///
+/// let example = r#"
+/// [ "Expr"
+/// , { "expr": "1 + 2"
+/// }
+/// ]
+/// "#;
+/// let expected = DiscocamlResponse::Expr(DiscocamlResponseExpr {
+/// expr: "1 + 2".to_string(),
+/// });
+///
+/// let mut de = Deserializer::from_str(&example);
+/// let out = DiscocamlResponse::deserialize(EnumAsArray(&mut de)).unwrap();
+/// de.end().unwrap();
+///
+/// assert_eq!(out, expected);
+/// ```
+#[derive(Debug, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)]
-enum DiscocamlResponse {
+pub enum DiscocamlResponse {
+ Expr(DiscocamlResponseExpr),
Error(String),
}
+#[derive(Debug, Deserialize, PartialEq)]
+#[serde(deny_unknown_fields)]
+pub struct DiscocamlResponseExpr {
+ pub expr: String,
+}
+
pub fn command() -> CreateCommand {
CreateCommand::new("discocaml")
.kind(CommandType::ChatInput)
@@ -82,10 +112,10 @@ async fn respond_with_error(ctx: &Context, command: &CommandInteraction, err: &E
}
}
-async fn run_discocaml(
+pub async fn run_discocaml(
config: &DiscocamlConfig,
req: &DiscocamlRequest,
-) -> Result<DiscocamlResponse> {
+) -> Result<DiscocamlResponseExpr> {
let mut child = Command::new(&config.command[0])
.args(&config.command)
.stdin(Stdio::piped())
@@ -120,7 +150,22 @@ async fn run_discocaml(
.context("failed to parse response from discocaml")?;
de.end()
.context("failed to parse response from discocaml")?;
- Ok(out)
+
+ match out {
+ DiscocamlResponse::Expr(expr) => Ok(expr),
+ DiscocamlResponse::Error(err) => bail!("got an error from discocaml: {:?}", err),
+ }
+}
+
+fn make_response_message(expr: &DiscocamlResponseExpr) -> CreateInteractionResponseMessage {
+ // TODO: Real escaping
+ CreateInteractionResponseMessage::new()
+ .content(format!("```ocaml\n{}\n```", expr.expr))
+ .button(CreateButton::new("step-cbv").label("Step (CBV)"))
+ .button(CreateButton::new("step-cbn").label("Step (CBN)"))
+ .button(CreateButton::new("run-cbv").label("Run (CBV)"))
+ .button(CreateButton::new("run-cbn").label("Run (CBN)"))
+ .button(CreateButton::new("draw-tree").label("Draw Tree"))
}
pub async fn handle_command(
@@ -163,15 +208,17 @@ pub async fn handle_command(
let res = match run_discocaml(config, &req).await {
Ok(res) => res,
Err(err) => {
- let err = err.context("failed to run discocaml");
respond_with_error(ctx, command, &err).await;
- return Err(err);
+ return Err(err.context("failed to run discocaml"));
}
};
- let msg = CreateInteractionResponseMessage::new().content(format!("`{:?}`", res));
+ // Respond with the expression and the buttons.
command
- .create_response(&ctx, CreateInteractionResponse::Message(msg))
+ .create_response(
+ &ctx,
+ CreateInteractionResponse::Message(make_response_message(&res)),
+ )
.await
.context("failed to respond")
}
diff --git a/src/commands/mod.rs b/src/commands/mod.rs
index 083b200..899bb8f 100644
--- a/src/commands/mod.rs
+++ b/src/commands/mod.rs
@@ -1,4 +1,4 @@
-mod discocaml;
+pub mod discocaml;
use crate::commands::discocaml::DiscocamlConfig;
use anyhow::{Context as _, Result};