diff --git a/src/cli.rs b/src/cli.rs index 57ff5db..811901a 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -10,13 +10,17 @@ use clap::Parser; use crate::{ config::read_config, - module::{direnv::DirenvModule, gitignore::GitIgnoreModule, Module}, + module::{direnv::DirenvModule, gitignore::GitIgnoreModule, nix_flake::NixFlakeModule, Module}, }; -use self::{direnv::DirenvModuleCliArgs, gitignore::GitIgnoreModuleCliArgs}; +use self::{ + direnv::DirenvModuleCliArgs, gitignore::GitIgnoreModuleCliArgs, + nix_flake::NixFlakeModuleCliArgs, +}; mod direnv; mod gitignore; +mod nix_flake; #[derive(Debug, Clone, clap::Args)] struct MakeCommand { @@ -28,6 +32,8 @@ enum AddModuleCommand { Direnv(DirenvModuleCliArgs), #[clap(name = "gitignore")] GitIgnore(GitIgnoreModuleCliArgs), + #[clap(name = "nix.flake")] + NixFlake(NixFlakeModuleCliArgs), #[clap(external_subcommand)] External(Vec), } @@ -140,24 +146,27 @@ pub fn run() -> Result<(), Box> { match args.command { Command::Make(_make_args) => { let config = read_config(¤t_dir)?; - let mut make_files: HashMap = HashMap::new(); - - if let Some(cfg) = config.direnv { - make_files.extend(DirenvModule.make(cfg.into())) - } - if let Some(cfg) = config.gitignore { - make_files.extend(GitIgnoreModule.make(cfg.into())); - } + let make_files: HashMap = [ + config.direnv.map(|v| DirenvModule.make(v.into())), + config.gitignore.map(|v| GitIgnoreModule.make(v.into())), + config + .nix + .and_then(|cfg| cfg.flake.map(|v| NixFlakeModule.make(v.into()))), + ] + .into_iter() + .flatten() + .fold(HashMap::new(), |mut acc, files| { + acc.extend(files); + acc + }); make(current_dir, make_files, true) } Command::Add { force, command } => { - let mut make_files: HashMap = HashMap::new(); - match command { - AddModuleCommand::Direnv(args) => make_files.extend(DirenvModule.make(args.into())), - AddModuleCommand::GitIgnore(args) => { - make_files.extend(GitIgnoreModule.make(args.into())) - } + let make_files: HashMap = match command { + AddModuleCommand::Direnv(args) => DirenvModule.make(args.into()), + AddModuleCommand::GitIgnore(args) => GitIgnoreModule.make(args.into()), + AddModuleCommand::NixFlake(args) => NixFlakeModule.make(args.into()), AddModuleCommand::External(_) => { unimplemented!("external commands") } diff --git a/src/cli/nix_flake.rs b/src/cli/nix_flake.rs new file mode 100644 index 0000000..6634350 --- /dev/null +++ b/src/cli/nix_flake.rs @@ -0,0 +1,21 @@ +use crate::module::nix_flake::NixFlakeModuleArgs; + +#[derive(Debug, Clone, clap::Args)] +pub struct NixFlakeModuleCliArgs { + #[clap(short, long)] + description: Option, + #[clap(long)] + extra_inputs: Option, + #[clap(long)] + extra_outputs: Option, +} + +impl From for NixFlakeModuleArgs { + fn from(args: NixFlakeModuleCliArgs) -> Self { + NixFlakeModuleArgs { + description: args.description, + extra_inputs: args.extra_inputs, + extra_outputs: args.extra_outputs, + } + } +} diff --git a/src/config.rs b/src/config.rs index e52257c..f822826 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,12 +1,21 @@ use std::{fs, io, path::PathBuf}; -use self::{direnv::DirenvModuleConfig, gitignore::GitIgnoreModuleConfig}; +use self::{ + direnv::DirenvModuleConfig, gitignore::GitIgnoreModuleConfig, nix_flake::NixFlakeModuleConfig, +}; mod direnv; mod gitignore; +mod nix_flake; + +#[derive(serde::Deserialize, serde::Serialize)] +pub struct NixConfig { + pub flake: Option, +} #[derive(serde::Deserialize, serde::Serialize)] pub struct Config { + pub nix: Option, pub direnv: Option, pub gitignore: Option, } diff --git a/src/config/nix_flake.rs b/src/config/nix_flake.rs new file mode 100644 index 0000000..e4b042f --- /dev/null +++ b/src/config/nix_flake.rs @@ -0,0 +1,18 @@ +use crate::module::nix_flake::NixFlakeModuleArgs; + +#[derive(Default, serde::Deserialize, serde::Serialize)] +pub struct NixFlakeModuleConfig { + description: Option, + extra_inputs: Option, + extra_outputs: Option, +} + +impl From for NixFlakeModuleArgs { + fn from(cfg: NixFlakeModuleConfig) -> Self { + NixFlakeModuleArgs { + description: cfg.description, + extra_inputs: cfg.extra_inputs, + extra_outputs: cfg.extra_outputs, + } + } +} diff --git a/src/module.rs b/src/module.rs index a43d974..36fb394 100644 --- a/src/module.rs +++ b/src/module.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; pub mod direnv; pub mod gitignore; +pub mod nix_flake; pub trait Module { type ModuleArgs; diff --git a/src/module/nix_flake.rs b/src/module/nix_flake.rs new file mode 100644 index 0000000..45c30e4 --- /dev/null +++ b/src/module/nix_flake.rs @@ -0,0 +1,57 @@ +use std::collections::HashMap; +use std::io::{self, Write}; + +use super::Module; + +pub struct NixFlakeModuleArgs { + pub description: Option, + pub extra_inputs: Option, + pub extra_outputs: Option, +} + +fn make_flakenix_content(args: NixFlakeModuleArgs) -> Result { + let mut s = Vec::new(); + writeln!(s, "{{")?; + #[rustfmt::skip] + writeln!(s, " description = \"{}\";", args.description.unwrap_or_default())?; + + // ---------------------- + // INPUTS + writeln!(s, " inputs = {{")?; + if let Some(extra_inputs) = args.extra_inputs { + writeln!(s, "{}", extra_inputs.trim())?; + } + writeln!(s, " }};")?; + + // ---------------------- + // OUTPUTS + writeln!(s, " outputs =")?; + writeln!(s, " {{ self")?; + writeln!(s, " , nixpkgs")?; + writeln!(s, " , ...")?; + writeln!(s, " }} @ inputs:")?; + + if let Some(extra_outputs) = args.extra_outputs { + write!(s, " ({});", extra_outputs.trim())?; + } else { + writeln!(s, " {{")?; + writeln!(s, " }};")?; + } + + writeln!(s, "}}")?; + + Ok(String::from_utf8(s).unwrap()) +} + +pub struct NixFlakeModule; + +impl Module for NixFlakeModule { + type ModuleArgs = NixFlakeModuleArgs; + + fn make(&self, args: Self::ModuleArgs) -> HashMap { + HashMap::from([( + String::from("flake.nix"), + make_flakenix_content(args).unwrap(), + )]) + } +}