initial os release. I really expect SO much bugs, guys. good luck =)

This commit is contained in:
Yiffy Dev 2024-10-30 10:59:43 +05:00 • committed by spushk
commit 7d39af11b7
Signed by: spushk
GPG key ID: 7797B761E105E8AA

View file

@ -0,0 +1,202 @@
use std::{fmt::Debug, fs};
use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens, TokenStreamExt};
use sabry_intrnl::compiler::CompilerSyntax;
use syn::{braced, parse::Parse, spanned::Spanned, Ident, LitStr, Token};
pub mod sassy;
pub mod styly;
pub mod usey;
/// Macro input for arbitrary style code
///
/// Also supports string literal token instead of braces,
/// in which mode will look for relative file
///
/// Does not work nice with rust-analyzer though
#[derive(Clone, Debug)]
pub struct ArbitraryStyleBlock {
code: String,
span: Span,
}
impl ArbitraryStyleBlock {
pub fn span(&self) -> Span {
self.span
}
pub fn code(&self) -> &str {
&self.code
}
}
impl Parse for ArbitraryStyleBlock {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let (code, span) = if let Ok(path_tok) = input.parse::<LitStr>() {
let path = path_tok.value();
let iofile = match fs::read(&path) {
Ok(bf) => bf,
Err(_) => return Err(syn::Error::new(path_tok.span(), format!("Could not read file '{path}'. Perhaps its relative? Thats not currently supported :(")))
};
let code = String::from_utf8_lossy(&iofile).to_string();
(code, path_tok.span())
} else {
// Does not work on stable!
// We're on nightly though
// So what?
// Then is works.
let _s;
braced!(_s in input);
let stream = _s.parse::<TokenStream>()?;
let c = match stream.span().source_text() {
Some(stx) => stx,
// TODO: rust-analyzer does fall into this even if all is fine
None => "".to_string(), //return Err(syn::Error::new(stream.span(), "Source code expected")),
};
(c, stream.span())
};
Ok(Self { code, span })
}
}
#[allow(clippy::to_string_trait_impl)]
impl ToString for ArbitraryStyleBlock {
fn to_string(&self) -> String {
self.code.clone()
}
}
#[derive(Clone, Copy)]
pub enum ArbitraryStyleSyntax {
#[cfg(feature = "scss")]
Scss,
#[cfg(feature = "sass")]
Sass,
}
impl From<ArbitraryStyleSyntax> for CompilerSyntax {
fn from(value: ArbitraryStyleSyntax) -> Self {
match value {
#[cfg(feature = "sass")]
ArbitraryStyleSyntax::Sass => Self::Sass,
#[cfg(feature = "scss")]
ArbitraryStyleSyntax::Scss => Self::Scss,
}
}
}
impl ToTokens for ArbitraryStyleSyntax {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
#[cfg(feature = "sass")]
Self::Sass => tokens.append_all(quote! {"sass"}),
#[cfg(feature = "scss")]
Self::Scss => tokens.append_all(quote! {"scss"}),
}
}
}
impl Parse for ArbitraryStyleSyntax {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
match input.parse::<Token![:]>() {
Ok(_) => { /* Syntax is set */ }
Err(_) => {
/* Syntax is not set, falling to default */
return Ok(Self::default());
}
}
let ident = input.parse::<Ident>()?;
match ident.to_string().as_str() {
#[cfg(feature = "sass")]
"sass" => Ok(Self::Sass),
#[cfg(feature = "scss")]
"scss" => Ok(Self::Scss),
_ => Err(syn::Error::new(
ident.span(),
format!(
"Available syntax are `sass` (WIP) and `scss`, each of them requires feature flag. Omit to use default {:?} syntax",
Self::default()
),
)),
}
}
}
impl Debug for ArbitraryStyleSyntax {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let name = match self {
#[cfg(feature = "sass")]
Self::Sass => "sass",
#[cfg(feature = "scss")]
Self::Scss => "scss",
};
write!(f, "{name}")
}
}
impl Default for ArbitraryStyleSyntax {
#[cfg(feature = "scss")]
fn default() -> Self {
Self::Scss
}
#[cfg(all(feature = "sass", not(feature = "scss")))]
fn default() -> Self {
Self::Sass
}
}
impl From<ArbitraryStyleSyntax> for raffia::Syntax {
fn from(value: ArbitraryStyleSyntax) -> Self {
match value {
#[cfg(feature = "sass")]
ArbitraryStyleSyntax::Sass => Self::Sass,
#[cfg(feature = "scss")]
ArbitraryStyleSyntax::Scss => Self::Scss,
}
}
}
#[cfg(test)]
mod test {
#[cfg(feature = "sass")]
#[test]
fn arbitrary_style_block_sass() {
use super::ArbitraryStyleBlock;
let code = "#a
co:d
.sel
di: pi
.sel,div > sel
f: \"into\"";
let braced_code = format!("{{{code}}}");
let block = syn::parse_str::<ArbitraryStyleBlock>(&braced_code).unwrap();
assert_eq!(code, block.code);
}
#[cfg(feature = "scss")]
#[test]
fn arbitrary_style_block_scss() {
use super::ArbitraryStyleBlock;
let code = "#a {
c:r;
}
.b.c{
c:\"into\";
}";
let braced_code = format!("{{{code}}}");
let block = syn::parse_str::<ArbitraryStyleBlock>(&braced_code).unwrap();
assert_eq!(code, block.code)
}
}