use {
crate::{
Alignment,
Formattable,
FormattablePunct,
MakeSegsState,
SplitGroupBuilder,
SplitGroupIdx,
new_sg,
sg_general::{
append_whitespace,
has_comments,
},
whitespace::HashLineColumn,
},
proc_macro2::LineColumn,
quote::ToTokens,
syn::{
Expr,
punctuated::Punctuated,
},
};
pub(crate) fn append_bracketed_list<
E: Formattable + ToTokens,
T: FormattablePunct,
F: Formattable,
>(
out: &mut MakeSegsState,
base_indent: &Alignment,
sg: &mut SplitGroupBuilder,
prefix_start: LineColumn,
prefix: &str,
bracket_space: bool,
punct: &str,
exprs: &Punctuated<E, T>,
list_suffix: InlineListSuffix<F>,
suffix_start: LineColumn,
suffix: &str,
) {
if out.whitespaces.contains_key(&HashLineColumn(suffix_start)) {
sg.initial_split();
}
append_whitespace(out, base_indent, sg, prefix_start);
sg.seg(out, prefix);
let indent = base_indent.indent();
let empty = exprs.is_empty() && !matches!(&list_suffix, InlineListSuffix::Extra(_));
if !empty {
if bracket_space {
sg.seg_unsplit(out, " ");
}
sg.split(out, indent.clone(), true);
append_inline_list_raw(out, &indent, sg, punct, exprs, list_suffix);
if bracket_space {
sg.seg_unsplit(out, " ");
}
}
append_whitespace(out, &indent, sg, suffix_start);
if !empty {
sg.split(out, base_indent.clone(), false);
}
sg.seg(out, suffix);
}
pub(crate) fn append_bracketed_list_common<
E: Formattable + ToTokens,
T: FormattablePunct,
>(
out: &mut MakeSegsState,
base_indent: &Alignment,
sg: &mut SplitGroupBuilder,
prefix_start: LineColumn,
prefix: &str,
exprs: &Punctuated<E, T>,
suffix_start: LineColumn,
suffix: &str,
) {
append_bracketed_list(
out,
base_indent,
sg,
prefix_start,
prefix,
false,
",",
exprs,
if out.macro_depth.get() == 0 {
InlineListSuffix::<Expr>::Punct
} else {
InlineListSuffix::VerbatimPunct
},
suffix_start,
suffix,
);
}
pub(crate) fn append_bracketed_list_curly<
E: Formattable + ToTokens,
T: FormattablePunct,
>(
out: &mut MakeSegsState,
base_indent: &Alignment,
sg: &mut SplitGroupBuilder,
prefix_start: LineColumn,
exprs: &Punctuated<E, T>,
extra: Option<impl Formattable>,
suffix_start: LineColumn,
) {
append_bracketed_list(out, base_indent, sg, prefix_start, " {", true, ",", exprs, match extra {
Some(e) => InlineListSuffix::Extra(e),
None => if out.macro_depth.get() == 0 {
InlineListSuffix::Punct
} else {
InlineListSuffix::VerbatimPunct
},
}, suffix_start, "}")
}
pub(crate) fn append_inline_list<
E: Formattable + ToTokens,
T: FormattablePunct,
F: Formattable,
>(
out: &mut MakeSegsState,
base_indent: &Alignment,
sg: &mut SplitGroupBuilder,
punct: &str,
exprs: &Punctuated<E, T>,
suffix: InlineListSuffix<F>,
) {
let indent = base_indent.indent();
sg.split(out, indent.clone(), true);
append_inline_list_raw(out, &indent, sg, punct, exprs, suffix);
}
pub(crate) fn append_inline_list_raw<
E: Formattable + ToTokens,
T: FormattablePunct,
F: Formattable,
>(
out: &mut MakeSegsState,
base_indent: &Alignment,
sg: &mut SplitGroupBuilder,
punct: &str,
exprs: &Punctuated<E, T>,
suffix: InlineListSuffix<F>,
) {
if exprs
.pairs()
.any(|s| has_comments(out, s.value()) || (s.value().has_attrs() && out.config.split_attributes)) {
sg.initial_split();
}
let mut next_punct: Option<&T> = None;
for (i, pair) in exprs.pairs().enumerate() {
if i > 0 {
if let Some(p) = next_punct.take() {
append_whitespace(out, base_indent, sg, p.span_start());
sg.seg(out, punct);
}
sg.split(out, base_indent.clone(), true);
sg.seg_unsplit(out, " ");
}
sg.child(pair.value().make_segs(out, base_indent));
next_punct = pair.punct().copied();
}
match suffix {
InlineListSuffix::None => {
if let Some(p) = next_punct {
append_whitespace(out, base_indent, sg, p.span_start());
}
},
InlineListSuffix::UnitPunct if exprs.len() == 1 => {
if let Some(p) = next_punct {
append_whitespace(out, base_indent, sg, p.span_start());
sg.seg(out, punct);
} else if !exprs.is_empty() {
sg.seg(out, punct);
}
},
InlineListSuffix::Punct | InlineListSuffix::UnitPunct => {
if let Some(p) = next_punct {
append_whitespace(out, base_indent, sg, p.span_start());
sg.seg_split(out, punct);
} else if !exprs.is_empty() {
sg.seg_split(out, punct);
}
},
InlineListSuffix::VerbatimPunct => {
if let Some(p) = next_punct {
append_whitespace(out, base_indent, sg, p.span_start());
sg.seg(out, punct);
}
},
InlineListSuffix::Extra(e) => {
if let Some(p) = next_punct {
append_whitespace(out, base_indent, sg, p.span_start());
sg.seg(out, punct);
} else if !exprs.is_empty() {
sg.seg(out, punct);
}
if !exprs.is_empty() {
sg.split(out, base_indent.clone(), true);
sg.seg_unsplit(out, " ");
}
e.make_segs(out, base_indent);
},
}
}
pub(crate) enum InlineListSuffix<T: Formattable> {
Extra(T),
None,
Punct,
UnitPunct,
VerbatimPunct,
}
pub(crate) fn new_sg_bracketed_list<
E: Formattable + ToTokens,
T: FormattablePunct,
F: Formattable,
>(
out: &mut MakeSegsState,
base_indent: &Alignment,
prefix_start: LineColumn,
prefix: &str,
bracket_space: bool,
punct: &str,
exprs: &Punctuated<E, T>,
list_suffix: InlineListSuffix<F>,
suffix_start: LineColumn,
suffix: &str,
) -> SplitGroupIdx {
let mut sg = new_sg(out);
append_bracketed_list(
out,
base_indent,
&mut sg,
prefix_start,
prefix,
bracket_space,
punct,
exprs,
list_suffix,
suffix_start,
suffix,
);
sg.build(out)
}
pub(crate) fn new_sg_bracketed_list_common<
E: Formattable + ToTokens,
T: FormattablePunct,
>(
out: &mut MakeSegsState,
base_indent: &Alignment,
prefix_start: LineColumn,
prefix: &str,
exprs: &Punctuated<E, T>,
suffix_start: LineColumn,
suffix: &str,
) -> SplitGroupIdx {
new_sg_bracketed_list(out, base_indent, prefix_start, prefix, false, ",", exprs, if out.macro_depth.get() == 0 {
InlineListSuffix::<Expr>::Punct
} else {
InlineListSuffix::VerbatimPunct
}, suffix_start, suffix)
}