1use std::{
10 fs::{OpenOptions},
11 io::{Write},
12};
13use crate::read_ebml::Process;
14use crate::read_ebml::SubStep;
17
18
19pub struct Language {
33
34 name: String,
36
37 first: String,
39
40 c_open: String,
42
43 c_close:String,
45
46 last: String,
48
49 ext: String,
51
52 wait: String,
54
55 p_open: String,
57
58 p_close:String,
60}
61
62pub fn learn(lang:&str) -> Language {
128
129 match lang.split_whitespace().collect::<Vec<_>>().join("").to_uppercase().as_str() {
131 "ACTIONSCRIPT" | "AS3" => Language{
132 name: String::from("AppleScript"),
133 first: String::from("#!/usr/bin/as3shebang //\nimport shell.Program;\nimport flash.system.System;"),
134 c_open: String::from("// "),
135 c_close:String::from(""),
136 last: String::from("function onKeyPress(event:KeyboardEvent):void\n{\n if (event.keyCode == Keyboard.ENTER)\n { stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyPress);\n trace(\"Enter key pressed! Proceeding...\");\n play();\n }\n}\n\nreturn;"),
137 ext: String::from(".asc"),
138 wait: String::from("stop();\nstage.addEventListener(KeyboardEvent.KEY_UP, onKeyPress);"),
139 p_open: String::from("System.output(\""),
140 p_close:String::from("\n\");"),
141 },
142 "APPLESCRIPT" | "APPLE" => Language{
143 name: String::from("AppleScript"),
144 first: String::from("#!/usr/bin/osascript"),
145 c_open: String::from("-- "),
146 c_close:String::from(""),
147 last: String::from(""),
148 ext: String::from(".command"),
149 wait: String::from("read -p \"Press Enter to continue...\""),
150 p_open: String::from("echo '"),
151 p_close:String::from("'"),
152 },
153 "BASH" => Language{
154 name: String::from("bash"),
155 first: String::from("#!/bin/bash"),
156 c_open: String::from("# "),
157 c_close:String::from(""),
158 last: String::from("exit 0"),
159 ext: String::from(".sh"),
160 wait: String::from("read -p \"Press Enter to continue...\""),
161 p_open: String::from("echo '"),
162 p_close:String::from("'"),
163 },
164 "COFFEESCRIPT" | "COFFEE" => Language{
165 name: String::from("CoffeeScript"),
166 first: String::from("#!/usr/bin/env coffee\n\nreadline = require 'readline'\n\nwaitForEnter = ->\n new Promise (resolve) ->\n rl = readline.createInterface\n input: process.stdin\n output: process.stdout\n rl.question 'Press Enter to continue...', ->\n rl.close()\n resolve()\n\n"),
167 c_open: String::from("# "),
168 c_close:String::from(""),
169 last: String::from("process.exit(1)"),
170 ext: String::from(".coffee"),
171 wait: String::from("await waitForEnter()"),
172 p_open: String::from("console.log \""),
173 p_close:String::from("\""),
174 },
175 "DART" => Language{
176 name: String::from("Dart"),
177 first: String::from("#!/usr/bin/env dart\nimport 'dart:io';\nvoid main() {"),
178 c_open: String::from("// "),
179 c_close:String::from(""),
180 last: String::from("exit(0);\n}"),
181 ext: String::from(".dart"),
182 wait: String::from("print('Press Enter to continue...');\nstdin.readLineSync();"),
183 p_open: String::from("print('"),
184 p_close:String::from("');"),
185 },
186 "ELIXIR" | "EXS" => Language{
187 name: String::from("Elixir"),
188 first: String::from("#!/usr/bin/env elixir"),
189 c_open: String::from("# "),
190 c_close:String::from(""),
191 last: String::from("Process.exit(self, :normal)"),
192 ext: String::from(".exs"),
193 wait: String::from("IO.gets(\"Press Enter to continue...\")"),
194 p_open: String::from("IO.puts(\""),
195 p_close:String::from("\")"),
196 },
197 "JAVASCRIPT" | "JS" | "NODE.JS" => Language{
198 name: String::from("JavaScript"),
199 first: String::from("#!/usr/bin/env node"),
200 c_open: String::from("// "),
201 c_close:String::from(""),
202 last: String::from("process.exit(0)"),
203 ext: String::from(".js"),
204 wait: String::from(""),
205 p_open: String::from("console.log(\""),
206 p_close:String::from("\");"),
207 },
208 "JULIA" | "JL" => Language{
209 name: String::from("Julia"),
210 first: String::from("#!/usr/bin/env -S julia --color=yes --startup-file=no"),
211 c_open: String::from("# "),
212 c_close:String::from(""),
213 last: String::from("exit(0)"),
214 ext: String::from(".jl"),
215 wait: String::from("Base.prompt(\"Press Enter to continue...\")"),
216 p_open: String::from("println(\""),
217 p_close:String::from("\")"),
218 },
219 "LUA" => Language{
220 name: String::from("Lua"),
221 first: String::from("#!/usr/bin/env lua"),
222 c_open: String::from("-- "),
223 c_close:String::from(""),
224 last: String::from("return"),
225 ext: String::from(".lua"),
226 wait: String::from("print(\"Press Enter to continue...\")\nio.read()"),
227 p_open: String::from("println(\""),
228 p_close:String::from("\")"),
229 },
230 "MATLAB" | "MATHWORKS" | "MAT" | "M" => Language{
231 name: String::from("MATLAB"),
232 first: String::from("% no shebang statement for MATLAB"),
233 c_open: String::from("% "),
234 c_close:String::from(""),
235 last: String::from("exit(0)"),
236 ext: String::from(".m"),
237 wait: String::from("disp('Press Enter to continue...'); input('');"),
238 p_open: String::from("disp('"),
239 p_close:String::from("');"),
240 },
241 "PERL" | "PL" => Language{
242 name: String::from("Perl"),
243 first: String::from("#!/usr/bin/env perl"),
244 c_open: String::from("# "),
245 c_close:String::from(""),
246 last: String::from("exit 1;"),
247 ext: String::from(".pl"),
248 wait: String::from("print \"Press Enter to continue...\";\n<STDIN>;"),
249 p_open: String::from("print \""),
250 p_close:String::from("\";"),
251 },
252 "PHP" => Language{
253 name: String::from("PHP"),
254 first: String::from("#!/usr/bin/env php"),
255 c_open: String::from("// "),
256 c_close:String::from(""),
257 last: String::from("exit(0);"),
258 ext: String::from(".php"),
259 wait: String::from("readline(\"Press Enter to proceed...\");"),
260 p_open: String::from("echo \""),
261 p_close:String::from("\";"),
262 },
263 "POWERSHELL" | "PS" | "PS1" => Language{
264 name: String::from("PowerShell"),
265 first: String::from("#!/usr/bin/env pwsh"),
266 c_open: String::from("# "),
267 c_close:String::from(""),
268 last: String::from("exit 0"),
269 ext: String::from(".ps1"),
270 wait: String::from("Read-Host -Prompt \"Press Enter to continue...\""),
271 p_open: String::from("Write-Host \""),
272 p_close:String::from("\""),
273 },
274 "PYTHON" | "PYTHON3" | "PY" => Language{
275 name: String::from("Python 3"),
276 first: String::from("#!/usr/bin/python3"),
277 c_open: String::from("-- "),
278 c_close:String::from(""),
279 last: String::from(""),
280 ext: String::from(".py"),
281 wait: String::from("input(\"Press Enter to continue...\")"),
282 p_open: String::from("print(\""),
283 p_close:String::from("\")"),
284 },
285 "R" => Language{
286 name: String::from("R"),
287 first: String::from("#!/usr/bin/env Rscript"),
288 c_open: String::from("# "),
289 c_close:String::from(""),
290 last: String::from("quit()"),
291 ext: String::from(".R"),
292 wait: String::from("readline(prompt = \"Press Enter to continue...\")"),
293 p_open: String::from("print(\""),
294 p_close:String::from("\")"),
295 },
296 "RUBY" | "RB" => Language{
297 name: String::from("Ruby"),
298 first: String::from("#!/usr/bin/env ruby"),
299 c_open: String::from("// "),
300 c_close:String::from(""),
301 last: String::from("exit(0)"),
302 ext: String::from(".rb"),
303 wait: String::from("puts \"Press Enter to continue...\"\ngets"),
304 p_open: String::from("puts \""),
305 p_close:String::from("\""),
306 },
307 "TYPESCRIPT" | "TS" => Language{
308 name: String::from("TypeScript"),
309 first: String::from("#!/usr/bin/env tsx"),
310 c_open: String::from("# "),
311 c_close:String::from(""),
312 last: String::from("process.exit(0)"),
313 ext: String::from(".ts"),
314 wait: String::from(""),
315 p_open: String::from("console.log(\""),
316 p_close:String::from("\")"),
317 },
318 "VB.NET" | "VBNET" | "VB" => Language{
319 name: String::from("VB.NET"),
320 first: String::from("#!/usr/bin/env dotnet run"),
321 c_open: String::from("' "),
322 c_close:String::from(""),
323 last: String::from("Return"),
324 ext: String::from(".vb"),
325 wait: String::from("Console.WriteLine(\"Press Enter to continue...\")\nConsole.ReadLine()"),
326 p_open: String::from("Console.WriteLine(\""),
327 p_close:String::from("\""),
328 },
329 _ => Language{
330 name: String::from("Unknown"),
331 first: String::from("#!/bin/sh"),
332 c_open: String::from("# "),
333 c_close:String::from(""),
334 last: String::from("exit 0"),
335 ext: String::from(".sh"),
336 wait: String::from("read -p \"Press Enter to continue...\""),
337 p_open: String::from("echo '"),
338 p_close:String::from("'"),
339 },
340 }
341}
342
343pub fn script_file_from_process(p:Process,lang:Language,wait:bool) {
351
352 let mut script_lines:Vec<String> = vec![];
354
355 script_lines.push(lang.first.to_owned());
357
358 script_lines.push(comment_to_file(&("=============================================================".to_string()),&lang));
360 script_lines.push(comment_to_file(&(p.get_number().to_owned() + " Rev " + &p.get_revision() + " " + &p.get_title()),&lang));
361 script_lines.push(comment_to_file(&("Author: ".to_owned() + &p.get_author()),&lang));
362 script_lines.push(comment_to_file(&("Reviewer: ".to_owned() + &p.get_reviewer()),&lang));
363 script_lines.push(comment_to_file(&("".to_string()),&lang));
364 script_lines.push(comment_to_file(&(lang.name.to_owned()+ " generated by stanhope " + env!("CARGO_PKG_VERSION")),&lang));
365 script_lines.push(comment_to_file(&("=============================================================".to_string()),&lang));
366
367 script_lines.push("".to_string());
368
369 script_lines.push(print_to_stdout(&(p.get_number().to_owned() + " Rev " + &p.get_revision() + " " + &p.get_title()),&lang));
370 script_lines.push(print_to_stdout(&("".to_string()),&lang));
371 script_lines.push(print_to_stdout(&("Author: ".to_owned() + &p.get_author()),&lang));
372 script_lines.push(print_to_stdout(&("Reviewer: ".to_owned() + &p.get_reviewer()),&lang));
373 script_lines.push(print_to_stdout(&("".to_string()),&lang));
374
375 script_lines.push("".to_string());
376
377 if wait { script_lines.push(lang.wait.to_owned()) };
379
380 script_lines.push("".to_string());
381
382 let mut secnum:u16 = 0;
384 for section in p.get_all_sections() {
385 secnum += 1;
386 let mut stpnum:u16 = 0;
387
388 script_lines.push(comment_to_file(&("=============================================================".to_string()),&lang));
390 script_lines.push(comment_to_file(&("Section ".to_string() + &secnum.to_string() + ": " + §ion.get_title()),&lang));
391 script_lines.push(comment_to_file(&("=============================================================".to_string()),&lang));
392 script_lines.push("".to_string());
393
394 for step in section.get_all_steps() {
396 stpnum += 1;
397 script_lines.push(print_to_stdout(&("Step ".to_string() + &secnum.to_string() + "." + &stpnum.to_string()),&lang));
399 script_lines.push(print_to_stdout(&(step.get_text().trim().to_string()),&lang));
400 script_lines.push(print_to_stdout(&("".to_string()),&lang));
401
402 for substep in step.get_all_sub_steps() {
404 match substep {
405
406 SubStep::Context(txt) => { script_lines.push(comment_to_file(&(txt.trim().to_string()),&lang)); },
409
410 SubStep::Command(txt) => {
411 script_lines.push(txt.trim().to_string());
413 if wait { script_lines.push(lang.wait.to_owned()) };
417 },
418
419 SubStep::Objective(txt) => {
424 script_lines.push(print_to_stdout(&("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *".to_string()),&lang));
425 script_lines.push(print_to_stdout(&("Objective Achieved!".to_string()),&lang));
426 script_lines.push(print_to_stdout(&(&txt.trim().to_string()),&lang));
427 script_lines.push(print_to_stdout(&("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *".to_string()),&lang));
428 },
429
430 _ => {},
433 }
434 }
435 script_lines.push(print_to_stdout(&("".to_string()),&lang));
437 script_lines.push("".to_string());
438 }
439 script_lines.push("".to_string());
441 }
442
443 script_lines.push(lang.last.to_owned());
445
446 let path_to_file = "./".to_string() + p.get_number() + " - " + p.get_title() + "/" + p.get_number() + " - " + p.get_title() + &lang.ext;
450
451 let mut file = OpenOptions::new()
453 .read(true)
454 .write(true)
455 .create(true)
456 .truncate(true)
457 .open(&path_to_file)
458 .expect("Could not open the file!");
459
460 for line in script_lines {
461 file.write((line + "\n").as_bytes()).expect("Could not write template line into new file!");
462 }
463
464 println!("You will need to make the script file executable if it isn't already. For example, you might need to run:\nchmod +x \"{}\"",&path_to_file);
465
466}
467
468fn comment_to_file(txt:&String,lang:&Language) -> String { lang.c_open.to_owned() + txt + &lang.c_close }
470
471fn print_to_stdout(txt:&String,lang:&Language) -> String {
473
474 let txt_san = txt.replace('"',"").replace("'","");
475 lang.p_open.to_owned() + &txt_san + &lang.p_close
476}
477
478
479#[cfg(test)]
492mod tests {
493
494 }