initial commit
This commit is contained in:
112
src/app.rs
Normal file
112
src/app.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
use std::{
|
||||
env::set_current_dir,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
const MAIN_C: &str = include_str!("templates/main.c");
|
||||
|
||||
#[derive(clap::Parser)]
|
||||
pub struct App {
|
||||
#[clap(subcommand)]
|
||||
command: Subcommand,
|
||||
}
|
||||
|
||||
#[derive(clap::Subcommand)]
|
||||
enum Subcommand {
|
||||
/// Create a new C project
|
||||
New {
|
||||
/// The name of the new project
|
||||
name: String,
|
||||
},
|
||||
/// Initialize a new C project
|
||||
Init,
|
||||
/// Run the local project
|
||||
Run {
|
||||
/// The build mode to use
|
||||
mode: Option<String>,
|
||||
},
|
||||
/// Build the local project
|
||||
Build {
|
||||
/// The build mode to use
|
||||
mode: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn run(self) {
|
||||
match self.command {
|
||||
Subcommand::New { name } => match create_project(&name) {
|
||||
Ok(_) => println!("Successfully created new project '{name}'."),
|
||||
Err(e) => {
|
||||
eprintln!("Error creating project '{name}': {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
},
|
||||
Subcommand::Init => match create_project(".") {
|
||||
Ok(_) => println!("Successfully initialized new project."),
|
||||
Err(e) => {
|
||||
eprintln!("Error initializing project: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
},
|
||||
Subcommand::Run { mode } => todo!(),
|
||||
Subcommand::Build { mode } => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_project<P: AsRef<Path>>(directory: P) -> std::io::Result<()> {
|
||||
let pathdir = directory.as_ref();
|
||||
|
||||
if pathdir.exists() && pathdir.to_string_lossy() != "." {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::AlreadyExists,
|
||||
"specified directory already exists",
|
||||
));
|
||||
}
|
||||
|
||||
if !pathdir.exists() && pathdir.to_string_lossy() != "." {
|
||||
std::fs::create_dir(pathdir)?;
|
||||
}
|
||||
|
||||
set_current_dir(pathdir)?;
|
||||
|
||||
std::fs::create_dir("src")?;
|
||||
|
||||
std::fs::write("src/main.c", MAIN_C)?;
|
||||
|
||||
let config = crate::config::Config::new(&pathdir.to_string_lossy());
|
||||
|
||||
let serial = toml::to_string_pretty(&config).expect("a valid TOML structure");
|
||||
|
||||
std::fs::write("Pallet.toml", &serial)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_config() -> Option<crate::config::Config> {
|
||||
let p = PathBuf::from("Pallet.toml");
|
||||
if !p.exists() {
|
||||
return None;
|
||||
}
|
||||
let raw = std::fs::read_to_string(&p).expect("A valid config file");
|
||||
|
||||
toml::from_str(&raw).ok()
|
||||
}
|
||||
|
||||
fn build(mode: Option<String>) -> std::io::Result<()> {
|
||||
let conf = match get_config() {
|
||||
Some(conf) => conf,
|
||||
None => {
|
||||
eprintln!("Error opening config file. No Pallet.toml in current directory.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let build_config = conf.get_or_default(mode).ok_or(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
"build layout not found",
|
||||
))?;
|
||||
|
||||
todo!()
|
||||
}
|
||||
49
src/config.rs
Normal file
49
src/config.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
pub struct Config {
|
||||
/// The name of the output binary
|
||||
pub name: String,
|
||||
/// The default build to use
|
||||
pub default_build: String,
|
||||
/// Build configs
|
||||
pub build: Vec<BuildConf>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(name: &str) -> Self {
|
||||
Self {
|
||||
name: name.to_owned(),
|
||||
default_build: "debug".to_owned(),
|
||||
build: vec![BuildConf::debug(), BuildConf::release()],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_or_default(&self, mode: Option<String>) -> Option<&BuildConf> {
|
||||
if let Some(mode) = mode {
|
||||
self.build.iter().find(|bc| bc.name == mode)
|
||||
} else {
|
||||
self.build.iter().find(|bc| bc.name == self.default_build)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
pub struct BuildConf {
|
||||
pub name: String,
|
||||
pub args: Vec<String>,
|
||||
}
|
||||
|
||||
impl BuildConf {
|
||||
fn debug() -> Self {
|
||||
Self {
|
||||
name: "debug".to_owned(),
|
||||
args: vec!["-g".to_owned(), "-O0".to_owned()],
|
||||
}
|
||||
}
|
||||
|
||||
fn release() -> Self {
|
||||
Self {
|
||||
name: "release".to_owned(),
|
||||
args: vec!["-DNDEBUG".to_owned(), "-O3".to_owned()],
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/main.rs
Normal file
9
src/main.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
use clap::Parser;
|
||||
|
||||
mod app;
|
||||
mod config;
|
||||
|
||||
fn main() {
|
||||
let app = app::App::parse();
|
||||
app.run();
|
||||
}
|
||||
7
src/templates/main.c
Normal file
7
src/templates/main.c
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("Hello, world!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user