use core::fmt::Write as _;
use alloc::collections::BTreeSet;
use crate as genco;
use crate::fmt;
use crate::quote_in;
use crate::tokens::{quoted, ItemStr};
pub type Tokens = crate::Tokens<C>;
impl_lang! {
pub C {
type Config = Config;
type Format = Format;
type Item = Import;
fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {
super::c_family_write_quoted(out, input)
}
fn format_file(
tokens: &Tokens,
out: &mut fmt::Formatter<'_>,
config: &Self::Config,
) -> fmt::Result {
let mut header = Tokens::new();
Self::imports(&mut header, tokens);
let format = Format::default();
header.format(out, config, &format)?;
tokens.format(out, config, &format)?;
Ok(())
}
}
Import(Import) {
fn format(&self, out: &mut fmt::Formatter<'_>, _: &Config, _: &Format) -> fmt::Result {
out.write_str(&self.item)?;
Ok(())
}
}
}
#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct Import {
path: ItemStr,
item: ItemStr,
system: bool,
}
#[derive(Debug, Default)]
pub struct Format {}
#[derive(Debug, Default)]
pub struct Config {}
impl C {
fn imports(out: &mut Tokens, tokens: &Tokens) {
let mut includes = BTreeSet::new();
for include in tokens.iter_lang() {
includes.insert((&include.path, include.system));
}
if includes.is_empty() {
return;
}
for (file, system_header) in includes {
if system_header {
quote_in!(*out => #include <$(file)>);
} else {
quote_in!(*out => #include $(quoted(file)));
}
out.push();
}
out.line();
}
}
pub fn include(path: impl Into<ItemStr>, item: impl Into<ItemStr>) -> Import {
Import {
path: path.into(),
item: item.into(),
system: false,
}
}
pub fn include_system<M, N>(path: M, item: N) -> Import
where
M: Into<ItemStr>,
N: Into<ItemStr>,
{
Import {
path: path.into(),
item: item.into(),
system: true,
}
}