93
crates/cuddle-actions/src/lib.rs
Normal file
93
crates/cuddle-actions/src/lib.rs
Normal file
@@ -0,0 +1,93 @@
|
||||
// Cuddle actions is a two part action, it is called from cuddle itself, second the cli uses a provided sdk to expose functionality
|
||||
|
||||
use std::{collections::BTreeMap, ffi::OsString, io::Write};
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
// Fix design make it so that it works like axum!
|
||||
|
||||
type ActionFn = dyn Fn() + 'static;
|
||||
|
||||
struct Action {
|
||||
name: String,
|
||||
description: Option<String>,
|
||||
f: Box<ActionFn>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
struct ActionSchema<'a> {
|
||||
name: &'a str,
|
||||
description: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CuddleActions {
|
||||
actions: BTreeMap<String, Action>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct AddActionOptions {
|
||||
description: Option<String>,
|
||||
}
|
||||
|
||||
impl CuddleActions {
|
||||
pub fn add_action<F>(
|
||||
&mut self,
|
||||
name: &str,
|
||||
action_fn: F,
|
||||
options: &AddActionOptions,
|
||||
) -> &mut Self
|
||||
where
|
||||
F: Fn() + 'static,
|
||||
{
|
||||
self.actions.insert(
|
||||
name.into(),
|
||||
Action {
|
||||
name: name.into(),
|
||||
description: options.description.clone(),
|
||||
f: Box::new(action_fn),
|
||||
},
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn execute(&mut self) -> anyhow::Result<()> {
|
||||
let output = self.execute_from(std::env::args())?;
|
||||
|
||||
// Write all stdout to buffer
|
||||
std::io::stdout().write_all(output.as_bytes())?;
|
||||
std::io::stdout().write_all("\n".as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn execute_from<I, T>(&mut self, items: I) -> anyhow::Result<String>
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone,
|
||||
{
|
||||
let root = clap::Command::new("cuddle-action")
|
||||
.subcommand_required(true)
|
||||
.subcommand(clap::Command::new("schema"));
|
||||
|
||||
let matches = root.get_matches_from(items);
|
||||
match matches.subcommand().expect("subcommand to be required") {
|
||||
("schema", _args) => {
|
||||
let schema = self
|
||||
.actions
|
||||
.values()
|
||||
.map(|a| ActionSchema {
|
||||
name: &a.name,
|
||||
description: a.description.as_ref().map(|d| d.as_str()),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let output = serde_json::to_string_pretty(&schema)?;
|
||||
|
||||
Ok(output)
|
||||
}
|
||||
_ => Ok("".into()),
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user