styleable_helpers.rs

  1use proc_macro::TokenStream;
  2use proc_macro2::TokenStream as TokenStream2;
  3use quote::{format_ident, quote};
  4use syn::{
  5    parse::{Parse, ParseStream, Result},
  6    parse_macro_input,
  7};
  8
  9struct StyleableMacroInput;
 10
 11impl Parse for StyleableMacroInput {
 12    fn parse(_input: ParseStream) -> Result<Self> {
 13        Ok(StyleableMacroInput)
 14    }
 15}
 16
 17pub fn styleable_helpers(input: TokenStream) -> TokenStream {
 18    let _ = parse_macro_input!(input as StyleableMacroInput);
 19    let methods = generate_methods();
 20    let output = quote! {
 21        #(#methods)*
 22    };
 23    output.into()
 24}
 25
 26fn generate_methods() -> Vec<TokenStream2> {
 27    let mut methods = Vec::new();
 28
 29    for (prefix, auto_allowed, fields) in tailwind_prefixes() {
 30        for (suffix, length_tokens) in tailwind_lengths() {
 31            if !auto_allowed && suffix == "auto" {
 32                // Conditional to skip "auto"
 33                continue;
 34            }
 35
 36            let method_name = format_ident!("{}_{}", prefix, suffix);
 37            let field_assignments = fields
 38                .iter()
 39                .map(|field_tokens| {
 40                    quote! {
 41                        style.#field_tokens = Some(gpui::geometry::#length_tokens);
 42                    }
 43                })
 44                .collect::<Vec<_>>();
 45
 46            let method = quote! {
 47                fn #method_name(mut self) -> Self where Self: std::marker::Sized {
 48                    let mut style = self.declared_style();
 49                    #(#field_assignments)*
 50                    self
 51                }
 52            };
 53
 54            methods.push(method);
 55        }
 56    }
 57
 58    methods
 59}
 60
 61fn tailwind_lengths() -> Vec<(&'static str, TokenStream2)> {
 62    vec![
 63        ("0", quote! { pixels(0.) }),
 64        ("1", quote! { rems(0.25) }),
 65        ("2", quote! { rems(0.5) }),
 66        ("3", quote! { rems(0.75) }),
 67        ("4", quote! { rems(1.) }),
 68        ("5", quote! { rems(1.25) }),
 69        ("6", quote! { rems(1.5) }),
 70        ("8", quote! { rems(2.0) }),
 71        ("10", quote! { rems(2.5) }),
 72        ("12", quote! { rems(3.) }),
 73        ("16", quote! { rems(4.) }),
 74        ("20", quote! { rems(5.) }),
 75        ("24", quote! { rems(6.) }),
 76        ("32", quote! { rems(8.) }),
 77        ("40", quote! { rems(10.) }),
 78        ("48", quote! { rems(12.) }),
 79        ("56", quote! { rems(14.) }),
 80        ("64", quote! { rems(16.) }),
 81        ("72", quote! { rems(18.) }),
 82        ("80", quote! { rems(20.) }),
 83        ("96", quote! { rems(24.) }),
 84        ("auto", quote! { auto() }),
 85        ("px", quote! { pixels(1.) }),
 86        ("full", quote! { relative(1.) }),
 87        ("1_2", quote! { relative(0.5) }),
 88        ("1_3", quote! { relative(1./3.) }),
 89        ("2_3", quote! { relative(2./3.) }),
 90        ("1_4", quote! { relative(0.25) }),
 91        ("2_4", quote! { relative(0.5) }),
 92        ("3_4", quote! { relative(0.75) }),
 93        ("1_5", quote! { relative(0.2) }),
 94        ("2_5", quote! { relative(0.4) }),
 95        ("3_5", quote! { relative(0.6) }),
 96        ("4_5", quote! { relative(0.8) }),
 97        ("1_6", quote! { relative(1./6.) }),
 98        ("5_6", quote! { relative(5./6.) }),
 99        ("1_12", quote! { relative(1./12.) }),
100        // ("screen_50", quote! { DefiniteLength::Vh(50.0) }),
101        // ("screen_75", quote! { DefiniteLength::Vh(75.0) }),
102        // ("screen", quote! { DefiniteLength::Vh(100.0) }),
103    ]
104}
105
106fn tailwind_prefixes() -> Vec<(&'static str, bool, Vec<TokenStream2>)> {
107    vec![
108        ("w", true, vec![quote! { size.width }]),
109        ("h", true, vec![quote! { size.height }]),
110        ("min_w", false, vec![quote! { min_size.width }]),
111        ("min_h", false, vec![quote! { min_size.height }]),
112        ("max_w", false, vec![quote! { max_size.width }]),
113        ("max_h", false, vec![quote! { max_size.height }]),
114        (
115            "m",
116            true,
117            vec![quote! { margin.top }, quote! { margin.bottom }],
118        ),
119        ("mt", true, vec![quote! { margin.top }]),
120        ("mb", true, vec![quote! { margin.bottom }]),
121        (
122            "mx",
123            true,
124            vec![quote! { margin.left }, quote! { margin.right }],
125        ),
126        ("ml", true, vec![quote! { margin.left }]),
127        ("mr", true, vec![quote! { margin.right }]),
128        (
129            "p",
130            false,
131            vec![quote! { padding.top }, quote! { padding.bottom }],
132        ),
133        ("pt", false, vec![quote! { padding.top }]),
134        ("pb", false, vec![quote! { padding.bottom }]),
135        (
136            "px",
137            false,
138            vec![quote! { padding.left }, quote! { padding.right }],
139        ),
140        ("pl", false, vec![quote! { padding.left }]),
141        ("pr", false, vec![quote! { padding.right }]),
142        ("top", true, vec![quote! { inset.top }]),
143        ("bottom", true, vec![quote! { inset.bottom }]),
144        ("left", true, vec![quote! { inset.left }]),
145        ("right", true, vec![quote! { inset.right }]),
146    ]
147}