diff --git a/.justfile b/.justfile
index f34bf85..19b6f7f 100644
--- a/.justfile
+++ b/.justfile
@@ -6,7 +6,7 @@ _default:
# Build on changes
[group('dev')]
serve-watch:
- bacon --job run-long -- localhost:3003
+ bacon --job run-long -- -- --host localhost --port 3003
alias sw := serve-watch
alias dev := serve-watch
@@ -37,7 +37,7 @@ push: check
# Start server
[group('run')]
serve:
- cargo run localhost:3003
+ cargo run -- --hostname localhost --port 3003
alias s := serve
diff --git a/src/formats.rs b/src/formats.rs
index 2054962..28eff67 100644
--- a/src/formats.rs
+++ b/src/formats.rs
@@ -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}"),
};
diff --git a/src/handlers/fixed.rs b/src/handlers/fixed.rs
index c9b0fb0..a74093c 100644
--- a/src/handlers/fixed.rs
+++ b/src/handlers/fixed.rs
@@ -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
{
diff --git a/src/handlers/graph.rs b/src/handlers/graph.rs
index dfabf82..8b16b69 100644
--- a/src/handlers/graph.rs
+++ b/src/handlers/graph.rs
@@ -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) -> Response {
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);
diff --git a/src/main.rs b/src/main.rs
index edeb0c7..1d637e8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -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 =
@@ -14,9 +15,8 @@ static ONSET: sync::LazyLock =
#[tokio::main]
async fn main() -> io::Result<()> {
- let args: Vec = 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:#?}"),
diff --git a/src/syntax.rs b/src/syntax.rs
new file mode 100644
index 0000000..d08cc22
--- /dev/null
+++ b/src/syntax.rs
@@ -0,0 +1 @@
+pub mod arguments;
diff --git a/src/syntax/arguments.rs b/src/syntax/arguments.rs
new file mode 100644
index 0000000..4226474
--- /dev/null
+++ b/src/syntax/arguments.rs
@@ -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 = 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
+}