@@ -14,3 +14,4 @@ dotenv.workspace = true
|
||||
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
uuid = { version = "1.7.0", features = ["v4"] }
|
||||
toml = "0.8.19"
|
||||
|
2
crates/cuddle/examples/basic/cuddle.toml
Normal file
2
crates/cuddle/examples/basic/cuddle.toml
Normal file
@@ -0,0 +1,2 @@
|
||||
[project]
|
||||
name = "basic"
|
@@ -1,29 +1,97 @@
|
||||
use anyhow::Context;
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None, subcommand_required = true)]
|
||||
struct Command {
|
||||
#[command(subcommand)]
|
||||
command: Option<Commands>,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
Hello {},
|
||||
}
|
||||
use project::Project;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
dotenv::dotenv().ok();
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
let cli = Command::parse();
|
||||
tracing::debug!("Starting cli");
|
||||
|
||||
if let Some(Commands::Hello {}) = cli.command {
|
||||
println!("Hello!")
|
||||
}
|
||||
Cuddle::new().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct Cuddle {
|
||||
project: Option<Project>,
|
||||
}
|
||||
|
||||
impl Cuddle {
|
||||
pub async fn new() -> anyhow::Result<Self> {
|
||||
let project = Project::from_current_path().await?;
|
||||
|
||||
Ok(Self { project })
|
||||
}
|
||||
}
|
||||
|
||||
mod project {
|
||||
use std::env::current_dir;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
const CUDDLE_FILE_NAME: &str = "cuddle.toml";
|
||||
|
||||
pub struct Project {
|
||||
config: Config,
|
||||
}
|
||||
|
||||
impl Project {
|
||||
pub fn new(config: Config) -> Self {
|
||||
Self { config }
|
||||
}
|
||||
|
||||
pub fn from_file(content: &str) -> anyhow::Result<Self> {
|
||||
let config: Config = toml::from_str(&content)?;
|
||||
|
||||
Ok(Self::new(config))
|
||||
}
|
||||
|
||||
pub async fn from_current_path() -> anyhow::Result<Option<Self>> {
|
||||
let cur_dir = current_dir()?;
|
||||
let cuddle_file = cur_dir.join(CUDDLE_FILE_NAME);
|
||||
|
||||
if !cuddle_file.exists() {
|
||||
// We may want to recursively search for the file (towards root)
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let cuddle_project_file = tokio::fs::read_to_string(cuddle_file).await?;
|
||||
|
||||
Ok(Some(Self::from_file(&cuddle_project_file)?))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
||||
pub struct Config {
|
||||
project: ProjectConfig,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
||||
pub struct ProjectConfig {
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_can_parse_simple_file() -> anyhow::Result<()> {
|
||||
let project = Project::from_file(
|
||||
r##"
|
||||
[project]
|
||||
name = "simple_file"
|
||||
"##,
|
||||
)?;
|
||||
|
||||
assert_eq!(
|
||||
Config {
|
||||
project: ProjectConfig {
|
||||
name: "simple_file".into()
|
||||
}
|
||||
},
|
||||
project.config
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user