1pub mod c;
19pub mod csharp;
20pub mod dart;
21pub mod go;
22pub mod java;
23
24pub mod js;
25pub mod kotlin;
26pub mod nix;
27pub mod python;
28pub mod rust;
29pub mod swift;
30
31pub use self::c::C;
32pub use self::csharp::Csharp;
33pub use self::dart::Dart;
34pub use self::go::Go;
35pub use self::java::Java;
36pub use self::js::JavaScript;
37pub use self::kotlin::Kotlin;
38pub use self::nix::Nix;
39pub use self::python::Python;
40pub use self::rust::Rust;
41pub use self::swift::Swift;
42
43use core::fmt::Write as _;
44
45use crate::fmt;
46use crate::Tokens;
47
48pub trait Lang: Sized {
53 type Config;
55 type Format: Default;
57 type Item: LangItem<Self>;
59
60 fn default_indentation() -> fmt::Indentation {
62 fmt::Indentation::Space(4)
63 }
64
65 fn open_quote(
67 out: &mut fmt::Formatter<'_>,
68 _config: &Self::Config,
69 _format: &Self::Format,
70 _has_eval: bool,
71 ) -> fmt::Result {
72 out.write_char('"')?;
73 Ok(())
74 }
75
76 fn close_quote(
78 out: &mut fmt::Formatter<'_>,
79 _config: &Self::Config,
80 _format: &Self::Format,
81 _has_eval: bool,
82 ) -> fmt::Result {
83 out.write_char('"')?;
84 Ok(())
85 }
86
87 fn string_eval_literal(
89 out: &mut fmt::Formatter<'_>,
90 config: &Self::Config,
91 format: &Self::Format,
92 literal: &str,
93 ) -> fmt::Result {
94 Self::start_string_eval(out, config, format)?;
95 out.write_str(literal)?;
96 Self::end_string_eval(out, config, format)?;
97 Ok(())
98 }
99
100 fn start_string_eval(
102 _out: &mut fmt::Formatter<'_>,
103 _config: &Self::Config,
104 _format: &Self::Format,
105 ) -> fmt::Result {
106 Ok(())
107 }
108
109 fn end_string_eval(
111 _out: &mut fmt::Formatter<'_>,
112 _config: &Self::Config,
113 _format: &Self::Format,
114 ) -> fmt::Result {
115 Ok(())
116 }
117
118 fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {
120 out.write_str(input)
121 }
122
123 fn format_file(
125 tokens: &Tokens<Self>,
126 out: &mut fmt::Formatter<'_>,
127 config: &Self::Config,
128 ) -> fmt::Result {
129 let format = Self::Format::default();
130 tokens.format(out, config, &format)
131 }
132}
133
134pub trait LangSupportsEval: Lang {}
139
140impl Lang for () {
142 type Config = ();
143 type Format = ();
144 type Item = ();
145}
146
147impl<L> LangItem<L> for ()
148where
149 L: Lang,
150{
151 fn format(&self, _: &mut fmt::Formatter<'_>, _: &L::Config, _: &L::Format) -> fmt::Result {
152 Ok(())
153 }
154}
155
156pub trait LangItem<L>
161where
162 L: Lang,
163{
164 fn format(
166 &self,
167 fmt: &mut fmt::Formatter<'_>,
168 config: &L::Config,
169 format: &L::Format,
170 ) -> fmt::Result;
171}
172
173pub fn c_family_write_quoted(out: &mut fmt::Formatter, input: &str) -> fmt::Result {
180 for c in input.chars() {
181 match c {
182 '\u{0007}' => out.write_str("\\a")?,
184 '\u{0008}' => out.write_str("\\b")?,
186 '\u{0012}' => out.write_str("\\f")?,
188 '\n' => out.write_str("\\n")?,
190 '\r' => out.write_str("\\r")?,
192 '\t' => out.write_str("\\t")?,
194 '\u{0011}' => out.write_str("\\v")?,
196 '\'' => out.write_str("\\'")?,
197 '"' => out.write_str("\\\"")?,
198 '\\' => out.write_str("\\\\")?,
199 ' ' => out.write_char(' ')?,
200 c if c.is_ascii() => {
201 if !c.is_control() {
202 out.write_char(c)?
203 } else {
204 write!(out, "\\x{:02x}", c as u32)?;
205 }
206 }
207 c if (c as u32) < 0x10000 => {
208 write!(out, "\\u{:04x}", c as u32)?;
209 }
210 c => {
211 write!(out, "\\U{:08x}", c as u32)?;
212 }
213 };
214 }
215
216 Ok(())
217}