1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
use crate::lang::Lang;
use crate::tokens;
use crate::Tokens;

/// Construct a [FormatInto][crate::tokens::FormatInto] implementation from a
/// function.
///
/// # Examples
///
/// ```
/// use genco::{quote, quote_in};
/// use genco::lang::{Lang, Rust};
/// use genco::tokens::{ItemStr, FormatInto, Tokens, from_fn, static_literal};
///
/// fn comment(s: impl Into<ItemStr> + Copy) -> impl FormatInto<Rust> + Copy {
///     from_fn(move |tokens| {
///         let s = s.into();
///         quote_in!(*tokens => $(static_literal("//")) #s);
///     })
/// }
///
/// let c = comment("hello world");
/// let _: Tokens<Rust> = quote!($c $['\n'] $c);
/// # Ok::<_, genco::fmt::Error>(())
/// ```
pub fn from_fn<F, L>(f: F) -> FromFn<F>
where
    F: FnOnce(&mut Tokens<L>),
    L: Lang,
{
    FromFn { f }
}

/// A captured function used for formatting tokens.
///
/// Constructed using [from_fn()] or the [quote_fn!][crate::quote_fn] macro.
#[derive(Clone, Copy)]
pub struct FromFn<F> {
    f: F,
}

impl<L, F> tokens::FormatInto<L> for FromFn<F>
where
    L: Lang,
    F: FnOnce(&mut Tokens<L>),
{
    fn format_into(self, tokens: &mut Tokens<L>) {
        (self.f)(tokens);
    }
}