From 453d9540634b96785099fa5dd486d46251c05605 Mon Sep 17 00:00:00 2001 From: soup Date: Fri, 17 May 2024 23:20:20 -0400 Subject: [PATCH] Initial commit --- .gitignore | 1 + Cargo.lock | 7 ++++ Cargo.toml | 6 +++ flake.lock | 97 +++++++++++++++++++++++++++++++++++++++++++ flake.nix | 26 ++++++++++++ rustfmt.toml | 5 +++ src/internal/mod.rs | 5 +++ src/internal/parse.rs | 58 ++++++++++++++++++++++++++ src/lib.rs | 67 ++++++++++++++++++++++++++++++ 9 files changed, 272 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 rustfmt.toml create mode 100644 src/internal/mod.rs create mode 100644 src/internal/parse.rs create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..baf1e29 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "newt" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..897d2ef --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "newt" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..db5fb5e --- /dev/null +++ b/flake.lock @@ -0,0 +1,97 @@ +{ + "nodes": { + "fenix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1715927173, + "narHash": "sha256-2S8hVck6nlyiBifzymDvePl5HWgqvVgxkBZCRax1qD8=", + "owner": "nix-community", + "repo": "fenix", + "rev": "a2d19ef9305841f26c8ab908b1c09a84ca307e18", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1715668745, + "narHash": "sha256-xp62OkRkbUDNUc6VSqH02jB0FbOS+MsfMb7wL1RJOfA=", + "path": "/nix/store/7q4y8idjk2di380j1fxn4k7wx9y935cl-source", + "rev": "9ddcaffecdf098822d944d4147dd8da30b4e6843", + "type": "path" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "root": { + "inputs": { + "fenix": "fenix", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1715839492, + "narHash": "sha256-EyjtjocGLtB7tqyqwBfadP4y5BBtT5EkoG3kq/zym5U=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "83ba42043166948db91fcfcfe30e0b7eac10b3d5", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..71e051b --- /dev/null +++ b/flake.nix @@ -0,0 +1,26 @@ +{ + inputs.nixpkgs.url = "nixpkgs"; + inputs.flake-utils.url = "github:numtide/flake-utils"; + inputs.fenix = { + url = "github:nix-community/fenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = { self, nixpkgs, flake-utils, fenix }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + fenix' = fenix.packages.${system}; + nightly = fenix'.default; + stable = fenix'.stable; + in { + devShells.default = pkgs.mkShell { + packages = [ (fenix'.combine [ + (stable.withComponents [ + "cargo" "rustc" "rust-src" "rust-analyzer" "clippy" + ]) + nightly.rustfmt + ]) pkgs.cargo-watch ]; + }; + }); +} diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..7000591 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,5 @@ +edition = "2021" +hard_tabs = true +match_block_trailing_comma = true +max_width = 80 +empty_item_single_line = false diff --git a/src/internal/mod.rs b/src/internal/mod.rs new file mode 100644 index 0000000..ba53dec --- /dev/null +++ b/src/internal/mod.rs @@ -0,0 +1,5 @@ +//! NOTE: Anything marked pub within this module or its children should not be +//! considered stable when it comes to semver. However, they are exposed for +//! advanced use cases. + +pub mod parse; diff --git a/src/internal/parse.rs b/src/internal/parse.rs new file mode 100644 index 0000000..0ef8e23 --- /dev/null +++ b/src/internal/parse.rs @@ -0,0 +1,58 @@ +use crate::Result; + +pub struct ValuePath {} +pub enum Expr { + ValuePath(ValuePath), +} + +pub struct If { + expr: Box, + then: Ast, + else_: Option, +} +pub struct For { + expr: Box, + body: Ast, +} +pub struct Has { + expr: Box, + body: Ast, +} +pub struct Print { + expr: Box, +} +pub enum AstKind { + Text(String), + Print(Print), + Has(Has), + If(If), + For(For), +} +pub type Ast = Vec; + +pub fn parse(template: &str) -> Result { + let mut out = Ast::new(); + let mut remaining = template; + while !remaining.is_empty() { + let (ast, r) = parse_one(remaining)?; + remaining = r; + out.push(ast); + } + Ok(out) +} + +pub fn parse_one(template: &str) -> Result<(AstKind, &str)> { + if template.starts_with("{{") { + parse_text(template) + } else if let Some(r) = template.strip_prefix('{') { + parse_block(r) + } else { + parse_text(template) + } +} + +pub fn parse_text(template: &str) -> Result<(AstKind, &str)> { + assert!(template.starts_with("{{") || !template.starts_with('{')); + + let template.trim_start_matches(|c| c != '{') +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..761647d --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,67 @@ +pub mod internal; + +use std::fmt::Write; + +pub enum Error {} +pub type Result = core::result::Result; + +pub trait Value { + fn print(&self, w: &mut dyn Write) -> core::fmt::Result; + fn has(&self) -> Option<&dyn Value> + where + Self: Sized, + { + Some(self) + } + + fn if_(&self) -> bool { + true + } + + fn for_(&self, index: usize) -> Option<&dyn Value> + where + Self: Sized, + { + if index == 0 { + Some(self) + } else { + None + } + } +} + +impl<'a, T> Value for &'a T +where + T: Value, +{ + fn print(&self, w: &mut dyn Write) -> core::fmt::Result { + (&**self).print(w) + } +} + +mod build {} + +pub struct Newt {} +impl Newt { + pub fn build(template: &str) -> Result { + } + + pub fn build_and_execute( + template: &str, + value: &dyn Value, + ) -> Result { + let newt = Newt::build(template)?; + + newt.execute(value) + } +} + +#[cfg(test)] +mod test { + #[test] + fn wishlist() { + let tmpl = r#"Hello, {.}"#; + let out = Newt::build_and_execute(tl, "World!").unwrap(); + assert_eq!(out, "Hello, World!"); + } +}