aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 466ffbc98eaf84fa7ec0bf7b0dbdf0f8b6179f03 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use std::path::PathBuf;

use clap::Parser;
use color_eyre::Result;
use error::{LuaXError, ReluaxError};

mod error;
mod luax;
mod server;

fn table_to_html<W: std::io::Write>(table: rlua::Table, f: &mut W) -> Result<()> {
    let type_name: Option<String> = table.get("tag").unwrap();

    if type_name.is_none() {
        return Err(ReluaxError::LuaX(LuaXError::MissingField("tag".to_string())).into());
    }

    let type_name = type_name.unwrap();

    write!(f, "<{}", type_name)?;
    let mut children = None;
    let mut attrs = None;
    for pair in table.pairs::<String, rlua::Value>() {
        let (key, value) = pair?;
        if key == "tag" {
            continue;
        }
        if key == "children" {
            children = Some(value);
            continue;
        }
        if key == "attrs" {
            attrs = Some(value);
            continue;
        }
    }
    if let Some(attrs) = attrs {
        if let rlua::Value::Table(attrs) = attrs {
            for pair in attrs.pairs::<String, rlua::String>() {
                let (key, value) = pair?;
                write!(f, " {}=\"{}\"", key, value.to_str()?)?;
            }
        } else {
            return Err(ReluaxError::LuaX(LuaXError::NonTableAttrs).into());
        }
    }
    write!(f, ">")?;

    if let Some(children) = children {
        if let rlua::Value::Table(children) = children {
            for child in children.sequence_values::<rlua::Value>() {
                match child? {
                    rlua::Value::Table(child) => table_to_html(child, f)?,
                    rlua::Value::String(s) => write!(f, "{}", s.to_str()?)?,
                    _ => return Err(ReluaxError::LuaX(LuaXError::NonTableChildren).into()),
                }
            }
        } else {
            return Err(ReluaxError::LuaX(LuaXError::NonTableChildren).into());
        }
    }

    write!(f, "</{}>", type_name)?;

    Ok(())
}

#[derive(Debug, Clone, clap::Parser)]
struct Args {
    #[clap(short = 'C', long = "current-dir", default_value = ".")]
    current_dir: std::path::PathBuf,
    #[clap(short = 'p', long = "port", default_value = "4310")]
    port: u16,
}

#[tokio::main]
async fn main() -> color_eyre::Result<()> {
    color_eyre::install().unwrap();
    let args = Args::parse();

    let current_dir = args.current_dir;

    if !current_dir.is_dir() {
        return Err(std::io::Error::new(
            std::io::ErrorKind::NotFound,
            format!("{} is not a directory", current_dir.display()),
        )
        .into());
    }

    std::env::set_current_dir(current_dir)?;

    luax::preprocess_dir(std::env::current_dir()?.as_path())?;

    println!("⛱️  Reluax files preprocessed!");

    let entry = PathBuf::from("reluax.lua");

    if !entry.is_file() {
        return Err(std::io::Error::new(
            std::io::ErrorKind::NotFound,
            format!("{} is not a file", entry.display()),
        )
        .into());
    }

    server::Server::serve(args.port).await?;

    Ok(())
}