-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #417 from Ogeon/codegen
Replace the build script with a codegent crate
- Loading branch information
Showing
11 changed files
with
532 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[package] | ||
name = "codegen" | ||
version = "0.0.0" | ||
authors = ["Erik Hedvall <[email protected]>"] | ||
exclude = [] | ||
description = "Code generation crate for palette." | ||
repository = "https://github.com/Ogeon/palette" | ||
license = "MIT OR Apache-2.0" | ||
edition = "2018" | ||
publish = false | ||
|
||
[dependencies] | ||
anyhow = "1.0.86" | ||
proc-macro2 = "1.0.86" | ||
quote = "1.0.37" | ||
|
||
|
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
use std::{ | ||
fs::File, | ||
io::Write, | ||
path::Path, | ||
process::{Command, Output, Stdio}, | ||
}; | ||
|
||
use anyhow::{Context, Result}; | ||
use proc_macro2::TokenStream; | ||
|
||
const HEADER_COMMENT: &str = r#"// This file is auto-generated and any manual changes to it will be overwritten. | ||
// | ||
// Run `cargo run -p codegen` from the project root to regenerate it. | ||
"#; | ||
|
||
pub struct CodegenFile { | ||
file: File, | ||
} | ||
|
||
impl CodegenFile { | ||
/// Create a new generated file. | ||
pub fn create<P: AsRef<Path>>(path: P) -> Result<Self> { | ||
let path = path.as_ref(); | ||
let mut file = | ||
File::create(path).with_context(|| format!("could not open or create {path:?}"))?; | ||
|
||
writeln!(file, "{HEADER_COMMENT}")?; | ||
|
||
Ok(Self { file }) | ||
} | ||
|
||
/// Formats and appends the tokens to the output file. | ||
pub fn append(&mut self, tokens: TokenStream) -> Result<()> { | ||
// Taken from https://github.com/Michael-F-Bryan/scad-rs/blob/4dbff0c30ce991105f1e649e678d68c2767e894b/crates/codegen/src/pretty_print.rs | ||
|
||
let mut child = Command::new("rustfmt") | ||
.stdin(Stdio::piped()) | ||
.stdout(Stdio::piped()) | ||
.stderr(Stdio::piped()) | ||
.spawn() | ||
.context("unable to start `rustfmt`. Is it installed?")?; | ||
|
||
let mut stdin = child.stdin.take().unwrap(); | ||
write!(stdin, "{tokens}")?; | ||
stdin.flush()?; | ||
drop(stdin); | ||
|
||
let Output { | ||
status, | ||
stdout, | ||
stderr, | ||
} = child.wait_with_output()?; | ||
let stdout = String::from_utf8_lossy(&stdout); | ||
let stderr = String::from_utf8_lossy(&stderr); | ||
|
||
if !status.success() { | ||
eprintln!("---- Stdout ----"); | ||
eprintln!("{stdout}"); | ||
eprintln!("---- Stderr ----"); | ||
eprintln!("{stderr}"); | ||
let code = status.code(); | ||
match code { | ||
Some(code) => anyhow::bail!("the `rustfmt` command failed with return code {code}"), | ||
None => anyhow::bail!("the `rustfmt` command failed"), | ||
} | ||
} | ||
|
||
writeln!(self.file, "{stdout}")?; | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
use anyhow::{Context, Result}; | ||
|
||
mod codegen_file; | ||
mod named; | ||
|
||
fn main() -> Result<()> { | ||
named::generate().context("could not generate named color constants")?; | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
use std::{ | ||
fs::File, | ||
io::{BufRead, BufReader}, | ||
}; | ||
|
||
use anyhow::{Context, Result}; | ||
use proc_macro2::{Ident, Span, TokenStream}; | ||
use quote::quote; | ||
|
||
use crate::codegen_file::CodegenFile; | ||
|
||
pub fn generate() -> Result<()> { | ||
let mut file = CodegenFile::create("palette/src/named/codegen.rs")?; | ||
|
||
let colors = parse_colors()?; | ||
|
||
file.append(build_colors(&colors))?; | ||
file.append(build_from_str(&colors))?; | ||
|
||
Ok(()) | ||
} | ||
|
||
struct ColorEntry { | ||
name: String, | ||
constant: Ident, | ||
red: u8, | ||
green: u8, | ||
blue: u8, | ||
} | ||
|
||
fn parse_colors() -> Result<Vec<ColorEntry>> { | ||
let reader = BufReader::new( | ||
File::open("codegen/res/svg_colors.txt").expect("could not open svg_colors.txt"), | ||
); | ||
|
||
// Expected format: "name\t123, 123, 123" | ||
reader | ||
.lines() | ||
.map(|line| { | ||
let line = line?; | ||
let mut parts = line.split('\t'); | ||
|
||
let name = parts | ||
.next() | ||
.context("couldn't get the color name")? | ||
.to_owned(); | ||
let mut rgb = parts | ||
.next() | ||
.with_context(|| format!("couldn't get RGB for {}", name))? | ||
.split(", "); | ||
|
||
let red: u8 = rgb | ||
.next() | ||
.with_context(|| format!("missing red for {name}"))? | ||
.trim() | ||
.parse() | ||
.with_context(|| format!("couldn't parse red for {}", name))?; | ||
|
||
let green: u8 = rgb | ||
.next() | ||
.with_context(|| format!("missing green for {name}"))? | ||
.trim() | ||
.parse() | ||
.with_context(|| format!("couldn't parse green for {}", name))?; | ||
|
||
let blue: u8 = rgb | ||
.next() | ||
.with_context(|| format!("missing blue for {name}"))? | ||
.trim() | ||
.parse() | ||
.with_context(|| format!("couldn't parse blue for {}", name))?; | ||
|
||
let constant = Ident::new(&name.to_ascii_uppercase(), Span::call_site()); | ||
|
||
Ok(ColorEntry { | ||
name, | ||
constant, | ||
red, | ||
green, | ||
blue, | ||
}) | ||
}) | ||
.collect() | ||
} | ||
|
||
fn build_colors(colors: &[ColorEntry]) -> TokenStream { | ||
let constants = colors.iter().map(|ColorEntry { name, constant, red, green, blue }| { | ||
let swatch_html = format!( | ||
r#"<div style="display: inline-block; width: 3em; height: 1em; border: 1px solid black; background: {name};"></div>"# | ||
); | ||
|
||
quote! { | ||
#[doc = #swatch_html] | ||
pub const #constant: crate::rgb::Srgb<u8> = crate::rgb::Srgb::new(#red, #green, #blue); | ||
} | ||
}); | ||
|
||
quote! { | ||
#(#constants)* | ||
} | ||
} | ||
|
||
fn build_from_str(entries: &[ColorEntry]) -> TokenStream { | ||
let entries = entries | ||
.iter() | ||
.map(|ColorEntry { name, constant, .. }| quote! {#name => #constant}); | ||
|
||
quote! { | ||
#[cfg(feature = "named_from_str")] | ||
pub(crate) static COLORS: ::phf::Map<&'static str, crate::rgb::Srgb<u8>> = phf::phf_map! { | ||
#(#entries),* | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.