nix: add module to generate nix flake #1

Merged
pleshevskiy merged 1 commit from nix_flake into main 2024-04-14 00:02:35 +03:00
6 changed files with 132 additions and 17 deletions

View file

@ -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<String>),
}
@ -140,24 +146,27 @@ pub fn run() -> Result<(), Box<dyn std::error::Error>> {
match args.command {
Command::Make(_make_args) => {
let config = read_config(&current_dir)?;
let mut make_files: HashMap<String, String> = 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<String, String> = [
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<String, String> = 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<String, String> = 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")
}

21
src/cli/nix_flake.rs Normal file
View file

@ -0,0 +1,21 @@
use crate::module::nix_flake::NixFlakeModuleArgs;
#[derive(Debug, Clone, clap::Args)]
pub struct NixFlakeModuleCliArgs {
#[clap(short, long)]
description: Option<String>,
#[clap(long)]
extra_inputs: Option<String>,
#[clap(long)]
extra_outputs: Option<String>,
}
impl From<NixFlakeModuleCliArgs> for NixFlakeModuleArgs {
fn from(args: NixFlakeModuleCliArgs) -> Self {
NixFlakeModuleArgs {
description: args.description,
extra_inputs: args.extra_inputs,
extra_outputs: args.extra_outputs,
}
}
}

View file

@ -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<NixFlakeModuleConfig>,
}
#[derive(serde::Deserialize, serde::Serialize)]
pub struct Config {
pub nix: Option<NixConfig>,
pub direnv: Option<DirenvModuleConfig>,
pub gitignore: Option<GitIgnoreModuleConfig>,
}

18
src/config/nix_flake.rs Normal file
View file

@ -0,0 +1,18 @@
use crate::module::nix_flake::NixFlakeModuleArgs;
#[derive(Default, serde::Deserialize, serde::Serialize)]
pub struct NixFlakeModuleConfig {
description: Option<String>,
extra_inputs: Option<String>,
extra_outputs: Option<String>,
}
impl From<NixFlakeModuleConfig> for NixFlakeModuleArgs {
fn from(cfg: NixFlakeModuleConfig) -> Self {
NixFlakeModuleArgs {
description: cfg.description,
extra_inputs: cfg.extra_inputs,
extra_outputs: cfg.extra_outputs,
}
}
}

View file

@ -2,6 +2,7 @@ use std::collections::HashMap;
pub mod direnv;
pub mod gitignore;
pub mod nix_flake;
pub trait Module {
type ModuleArgs;

57
src/module/nix_flake.rs Normal file
View file

@ -0,0 +1,57 @@
use std::collections::HashMap;
use std::io::{self, Write};
use super::Module;
pub struct NixFlakeModuleArgs {
pub description: Option<String>,
pub extra_inputs: Option<String>,
pub extra_outputs: Option<String>,
}
fn make_flakenix_content(args: NixFlakeModuleArgs) -> Result<String, io::Error> {
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<String, String> {
HashMap::from([(
String::from("flake.nix"),
make_flakenix_content(args).unwrap(),
)])
}
}