Handle CLI arguments as structured argument-parameter pairs

This commit is contained in:
Juno Takano 2025-12-14 15:08:55 -03:00
commit 2040854e82
7 changed files with 83 additions and 15 deletions

View file

@ -1,9 +1,13 @@
use std::collections::HashMap;
use crate::types::{Graph, Node, Edge};
use crate::{
syntax::arguments::Arguments,
types::{Edge, Graph, Node},
};
pub fn populate_graph() -> Graph {
let toml_source = match std::fs::read_to_string("./static/graph.toml") {
let args = Arguments::new().parse();
let toml_source = match std::fs::read_to_string(args.graph_path) {
Ok(s) => s,
Err(e) => format!("Error: {e}"),
};

View file

@ -3,7 +3,9 @@ use axum::{
http::{Response, StatusCode, header, HeaderValue},
};
use crate::formats::{Format, populate_graph, serialize_graph};
use crate::{
formats::{Format, populate_graph, serialize_graph},
};
use crate::handlers;
pub async fn file(file_path: &str, content_type: &str) -> Response<Body> {

View file

@ -1,16 +1,14 @@
use axum::{body::Body, extract::Path, http::Response};
use crate::{formats::populate_graph, types::Node, handlers};
use crate::{formats::populate_graph, handlers, types::Node};
pub async fn node(Path(id): Path<String>) -> Response<Body> {
let mut context = tera::Context::new();
let graph = populate_graph();
let nodes = graph.nodes;
let empty_node =
Node::new(Some(format!("Could not find node with ID {id}.")));
let empty_node = Node::new(Some(format!("Could not find node ID {id}.")));
let node: &Node = nodes.get(&id).unwrap_or(&empty_node);
let node: &Node = graph.nodes.get(&id).unwrap_or(&empty_node);
context.insert("id", &id);
context.insert("title", &node.title);

View file

@ -1,4 +1,4 @@
use std::{backtrace, env, io, panic, sync, time};
use std::{backtrace, io, panic, sync, time};
use axum::{routing::get, Router};
@ -7,6 +7,7 @@ use formats::Format;
mod formats;
mod types;
mod handlers;
mod syntax;
mod dev;
static ONSET: sync::LazyLock<time::Instant> =
@ -14,9 +15,8 @@ static ONSET: sync::LazyLock<time::Instant> =
#[tokio::main]
async fn main() -> io::Result<()> {
let args: Vec<String> = env::args().collect();
let default_address = "0.0.0.0:0".to_string();
let address: &String = args.get(1).unwrap_or(&default_address);
let args = syntax::arguments::Arguments::new().parse();
let address = args.make_address();
panic::set_hook(Box::new(|info| {
let payload = info
@ -73,7 +73,7 @@ async fn main() -> io::Result<()> {
.fallback(handlers::error::not_found);
let listener =
tokio::net::TcpListener::bind(address).await.map_err(|e| {
tokio::net::TcpListener::bind(&address).await.map_err(|e| {
dev::log(
&main,
&format!("Failed to create listener at {address}: {e:#?}"),

1
src/syntax.rs Normal file
View file

@ -0,0 +1 @@
pub mod arguments;

63
src/syntax/arguments.rs Normal file
View file

@ -0,0 +1,63 @@
use std::path::PathBuf;
#[derive(Clone, Debug)]
pub struct Arguments {
pub hostname: String,
pub port: u16,
pub graph_path: PathBuf,
}
impl Arguments {
pub fn make_address(&self) -> String {
format!("{}:{}", self.hostname, self.port)
}
pub fn new() -> Arguments {
Arguments {
hostname: String::from("0.0.0.0"),
port: 0,
graph_path: PathBuf::from("./static/graph.toml"),
}
}
pub fn parse(&self) -> Arguments {
let args: Vec<String> = std::env::args().collect();
parse(self, &args)
}
}
fn parse(defaults: &Arguments, args: &[String]) -> Arguments {
let mut out_args = defaults.clone();
let filtered_args = if let Some((head, tail)) = args.split_first() {
if head.starts_with('-') { args } else { tail }
} else {
args
};
for arg in filtered_args.chunks(2) {
if let Some(argument) = arg.first()
&& let Some(parameter) = arg.last()
{
if argument.eq("-h") || argument.eq("--hostname") {
out_args.hostname = String::from(parameter);
} else if argument.eq("-p") || argument.eq("--port") {
out_args.port = parameter.parse().unwrap_or(out_args.port);
} else if argument.eq("-g") || argument.eq("--graph") {
out_args.graph_path = PathBuf::from(parameter);
} else {
crate::dev::log(
&parse,
&format!("Dropped unrecognized argument {argument}"),
);
}
} else {
crate::dev::log(
&parse,
"Dropped: Couldn't pair either one of or
both argument \"{argument}\", parameter \"{parameter}\"",
);
}
}
out_args
}