refactored cli and logging
All checks were successful
Test the running changes / Test (push) Successful in 41s
All checks were successful
Test the running changes / Test (push) Successful in 41s
This commit is contained in:
@@ -1,84 +0,0 @@
|
||||
//! Simple and program specific command line argument parsing solution.
|
||||
|
||||
// todo: refactor to <command> <subcommand> [<options>]
|
||||
|
||||
use slogger::{LOG_LEVEL, Level};
|
||||
|
||||
use crate::error::Error;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct ProgramArgs {
|
||||
pub outdir: PathBuf,
|
||||
pub indir: PathBuf,
|
||||
pub generate: bool,
|
||||
pub force: bool,
|
||||
pub addr: Ipv4Addr,
|
||||
pub port: u16,
|
||||
pub verbose: bool,
|
||||
}
|
||||
|
||||
impl Default for ProgramArgs {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
indir: PathBuf::from("./web"),
|
||||
outdir: PathBuf::from("./html"),
|
||||
generate: false,
|
||||
force: false,
|
||||
addr: Ipv4Addr::UNSPECIFIED,
|
||||
port: 8080,
|
||||
verbose: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<std::env::Args> for ProgramArgs {
|
||||
type Error = crate::error::Error;
|
||||
fn try_from(mut value: std::env::Args) -> Result<Self, Self::Error> {
|
||||
let mut a = Self::default();
|
||||
let _ = value.next(); // ignore executable path
|
||||
while let Some(v) = value.next() {
|
||||
match v.as_str() {
|
||||
"-i" => {
|
||||
a.indir = value
|
||||
.next()
|
||||
.ok_or(Error::CommandLineArgsParse(
|
||||
"Expected input directory after option `-i`".to_string(),
|
||||
))?
|
||||
.into();
|
||||
}
|
||||
"-a" => {
|
||||
let addr_string = value.next().ok_or(Error::CommandLineArgsParse(
|
||||
"Expected listener IPv4 address after option `-a`".to_string(),
|
||||
))?;
|
||||
a.addr = Ipv4Addr::parse_ascii(addr_string.as_bytes()).map_err(|_e| {
|
||||
Error::CommandLineArgsParse(
|
||||
"Invalid IPv4 address after option `-a`".to_string(),
|
||||
)
|
||||
})?;
|
||||
}
|
||||
"-p" => {
|
||||
let port_string = value.next().ok_or(Error::CommandLineArgsParse(
|
||||
"Expected listener port after option `-p`".to_string(),
|
||||
))?;
|
||||
a.port = port_string.parse().map_err(|_e| {
|
||||
Error::CommandLineArgsParse(
|
||||
"Invalid 16-bit port number after option `-p`".to_string(),
|
||||
)
|
||||
})?;
|
||||
}
|
||||
"-g" => a.generate = true,
|
||||
"-f" => a.force = true,
|
||||
"-v" => {
|
||||
a.verbose = true;
|
||||
LOG_LEVEL.get_or_init(|| Level::Debug);
|
||||
}
|
||||
_ => {
|
||||
a.outdir = v.into();
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_LEVEL.get_or_init(|| Level::Info);
|
||||
Ok(a)
|
||||
}
|
||||
}
|
||||
162
gravel_cli/src/config.rs
Normal file
162
gravel_cli/src/config.rs
Normal file
@@ -0,0 +1,162 @@
|
||||
//! Simple and program specific command line argument parsing solution.
|
||||
|
||||
// todo: refactor to <command> <subcommand> [<options>]
|
||||
|
||||
use slogger::{LOG_LEVEL, Level, log};
|
||||
|
||||
use crate::error::Error;
|
||||
use std::env::Args;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub enum Command {
|
||||
Generate { force: bool },
|
||||
Serve { addr: Ipv4Addr, port: u16 },
|
||||
Init,
|
||||
}
|
||||
|
||||
impl Default for Command {
|
||||
fn default() -> Self {
|
||||
Self::Generate { force: true }
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Args> for Command {
|
||||
type Error = Error;
|
||||
fn try_from(mut value: Args) -> Result<Self, Self::Error> {
|
||||
let mut comm = Command::default();
|
||||
let _ = value.next(); // ignore executable
|
||||
let command = value.next();
|
||||
|
||||
// `gravel serve` command
|
||||
if let Some("serve") = command.as_deref() {
|
||||
let mut addr = Ipv4Addr::UNSPECIFIED;
|
||||
let mut port = 8080;
|
||||
while let Some(a) = value.next() {
|
||||
match a.as_str() {
|
||||
"-a" => {
|
||||
let address_str = value.next().ok_or(Error::CommandLineArgsParse(
|
||||
"Missing argument after `-a`. Expected IPv4 address.".to_string(),
|
||||
))?;
|
||||
addr = Ipv4Addr::parse_ascii(address_str.as_bytes()).map_err(|_e| {
|
||||
Error::CommandLineArgsParse("Parsing IP address failed".to_string())
|
||||
})?;
|
||||
}
|
||||
"-p" => {
|
||||
let port_str = value.next().ok_or(Error::CommandLineArgsParse(
|
||||
"Missing argument after `-p`. Expected TCP port number.".to_string(),
|
||||
))?;
|
||||
port = port_str.parse().map_err(|_e| {
|
||||
Error::CommandLineArgsParse("Parsing TCP port failed".to_string())
|
||||
})?;
|
||||
}
|
||||
&_ => Err(Error::CommandLineArgsParse(format!(
|
||||
"Unknown argument: `{a}`"
|
||||
)))?,
|
||||
}
|
||||
}
|
||||
comm = Command::Serve { addr, port };
|
||||
}
|
||||
// `gravel init` command
|
||||
else if let Some("init") = command.as_deref() {
|
||||
if let Some(a) = value.next() {
|
||||
Err(Error::CommandLineArgsParse(format!(
|
||||
"Unexpected argument: `{a}`"
|
||||
)))?;
|
||||
}
|
||||
comm = Command::Init;
|
||||
}
|
||||
// `gravel` command
|
||||
else if let Some(a) = value.next() {
|
||||
Err(Error::CommandLineArgsParse(format!(
|
||||
"Unexpected argument: `{a}`"
|
||||
)))?;
|
||||
}
|
||||
|
||||
Ok(comm)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub struct ProgramConfig {
|
||||
pub outdir: PathBuf,
|
||||
pub indir: PathBuf,
|
||||
pub command: Command,
|
||||
pub verbose: bool,
|
||||
}
|
||||
|
||||
impl Default for ProgramConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
indir: PathBuf::from("./pebbles"),
|
||||
outdir: PathBuf::from("./site"),
|
||||
command: Command::default(),
|
||||
verbose: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ProgramConfig {
|
||||
pub fn new<P: AsRef<Path>>(_toml_file: P, args: Args) -> Result<Self, Error> {
|
||||
let conf = Self {
|
||||
command: args.try_into()?,
|
||||
..Default::default()
|
||||
};
|
||||
LOG_LEVEL.get_or_init(|| Level::Debug);
|
||||
log!(Level::Warn, "TOML parsing not implemented, skipping");
|
||||
Ok(conf)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl TryFrom<std::env::Args> for ProgramConfig {
|
||||
type Error = crate::error::Error;
|
||||
fn try_from(mut value: std::env::Args) -> Result<Self, Self::Error> {
|
||||
let mut a = Self::default();
|
||||
let _ = value.next(); // ignore executable path
|
||||
while let Some(v) = value.next() {
|
||||
match v.as_str() {
|
||||
"-i" => {
|
||||
a.indir = value
|
||||
.next()
|
||||
.ok_or(Error::CommandLineArgsParse(
|
||||
"Expected input directory after option `-i`".to_string(),
|
||||
))?
|
||||
.into();
|
||||
}
|
||||
"-a" => {
|
||||
let addr_string = value.next().ok_or(Error::CommandLineArgsParse(
|
||||
"Expected listener IPv4 address after option `-a`".to_string(),
|
||||
))?;
|
||||
a.addr = Ipv4Addr::parse_ascii(addr_string.as_bytes()).map_err(|_e| {
|
||||
Error::CommandLineArgsParse(
|
||||
"Invalid IPv4 address after option `-a`".to_string(),
|
||||
)
|
||||
})?;
|
||||
}
|
||||
"-p" => {
|
||||
let port_string = value.next().ok_or(Error::CommandLineArgsParse(
|
||||
"Expected listener port after option `-p`".to_string(),
|
||||
))?;
|
||||
a.port = port_string.parse().map_err(|_e| {
|
||||
Error::CommandLineArgsParse(
|
||||
"Invalid 16-bit port number after option `-p`".to_string(),
|
||||
)
|
||||
})?;
|
||||
}
|
||||
"-g" => a.generate = true,
|
||||
"-f" => a.force = true,
|
||||
"-v" => {
|
||||
a.verbose = true;
|
||||
LOG_LEVEL.get_or_init(|| Level::Debug);
|
||||
}
|
||||
_ => {
|
||||
a.outdir = v.into();
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_LEVEL.get_or_init(|| Level::Info);
|
||||
Ok(a)
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -1,16 +1,30 @@
|
||||
#![feature(addr_parse_ascii, never_type)]
|
||||
|
||||
use args::ProgramArgs;
|
||||
use std::process;
|
||||
|
||||
use config::{Command, ProgramConfig};
|
||||
use cracked_md::generate;
|
||||
use error::Error;
|
||||
use slogger::{Level, log};
|
||||
use stdsrv::serve;
|
||||
|
||||
mod args;
|
||||
mod config;
|
||||
mod error;
|
||||
|
||||
fn main() -> Result<!, Error> {
|
||||
let args = ProgramArgs::try_from(std::env::args())?;
|
||||
fn run() -> Result<(), Error> {
|
||||
let conf = ProgramConfig::new("gravel.toml", std::env::args())?;
|
||||
|
||||
generate(&args.indir, &args.outdir, args.force)?;
|
||||
serve(args.addr, args.port, args.outdir)?;
|
||||
match conf.command {
|
||||
Command::Init => todo!("project init not implemented"),
|
||||
Command::Serve { addr, port } => serve(addr, port, conf.outdir)?,
|
||||
Command::Generate { force } => generate(&conf.indir, &conf.outdir, force)?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = run().map_err(|e| {
|
||||
log!(Level::Error, "{}", e);
|
||||
process::exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user