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};
const MODULE_SEP: &str = "/";
const SEP: &str = ".";
pub type Tokens = crate::Tokens<Go>;
impl_lang! {
pub Go {
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();
if let Some(package) = &config.package {
quote_in!(header => package $package);
header.line();
}
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 {
if let Some(module) = self.module.rsplit(MODULE_SEP).next() {
out.write_str(module)?;
out.write_str(SEP)?;
}
out.write_str(&self.name)?;
Ok(())
}
}
}
#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct Import {
module: ItemStr,
name: ItemStr,
}
#[derive(Debug, Default)]
pub struct Format {}
#[derive(Debug, Default)]
pub struct Config {
package: Option<ItemStr>,
}
impl Config {
pub fn with_package<P: Into<ItemStr>>(self, package: P) -> Self {
Self {
package: Some(package.into()),
}
}
}
impl Go {
fn imports(out: &mut Tokens, tokens: &Tokens) {
let mut modules = BTreeSet::new();
for import in tokens.iter_lang() {
modules.insert(&import.module);
}
if modules.is_empty() {
return;
}
for module in modules {
quote_in!(*out => import $(quoted(module)));
out.push();
}
out.line();
}
}
pub fn import<M, N>(module: M, name: N) -> Import
where
M: Into<ItemStr>,
N: Into<ItemStr>,
{
Import {
module: module.into(),
name: name.into(),
}
}