rpgmv_tool/command/commands2py/generate/
function_call_writer.rs1use super::escape_string;
2use super::stringify_bool;
3use super::write_indent;
4use anyhow::bail;
5use anyhow::Context;
6use std::io::Write;
7
8#[derive(Debug)]
9pub struct FunctionCallWriter<W> {
10 writer: W,
11 indent: u16,
12
13 has_params: bool,
14 multiline: bool,
15}
16
17impl<W> FunctionCallWriter<W>
18where
19 W: Write,
20{
21 pub fn new(mut writer: W, indent: u16, name: &str) -> anyhow::Result<Self> {
22 write_indent(&mut writer, indent)?;
23 write!(writer, "{name}(")?;
24
25 Ok(Self {
26 writer,
27 indent,
28 has_params: false,
29 multiline: true,
30 })
31 }
32
33 pub fn set_multiline(&mut self, multiline: bool) {
34 self.multiline = multiline;
35 }
36
37 pub fn write_param<T>(&mut self, name: &str, param: &T) -> anyhow::Result<()>
38 where
39 T: FunctionParamValue,
40 {
41 if self.has_params {
42 write!(self.writer, ",")?;
43
44 if !self.multiline {
45 write!(self.writer, " ")?;
46 }
47 }
48 if self.multiline {
49 writeln!(self.writer)?;
50 write_indent(&mut self.writer, self.indent + 1)?;
51 }
52 write!(self.writer, "{name}=")?;
53 param.write_param_value(&mut self.writer, self.indent + 1)?;
54
55 self.has_params = true;
56
57 Ok(())
58 }
59
60 pub fn finish(&mut self) -> anyhow::Result<()> {
61 if self.has_params && self.multiline {
62 writeln!(self.writer, ",")?;
63 write_indent(&mut self.writer, self.indent)?;
64 }
65
66 writeln!(&mut self.writer, ")")?;
67
68 Ok(())
69 }
70}
71
72pub trait FunctionParamValue {
73 fn write_param_value(&self, writer: &mut dyn Write, indent: u16) -> anyhow::Result<()>;
74}
75
76impl FunctionParamValue for str {
77 fn write_param_value(&self, writer: &mut dyn Write, _indent: u16) -> anyhow::Result<()> {
78 let value = escape_string(self);
79 write!(writer, "'{value}'")?;
80 Ok(())
81 }
82}
83
84impl FunctionParamValue for String {
85 fn write_param_value(&self, writer: &mut dyn Write, indent: u16) -> anyhow::Result<()> {
86 self.as_str().write_param_value(writer, indent)
87 }
88}
89
90impl FunctionParamValue for i64 {
91 fn write_param_value(&self, writer: &mut dyn Write, _indent: u16) -> anyhow::Result<()> {
92 write!(writer, "{}", self)?;
93
94 Ok(())
95 }
96}
97
98impl FunctionParamValue for u32 {
99 fn write_param_value(&self, writer: &mut dyn Write, _indent: u16) -> anyhow::Result<()> {
100 write!(writer, "{}", self)?;
101
102 Ok(())
103 }
104}
105
106impl FunctionParamValue for i32 {
107 fn write_param_value(&self, writer: &mut dyn Write, _indent: u16) -> anyhow::Result<()> {
108 write!(writer, "{}", self)?;
109
110 Ok(())
111 }
112}
113
114impl FunctionParamValue for u8 {
115 fn write_param_value(&self, writer: &mut dyn Write, _indent: u16) -> anyhow::Result<()> {
116 write!(writer, "{}", self)?;
117
118 Ok(())
119 }
120}
121
122impl FunctionParamValue for bool {
123 fn write_param_value(&self, writer: &mut dyn Write, _indent: u16) -> anyhow::Result<()> {
124 let value = stringify_bool(*self);
125 write!(writer, "{value}")?;
126
127 Ok(())
128 }
129}
130
131impl<T> FunctionParamValue for &[T]
132where
133 T: FunctionParamValue,
134{
135 fn write_param_value(&self, mut writer: &mut dyn Write, indent: u16) -> anyhow::Result<()> {
136 writeln!(writer, "[")?;
137
138 for entry in self.iter() {
139 write_indent(&mut writer, indent + 1)?;
140 entry.write_param_value(writer, indent + 1)?;
141 writeln!(writer, ",")?;
142 }
143
144 write_indent(&mut writer, indent)?;
145 write!(writer, "]")?;
146
147 Ok(())
148 }
149}
150
151impl<T> FunctionParamValue for Vec<T>
152where
153 T: FunctionParamValue,
154{
155 fn write_param_value(&self, writer: &mut dyn Write, indent: u16) -> anyhow::Result<()> {
156 self.as_slice().write_param_value(writer, indent)
157 }
158}
159
160impl FunctionParamValue for rpgmv_types::MoveRoute {
161 fn write_param_value(&self, mut writer: &mut dyn Write, indent: u16) -> anyhow::Result<()> {
162 let repeat = stringify_bool(self.repeat);
163 let skippable = stringify_bool(self.skippable);
164 let wait = stringify_bool(self.wait);
165
166 writeln!(writer, "MoveRoute(")?;
167
168 write_indent(&mut writer, indent + 1)?;
169 writeln!(writer, "repeat={repeat},")?;
170
171 write_indent(&mut writer, indent + 1)?;
172 writeln!(writer, "skippable={skippable},")?;
173
174 write_indent(&mut writer, indent + 1)?;
175 writeln!(&mut writer, "wait={wait},")?;
176
177 write_indent(&mut writer, indent + 1)?;
178 writeln!(writer, "list=[")?;
179
180 for command in self.list.iter() {
181 let command_indent = command
182 .indent
183 .map(|indent| indent.to_string())
184 .unwrap_or_else(|| "None".to_string());
185
186 write_indent(&mut writer, indent + 2)?;
187 writeln!(writer, "MoveCommand(")?;
188
189 write_indent(&mut writer, indent + 3)?;
190 writeln!(writer, "code={},", command.code)?;
191
192 write_indent(&mut writer, indent + 3)?;
193 writeln!(writer, "indent={command_indent},")?;
194
195 match command.parameters.as_ref() {
196 Some(parameters) => {
197 write_indent(&mut writer, indent + 3)?;
198 writeln!(writer, "parameters=[")?;
199
200 for parameter in parameters {
201 match parameter {
202 serde_json::Value::Number(number) if number.is_i64() => {
203 let value = number.as_i64().context("value is not an i64")?;
204
205 write_indent(&mut writer, indent + 4)?;
206 writeln!(writer, "{value},")?;
207 }
208 serde_json::Value::String(value) => {
209 let value = escape_string(value);
210 write_indent(&mut writer, indent + 4)?;
211 writeln!(writer, "'{value}',")?;
212 }
213 serde_json::Value::Object(object) => {
214 write_indent(&mut writer, indent + 4)?;
215 writeln!(writer, "{{")?;
216
217 for (key, value) in object.iter() {
218 write_indent(&mut writer, indent + 5)?;
219 writeln!(writer, "'{key}': {value},")?;
220 }
221
222 write_indent(&mut writer, indent + 4)?;
223 writeln!(writer, "}},")?;
224 }
225 _ => {
226 bail!("cannot write move route parameter \"{parameter:?}\"")
227 }
228 }
229 }
230
231 write_indent(&mut writer, indent + 3)?;
232 writeln!(writer, "],")?;
233 }
234 None => {
235 write_indent(&mut writer, indent + 3)?;
236 writeln!(writer, "parameters=None,")?;
237 }
238 }
239
240 write_indent(&mut writer, indent + 2)?;
241 writeln!(writer, "),")?;
242 }
243
244 write_indent(&mut writer, indent + 1)?;
245 writeln!(writer, "]")?;
246
247 write_indent(&mut writer, indent)?;
248 write!(writer, ")")?;
249
250 Ok(())
251 }
252}
253
254impl FunctionParamValue for rpgmv_types::AudioFile {
255 fn write_param_value(&self, mut writer: &mut dyn Write, indent: u16) -> anyhow::Result<()> {
256 let audio_name = escape_string(&self.name);
257
258 writeln!(writer, "AudioFile(")?;
259
260 write_indent(&mut writer, indent + 1)?;
261 writeln!(writer, "name='{audio_name}',")?;
262
263 write_indent(&mut writer, indent + 1)?;
264 writeln!(writer, "pan={},", self.pan)?;
265
266 write_indent(&mut writer, indent + 1)?;
267 writeln!(writer, "pitch={},", self.pitch)?;
268
269 write_indent(&mut writer, indent + 1)?;
270 writeln!(writer, "volume={},", self.volume)?;
271
272 write_indent(&mut writer, indent)?;
273 write!(writer, ")")?;
274
275 Ok(())
276 }
277}
278
279pub struct Ident<'a>(pub &'a str);
280
281impl FunctionParamValue for Ident<'_> {
282 fn write_param_value(&self, writer: &mut dyn Write, _indent: u16) -> anyhow::Result<()> {
283 write!(writer, "{}", self.0)?;
284 Ok(())
285 }
286}