Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce #[css(if_empty = "…", iterable)] #20230

Merged
merged 2 commits into from Mar 7, 2018
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Prev

Introduce #[css(if_empty = "…", iterable)]

  • Loading branch information
nox committed Mar 7, 2018
commit 90b23963b715b294d292f63bfbdaf609aef1448b
@@ -83,10 +83,6 @@
need_animatable=need_animatable, **kwargs)">
#[allow(unused_imports)]
use smallvec::SmallVec;
% if allow_empty:
use std::fmt::{self, Write};
use style_traits::{CssWriter, Separator, ToCss};
% endif

pub mod single_value {
#[allow(unused_imports)]
@@ -120,23 +116,22 @@
use values::computed::ComputedVecIter;

/// The computed value, effectively a list of single values.
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
% if need_animatable or animation_value_type == "ComputedValue":
#[derive(Animate, ComputeSquaredDistance)]
% endif
% if not allow_empty:
% if separator == "Comma":
#[css(comma)]
% endif
#[derive(ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
% if need_animatable or animation_value_type == "ComputedValue":
#[derive(Animate, ComputeSquaredDistance)]
% endif
pub struct T(
% if allow_empty and allow_empty != "NotInitial":
pub Vec<single_value::T>,
% else:
% if not allow_empty:
#[css(iterable)]
% else:
#[css(if_empty = "none", iterable)]

This comment has been minimized.

@emilio

emilio Mar 7, 2018

Member

Nice, thanks for cleaning this up :)

% endif
% if allow_empty and allow_empty != "NotInitial":
pub Vec<single_value::T>,
% else:
pub SmallVec<[single_value::T; 1]>,
% endif
);
@@ -165,63 +160,20 @@
}
}

% if allow_empty:
impl ToCss for computed_value::T {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
let mut iter = self.0.iter();
if let Some(val) = iter.next() {
val.to_css(dest)?;
} else {
return dest.write_str("none");
}
for i in iter {
dest.write_str(::style_traits::${separator}::separator())?;
i.to_css(dest)?;
}
Ok(())
}
}
% endif

/// The specified value of ${name}.
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
% if not allow_empty:
% if separator == "Comma":
#[css(comma)]
% endif
#[derive(ToCss)]
% endif
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
pub struct SpecifiedValue(
% if not allow_empty:
#[css(iterable)]
% else:
#[css(if_empty = "none", iterable)]
% endif
pub Vec<single_value::SpecifiedValue>,
);

% if allow_empty:
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
let mut iter = self.0.iter();
if let Some(val) = iter.next() {
val.to_css(dest)?;
} else {
return dest.write_str("none");
}
for i in iter {
dest.write_str(::style_traits::${separator}::separator())?;
i.to_css(dest)?;
}
Ok(())
}
}
% endif

pub fn get_initial_value() -> computed_value::T {
% if allow_empty and allow_empty != "NotInitial":
computed_value::T(vec![])
@@ -736,9 +736,12 @@ pub enum VariantAlternates {
HistoricalForms,
}

#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
/// List of Variant Alternates
pub struct VariantAlternatesList(pub Box<[VariantAlternates]>);
pub struct VariantAlternatesList(
#[css(if_empty = "normal", iterable)]
pub Box<[VariantAlternates]>,
);

impl VariantAlternatesList {
/// Returns the length of all variant alternates.
@@ -759,25 +762,6 @@ impl VariantAlternatesList {
}
}

impl ToCss for VariantAlternatesList {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if self.0.is_empty() {
return dest.write_str("normal");
}

let mut iter = self.0.iter();
iter.next().unwrap().to_css(dest)?;
for alternate in iter {
dest.write_str(" ")?;
alternate.to_css(dest)?;
}
Ok(())
}
}

#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
/// Control over the selection of these alternate glyphs
pub enum FontVariantAlternates {
@@ -150,6 +150,20 @@ fn derive_single_field_expr(
where_clause: &mut WhereClause,
) -> Tokens {
if attrs.iterable {
if let Some(if_empty) = attrs.if_empty {
return quote! {
{
let mut iter = #field.iter().peekable();

This comment has been minimized.

@emilio

emilio Mar 7, 2018

Member

There's no need to use peekable, right? You could just match on the first element returned and such... Not a big deal I guess.

if iter.peek().is_none() {
writer.item(&::style_traits::values::Verbatim(#if_empty))?;
} else {
for item in iter {
writer.item(&item)?;
}
}
}
};
}
quote! {
for item in #field.iter() {
writer.item(&item)?;
@@ -186,6 +200,7 @@ pub struct CssVariantAttrs {
#[darling(attributes(css), default)]
#[derive(Default, FromField)]
struct CssFieldAttrs {
if_empty: Option<String>,
ignore_bound: bool,
iterable: bool,
skip: bool,
@@ -27,6 +27,8 @@ use std::fmt::{self, Write};
/// * if `#[css(iterable)]` is found on a function variant, that variant needs
/// to have a single member, and that member needs to be iterable. The
/// iterable will be serialized as the arguments for the function;
/// * an iterable field can also be annotated with `#[css(if_empty = "foo")]`
/// to print `"foo"` if the iterator is empty;
/// * if `#[css(dimension)]` is found on a variant, that variant needs
/// to have a single member. The variant would be serialized as a CSS
/// dimension token, like: <member><identifier>;
@@ -210,6 +212,21 @@ where
}
}

/// A wrapper type that implements `ToCss` by printing its inner field.
pub struct Verbatim<'a, T>(pub &'a T)
where
T: ?Sized + 'a;

impl<'a, T> ToCss for Verbatim<'a, T>
where
T: AsRef<str> + ?Sized + 'a,
{
#[inline]
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: Write {
dest.write_str(self.0.as_ref())
}
}

/// Type used as the associated type in the `OneOrMoreSeparated` trait on a
/// type to indicate that a serialized list of elements of this type is
/// separated by commas.
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.