rpgmv_tool/command/commands2py/generate/
function_call_writer.rs

1use 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}