1use crate::action::{Action, Actions};
2use crate::config::Config;
3use crate::context::{Context, Format};
4use crate::error::{EngineError, MyError, MyResult};
5use crate::helper::CommandEditor;
6use crate::interface::{Directive, Interface, Operation};
7use crate::undo::Undo;
8use crate::util;
9use crate::value::Value;
10use fileinput::FileInput;
11use itertools::Itertools;
12use std::cell::RefCell;
13use std::fs::File;
14use std::io::{BufRead, BufReader, Write};
15use std::rc::Rc;
16
17pub struct Engine<W: Write> {
18 config: Config,
19 editor: CommandEditor,
20 interface: Rc<RefCell<Interface<W>>>,
21 context: Rc<RefCell<Context>>,
22 stack: Vec<Value>,
23 undos: Vec<Undo>,
24 redos: Vec<Undo>,
25 clip: Option<Value>,
26 dirty: bool,
27 interact: bool,
28}
29
30impl<W: Write> Engine<W> {
32 pub fn new(config: Config) -> MyResult<Self> {
33 let interface = Rc::new(RefCell::new(Interface::build()));
34 let editor = interface.borrow().create_editor()?;
35 let context = Rc::new(RefCell::new(Context::new()));
36 let stack = Vec::new();
37 let undos = Vec::new();
38 let redos = Vec::new();
39 let engine = Self {
40 config,
41 editor,
42 interface,
43 context,
44 stack,
45 undos,
46 redos,
47 clip: None,
48 dirty: false,
49 interact: false,
50 };
51 Ok(engine)
52 }
53
54 pub fn parse_input(&mut self, writer: &mut W) -> MyResult<()> {
55 if let Some(import) = &self.config.import {
56 let import = vec![String::from(import)];
57 self.import_file(writer, import)?;
58 }
59 if !self.config.values.is_empty() {
60 self.parse_values(writer)?;
61 if !self.config.mock {
62 self.show_simple(writer)?;
63 }
64 } else if !self.config.paths.is_empty() || atty::isnt(atty::Stream::Stdin) || atty::isnt(atty::Stream::Stdout) {
65 let reader = FileInput::new(&self.config.paths);
66 self.parse_files(writer, reader)?;
67 self.show_simple(writer)?;
68 } else {
69 self.parse_loop(writer)?;
70 }
71 Ok(())
72 }
73
74 fn parse_values(&mut self, writer: &mut W) -> MyResult<()> {
75 let values = self.config.values.drain(..).collect::<Vec<String>>();
76 if self.config.mock {
77 for (index, value) in values.iter().enumerate() {
78 self.interact = index + 1 == values.len();
79 self.interact_line(writer, &value)?;
80 }
81 } else {
82 for value in values {
83 self.parse_line(writer, &value)?;
84 }
85 }
86 Ok(())
87 }
88
89 fn parse_files(&mut self, writer: &mut W, reader: FileInput) -> MyResult<()> {
90 let reader = BufReader::new(reader);
91 for line in reader.lines() {
92 let line = line?;
93 self.parse_line(writer, &line)?;
94 }
95 Ok(())
96 }
97
98 fn parse_loop(&mut self, writer: &mut W) -> MyResult<()> {
99 self.interact = true;
100 loop {
101 let line = self.editor.readline("rpn> ")?;
102 self.editor.add_history_entry(&line)?;
103 self.interact_line(writer, &line)?;
104 }
105 }
106
107 fn interact_line(&mut self, writer: &mut W, line: &str) -> MyResult<()> {
108 let result = match self.parse_line(writer, line) {
109 Ok(()) => {
110 if self.interact && self.dirty {
111 self.show_stack(writer)?;
112 }
113 Ok(())
114 }
115 Err(MyError::Engine(error)) => {
116 if self.interact {
117 writeln!(writer, " {}", error)?;
118 }
119 Ok(())
120 }
121 Err(error) => {
122 Err(error)
123 }
124 };
125 self.dirty = false;
126 result
127 }
128
129 fn parse_line(&mut self, writer: &mut W, line: &str) -> MyResult<()> {
130 let mut empty = true;
131 let mut undo = Undo::default();
132 let mut redo = Undo::default();
133 let (line, comment) = Self::split_comment(line);
134 let actions = Actions::new(&self.interface, line.split_ascii_whitespace());
135 for action in actions {
136 let action = match action {
137 Ok((action, token)) => self.apply_action(
138 writer,
139 &mut undo,
140 &mut redo,
141 action,
142 Some(token),
143 ),
144 Err(error) => Err(error),
145 };
146 if let Err(error) = action {
147 undo.apply_to(&mut self.stack);
148 return Err(error);
149 }
150 empty = false;
151 }
152 if let Some(comment) = comment {
153 if let Err(error) = self.apply_comment(&mut undo, comment) {
154 undo.apply_to(&mut self.stack);
155 return Err(error);
156 }
157 empty = false;
158 }
159 self.commit_undo(undo, redo);
160 self.dirty |= empty;
161 Ok(())
162 }
163
164 fn split_comment(line: &str) -> (&str, Option<&str>) {
165 if let Some(stop) = line.find('#') {
166 let start = stop + 1;
167 let values = line[..stop].trim();
168 let comment = line[start..].trim();
169 let comment = if comment.is_empty() { None } else { Some(comment) };
170 (values, comment)
171 } else {
172 let values = line.trim();
173 (values, None)
174 }
175 }
176
177 fn apply_action(
178 &mut self,
179 writer: &mut W,
180 undo: &mut Undo,
181 redo: &mut Undo,
182 action: Action<W>,
183 token: Option<&str>,
184 ) -> MyResult<()> {
185 match action {
186 Action::Operation(operation) => {
187 match operation.as_ref() {
188 Operation::ValueNone(function) => {
189 let result = function()?;
190 self.push_single(undo, result, token);
191 self.dirty = true;
192 }
193 Operation::ValueOne(function) => {
194 let value = self.pop_single(undo, None)?;
195 let result = function(value)?;
196 self.push_single(undo, result, token);
197 self.dirty = true;
198 }
199 Operation::ValueTwo(function) => {
200 let (value1, value2) = self.pop_double(undo, None)?;
201 let result = function(value1, value2)?;
202 self.push_single(undo, result, token);
203 self.dirty = true;
204 }
205 Operation::ValueAll(function) => {
206 let values = self.stack.drain(..).collect::<Vec<Value>>();
207 let result = function(values.clone())?;
208 self.stack.push(result);
209 self.dirty = true;
210 undo.merge(1, values, token);
211 }
212 Operation::ValueTime(function) => {
213 let result = function(&self.config.now)?;
214 self.push_single(undo, result, token);
215 self.dirty = true;
216 }
217 Operation::ContextNone(function) => {
218 function(&mut self.context.borrow_mut());
219 self.dirty = true;
220 }
221 Operation::ContextOne(function) => {
222 let value = self.pop_single(undo, token)?;
223 function(&mut self.context.borrow_mut(), value);
224 self.dirty = true;
225 }
226 Operation::EngineNone(function, _, _) => {
227 self.dirty |= function(self, writer)?;
228 }
229 Operation::EngineUndo(function, _, _) => {
230 self.dirty |= function(self, undo, redo, token)?;
231 }
232 }
233 }
234 Action::Directive(directive, tokens) => {
235 match directive.as_ref() {
236 Directive::EngineAll(function, _, _) => {
237 self.dirty |= function(self, writer, tokens)?;
238 }
239 }
240 }
241 Action::Definition(actions) => {
242 for action in actions {
243 self.apply_action(writer, undo, redo, action, None)?;
244 }
245 undo.merge(0, vec![], token);
246 }
247 Action::Value(value) => {
248 self.push_single(undo, value, token);
249 }
250 }
251 Ok(())
252 }
253
254 fn apply_comment(&mut self, undo: &mut Undo, comment: &str) -> MyResult<()> {
255 let value = self.pop_single(undo, Some("#"))?;
256 let value = value.with_comment(comment);
257 self.push_single(undo, value, Some(comment));
258 self.dirty = true;
259 Ok(())
260 }
261
262 fn commit_undo(&mut self, undo: Undo, redo: Undo) {
263 if !undo.is_empty() {
264 self.undos.push(undo);
265 self.redos.clear();
266 } else if !redo.is_empty() {
267 self.redos.push(redo);
268 }
269 }
270
271 fn pop_single(&mut self, undo: &mut Undo, token: Option<&str>) -> MyResult<Value> {
272 if let Some(value) = self.stack.pop() {
273 undo.merge(0, vec![value.clone()], token);
274 Ok(value)
275 } else {
276 Err(MyError::from(EngineError::MissingValue))
277 }
278 }
279
280 fn pop_double(&mut self, undo: &mut Undo, token: Option<&str>) -> MyResult<(Value, Value)> {
281 if self.stack.len() >= 2 {
282 let value2 = self.stack.pop().unwrap_or_default();
283 let value1 = self.stack.pop().unwrap_or_default();
284 undo.merge(0, vec![value1.clone(), value2.clone()], token);
285 Ok((value1, value2))
286 } else {
287 Err(MyError::from(EngineError::MissingValue))
288 }
289 }
290
291 fn push_single(&mut self, undo: &mut Undo, value: Value, token: Option<&str>) {
292 self.stack.push(value);
293 undo.merge(1, vec![], token);
294 }
295
296 pub fn clear_values(
297 &mut self,
298 undo: &mut Undo,
299 redo: &mut Undo,
300 token: Option<&str>,
301 ) -> MyResult<bool> {
302 let values = self.stack.drain(..).collect();
303 undo.merge(0, values, token);
304 redo.clear();
305 Ok(true)
306 }
307
308 pub fn pop_value(
309 &mut self,
310 undo: &mut Undo,
311 redo: &mut Undo,
312 token: Option<&str>,
313 ) -> MyResult<bool> {
314 self.pop_single(undo, token)?;
315 redo.clear();
316 Ok(true)
317 }
318
319 pub fn dup_value(
320 &mut self,
321 undo: &mut Undo,
322 redo: &mut Undo,
323 token: Option<&str>,
324 ) -> MyResult<bool> {
325 if let Some(value) = self.stack.last() {
326 self.push_single(undo, value.clone(), token);
327 redo.clear();
328 Ok(true)
329 } else {
330 Err(MyError::from(EngineError::MissingValue))
331 }
332 }
333
334 pub fn swap_values(
335 &mut self,
336 undo: &mut Undo,
337 redo: &mut Undo,
338 token: Option<&str>,
339 ) -> MyResult<bool> {
340 let (value1, value2) = self.pop_double(undo, None)?;
341 self.push_single(undo, value2, None);
342 self.push_single(undo, value1, token);
343 redo.clear();
344 Ok(true)
345 }
346
347 pub fn cut_value(
348 &mut self,
349 undo: &mut Undo,
350 redo: &mut Undo,
351 token: Option<&str>,
352 ) -> MyResult<bool> {
353 let value = self.pop_single(undo, token)?;
354 self.clip = Some(value);
355 redo.clear();
356 Ok(true)
357 }
358
359 pub fn copy_value(
360 &mut self,
361 _undo: &mut Undo,
362 _redo: &mut Undo,
363 _token: Option<&str>,
364 ) -> MyResult<bool> {
365 if let Some(value) = self.stack.last() {
366 self.clip = Some(value.clone());
367 Ok(false)
368 } else {
369 Err(MyError::from(EngineError::MissingValue))
370 }
371 }
372
373 pub fn paste_value(
374 &mut self,
375 undo: &mut Undo,
376 redo: &mut Undo,
377 token: Option<&str>,
378 ) -> MyResult<bool> {
379 if let Some(clip) = &self.clip {
380 self.push_single(undo, clip.clone(), token);
381 redo.clear();
382 Ok(true)
383 } else {
384 Err(MyError::from(EngineError::MissingClip))
385 }
386 }
387
388 pub fn import_file(
389 &mut self,
390 writer: &mut W,
391 tokens: Vec<String>,
392 ) -> MyResult<bool> {
393 let reader = FileInput::new(&tokens);
394 self.parse_files(writer, reader)?;
395 Ok(true)
396 }
397
398 pub fn export_file(
399 &mut self,
400 _writer: &mut W,
401 tokens: Vec<String>,
402 ) -> MyResult<bool> {
403 if let Some(path) = tokens.first() {
404 let mut writer = File::create(path)?;
405 let sep = self.context.borrow_mut().swap_sep(false);
406 let result = self.write_simple(&mut writer);
407 self.context.borrow_mut().swap_sep(sep);
408 result?;
409 }
410 Ok(false)
411 }
412
413 pub fn define_function(
414 &mut self,
415 _writer: &mut W,
416 tokens: Vec<String>,
417 ) -> MyResult<bool> {
418 let mut tokens = tokens.iter();
419 if let Some(keyword) = tokens.next() {
420 let description = tokens.clone().join(" ");
421 let tokens = tokens.map(String::as_ref);
422 let actions = Actions::new(&self.interface, tokens);
423 let actions = actions
424 .map(|result| result.map(|(x, _)| x))
425 .collect::<MyResult<Vec<Action<W>>>>()?;
426 self.interface.borrow_mut().add_definition(keyword, actions, description);
427 self.interface.borrow().adjust_editor(&mut self.editor);
428 }
429 Ok(false)
430 }
431
432 pub fn undo_stack(
433 &mut self,
434 undo: &mut Undo,
435 redo: &mut Undo,
436 _token: Option<&str>,
437 ) -> MyResult<bool> {
438 if !undo.is_empty() {
439 self.redos.push(undo.apply_to(&mut self.stack));
440 redo.clear();
441 Ok(true)
442 } else if let Some(mut undo) = self.undos.pop() {
443 self.redos.push(undo.apply_to(&mut self.stack));
444 redo.clear();
445 Ok(true)
446 } else {
447 Err(MyError::from(EngineError::MissingUndo))
448 }
449 }
450
451 pub fn redo_stack(
452 &mut self,
453 undo: &mut Undo,
454 redo: &mut Undo,
455 _token: Option<&str>,
456 ) -> MyResult<bool> {
457 if undo.is_empty() {
458 if !redo.is_empty() {
459 self.undos.push(redo.apply_to(&mut self.stack));
460 return Ok(true);
461 } else if let Some(mut redo) = self.redos.pop() {
462 self.undos.push(redo.apply_to(&mut self.stack));
463 return Ok(true);
464 }
465 }
466 Err(MyError::from(EngineError::MissingRedo))
467 }
468
469 pub fn show_history(&mut self, writer: &mut W) -> MyResult<bool> {
470 if self.interact {
471 self.limit_history(writer, 10)?;
472 }
473 Ok(false)
474 }
475
476 fn limit_history(&mut self, writer: &mut W, limit: usize) -> MyResult<()> {
477 for undo in self.undos.iter().rev().take(limit).rev() {
478 writeln!(writer, " {}", undo)?;
479 }
480 writeln!(writer, " <==")?;
481 for redo in self.redos.iter().rev().take(limit) {
482 writeln!(writer, " {}", redo)?;
483 }
484 Ok(())
485 }
486
487 fn show_simple(&mut self, writer: &mut W) -> Result<(), MyError> {
488 if self.config.sum {
489 let values = self.stack.drain(..).collect::<Vec<Value>>();
490 let result = Value::calc_sum(values)?;
491 self.stack.push(result);
492 }
493 if self.config.hex {
494 self.context.borrow_mut().set_hex();
495 }
496 if self.config.sep {
497 self.context.borrow_mut().set_sep();
498 }
499 if let Some(dp) = self.config.dp {
500 self.context.borrow_mut().set_dp_u8(dp);
501 }
502 self.write_simple(writer)?;
503 Ok(())
504 }
505
506 fn write_simple<V: Write>(&mut self, writer: &mut V) -> MyResult<()> {
507 self.measure_hexadecimal();
508 let context = self.context.borrow();
509 for value in &self.stack {
510 let (integer, fraction, _) = value.to_strings(&context);
511 writeln!(writer, "{}{}", integer, fraction)?;
512 }
513 Ok(())
514 }
515
516 pub fn show_stack(&mut self, writer: &mut W) -> MyResult<bool> {
517 if self.interact {
518 self.measure_hexadecimal();
519 let context = self.context.borrow();
520 let table = self.stack.iter()
521 .map(|value| value.to_strings(&context))
522 .collect::<Vec<(String, String, Option<String>)>>();
523 let integer_width = table.iter()
524 .map(|(x, _, _)| x.len())
525 .max()
526 .unwrap_or_default();
527 let fraction_width = table.iter()
528 .map(|(_, x, _)| x.len())
529 .max()
530 .unwrap_or_default();
531 for (integer, fraction, comment) in table {
532 let padding = util::create_padding(' ', integer_width + 2, integer.len(), 0);
533 write!(writer, "{}{}{}", padding, integer, fraction)?;
534 if let Some(comment) = comment {
535 let padding = util::create_padding(' ', fraction_width + 1, fraction.len(), 0);
536 write!(writer, "{}# {}", padding, comment)?;
537 }
538 writeln!(writer)?;
539 }
540 }
541 Ok(false)
542 }
543
544 fn measure_hexadecimal(&mut self) {
545 let mut context = self.context.borrow_mut();
546 if let Format::Base16(_) = context.format {
547 let chunks = self.stack.iter()
548 .map(|x| x.measure_hexadecimal())
549 .max()
550 .unwrap_or_default();
551 context.format = Format::Base16(chunks);
552 }
553 }
554
555 pub fn show_help(&mut self, writer: &mut W) -> MyResult<bool> {
556 self.interface.borrow().show_help(writer, self.interact)?;
557 Ok(false)
558 }
559}
560
561#[cfg(test)]
563pub mod tests {
564 use crate::config::Config;
565 use crate::context::Format;
566 use crate::engine::Engine;
567 use crate::error::MyResult;
568 use crate::undo::tests::create_undo;
569 use crate::util::tests::BufferWriter;
570 use crate::value::Value;
571 use pretty_assertions::assert_eq;
572 use std::io::Write;
573
574 #[test]
575 fn test_split_comment_finds_first_hash() {
576 assert_eq!(Engine::<BufferWriter>::split_comment("\tone two three\t"), ("one two three", None));
577 assert_eq!(Engine::<BufferWriter>::split_comment("\tone two three #\t"), ("one two three", None));
578 assert_eq!(Engine::<BufferWriter>::split_comment("\tone # two # three\t"), ("one", Some("two # three")));
579 }
580
581 #[test]
584 fn test_create_values_modifies_stack() {
585 let expected_stack = create_values(vec!["1", "2", "3", "4", "5", "6"]);
586 let expected_undos = vec![
587 create_undo(3, vec![], vec!["1", "2", "3"]),
588 create_undo(3, vec![], vec!["4", "5", "6"]),
589 ];
590 let expected_redos = vec![];
591 let mut engine = create_engine();
592 let mut writer = BufferWriter::new();
593 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
594 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
595 assert_eq!(engine.stack, expected_stack);
596 assert_eq!(engine.undos, expected_undos);
597 assert_eq!(engine.redos, expected_redos);
598 assert_eq!(writer.buffer, "");
599 }
600
601 #[test]
602 fn test_comment_modifies_current_line() {
603 let expected_stack = vec![
604 create_value("1"),
605 create_value("2"),
606 create_value("3"),
607 create_value("42").with_comment("the answer"),
608 ];
609 let expected_undos = vec![
610 create_undo(2, vec![], vec!["1", "2"]),
611 create_undo(2, vec![], vec!["3", "42", "#", "the answer"]),
612 ];
613 let expected_redos = vec![];
614 let mut engine = create_engine();
615 let mut writer = BufferWriter::new();
616 assert!(parse_line(&mut engine, &mut writer, "1 2").is_ok());
617 assert!(parse_line(&mut engine, &mut writer, "3 42 # the answer").is_ok());
618 assert_eq!(engine.stack, expected_stack);
619 assert_eq!(engine.undos, expected_undos);
620 assert_eq!(engine.redos, expected_redos);
621 assert_eq!(writer.buffer, "");
622 }
623
624 #[test]
625 fn test_comment_modifies_previous_line() {
626 let expected_stack = vec![
627 create_value("1"),
628 create_value("2"),
629 create_value("3"),
630 create_value("42").with_comment("the answer"),
631 ];
632 let expected_undos = vec![
633 create_undo(4, vec![], vec!["1", "2", "3", "42"]),
634 create_undo(1, vec!["42"], vec!["#", "the answer"]),
635 ];
636 let expected_redos = vec![];
637 let mut engine = create_engine();
638 let mut writer = BufferWriter::new();
639 assert!(parse_line(&mut engine, &mut writer, "1 2 3 42").is_ok());
640 assert!(parse_line(&mut engine, &mut writer, "# the answer").is_ok());
641 assert_eq!(engine.stack, expected_stack);
642 assert_eq!(engine.undos, expected_undos);
643 assert_eq!(engine.redos, expected_redos);
644 assert_eq!(writer.buffer, "");
645 }
646
647 #[test]
648 fn test_comment_fails_cleanly() {
649 let expected_stack = vec![];
650 let expected_undos = vec![];
651 let expected_redos = vec![];
652 let mut engine = create_engine();
653 let mut writer = BufferWriter::new();
654 assert!(parse_line(&mut engine, &mut writer, "# the answer").is_err());
655 assert_eq!(engine.stack, expected_stack);
656 assert_eq!(engine.undos, expected_undos);
657 assert_eq!(engine.redos, expected_redos);
658 assert_eq!(writer.buffer, "Not enough values on stack\n");
659 }
660
661 #[test]
664 fn test_unknown_operation_fails_cleanly() {
665 let expected_stack = create_values(vec!["1", "2", "3"]);
666 let expected_undos = vec![
667 create_undo(3, vec![], vec!["1", "2", "3"]),
668 ];
669 let expected_redos = vec![];
670 let mut engine = create_engine();
671 let mut writer = BufferWriter::new();
672 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
673 assert!(parse_line(&mut engine, &mut writer, "4 5 xyz 999").is_err());
674 assert_eq!(engine.stack, expected_stack);
675 assert_eq!(engine.undos, expected_undos);
676 assert_eq!(engine.redos, expected_redos);
677 assert_eq!(writer.buffer, "Invalid number or keyword: xyz\n");
678 }
679
680 #[test]
683 fn test_nullary_operation_modifies_stack() {
684 let expected_undos = vec![
685 create_undo(1, vec![], vec!["now"]),
686 ];
687 let expected_redos = vec![];
688 let mut engine = create_engine();
689 let mut writer = BufferWriter::new();
690 assert!(parse_line(&mut engine, &mut writer, "now").is_ok());
691 assert_eq!(engine.stack.len(), 1);
692 assert_eq!(engine.undos, expected_undos);
693 assert_eq!(engine.redos, expected_redos);
694 assert_eq!(writer.buffer, "");
695 }
696
697 #[test]
700 fn test_unary_operation_modifies_stack() {
701 let expected_stack = create_values(vec!["1", "-2"]);
702 let expected_undos = vec![
703 create_undo(3, vec![], vec!["1", "2", "3"]),
704 create_undo(1, vec!["2", "3"], vec!["pop", "neg"]),
705 ];
706 let expected_redos = vec![];
707 let mut engine = create_engine();
708 let mut writer = BufferWriter::new();
709 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
710 assert!(parse_line(&mut engine, &mut writer, "pop neg").is_ok());
711 assert_eq!(engine.stack, expected_stack);
712 assert_eq!(engine.undos, expected_undos);
713 assert_eq!(engine.redos, expected_redos);
714 assert_eq!(writer.buffer, "");
715 }
716
717 #[test]
718 fn test_unary_operation_fails_cleanly() {
719 let expected_stack = create_values(vec!["1", "2", "3"]);
720 let expected_undos = vec![
721 create_undo(3, vec![], vec!["1", "2", "3"]),
722 ];
723 let expected_redos = vec![];
724 let mut engine = create_engine();
725 let mut writer = BufferWriter::new();
726 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
727 assert!(parse_line(&mut engine, &mut writer, "pop pop pop neg 999").is_err());
728 assert_eq!(engine.stack, expected_stack);
729 assert_eq!(engine.undos, expected_undos);
730 assert_eq!(engine.redos, expected_redos);
731 assert_eq!(writer.buffer, "Not enough values on stack\n");
732 }
733
734 #[test]
737 fn test_binary_operation_modifies_stack() {
738 let expected_stack = create_values(vec!["1", "5"]);
739 let expected_undos = vec![
740 create_undo(3, vec![], vec!["1", "2", "3"]),
741 create_undo(1, vec!["2", "3"], vec!["add"]),
742 ];
743 let expected_redos = vec![];
744 let mut engine = create_engine();
745 let mut writer = BufferWriter::new();
746 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
747 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
748 assert_eq!(engine.stack, expected_stack);
749 assert_eq!(engine.undos, expected_undos);
750 assert_eq!(engine.redos, expected_redos);
751 assert_eq!(writer.buffer, "");
752 }
753
754 #[test]
755 fn test_binary_operation_fails_cleanly() {
756 let expected_stack = create_values(vec!["1", "2", "3"]);
757 let expected_undos = vec![
758 create_undo(3, vec![], vec!["1", "2", "3"]),
759 ];
760 let expected_redos = vec![];
761 let mut engine = create_engine();
762 let mut writer = BufferWriter::new();
763 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
764 assert!(parse_line(&mut engine, &mut writer, "pop pop add 999").is_err());
765 assert_eq!(engine.stack, expected_stack);
766 assert_eq!(engine.undos, expected_undos);
767 assert_eq!(engine.redos, expected_redos);
768 assert_eq!(writer.buffer, "Not enough values on stack\n");
769 }
770
771 #[test]
774 fn test_series_operation_modifies_stack() {
775 let expected_stack = create_values(vec!["6"]);
776 let expected_undos = vec![
777 create_undo(3, vec![], vec!["1", "2", "3"]),
778 create_undo(1, vec!["1", "2", "3"], vec!["sum"]),
779 ];
780 let expected_redos = vec![];
781 let mut engine = create_engine();
782 let mut writer = BufferWriter::new();
783 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
784 assert!(parse_line(&mut engine, &mut writer, "sum").is_ok());
785 assert_eq!(engine.stack, expected_stack);
786 assert_eq!(engine.undos, expected_undos);
787 assert_eq!(engine.redos, expected_redos);
788 assert_eq!(writer.buffer, "");
789 }
790
791 #[test]
794 fn test_clear_operation_modifies_stack() {
795 let expected_stack = vec![];
796 let expected_undos = vec![
797 create_undo(3, vec![], vec!["1", "2", "3"]),
798 create_undo(0, vec!["1", "2", "3"], vec!["clear"]),
799 ];
800 let expected_redos = vec![];
801 let mut engine = create_engine();
802 let mut writer = BufferWriter::new();
803 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
804 assert!(parse_line(&mut engine, &mut writer, "clear").is_ok());
805 assert_eq!(engine.stack, expected_stack);
806 assert_eq!(engine.undos, expected_undos);
807 assert_eq!(engine.redos, expected_redos);
808 assert_eq!(writer.buffer, "");
809 }
810
811 #[test]
814 fn test_pop_operation_modifies_stack() {
815 let expected_stack = create_values(vec!["1", "2"]);
816 let expected_undos = vec![
817 create_undo(3, vec![], vec!["1", "2", "3"]),
818 create_undo(0, vec!["3"], vec!["pop"]),
819 ];
820 let expected_redos = vec![];
821 let mut engine = create_engine();
822 let mut writer = BufferWriter::new();
823 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
824 assert!(parse_line(&mut engine, &mut writer, "pop").is_ok());
825 assert_eq!(engine.stack, expected_stack);
826 assert_eq!(engine.undos, expected_undos);
827 assert_eq!(engine.redos, expected_redos);
828 assert_eq!(writer.buffer, "");
829 }
830
831 #[test]
832 fn test_pop_operation_fails_cleanly() {
833 let expected_stack = create_values(vec!["1", "2", "3"]);
834 let expected_undos = vec![
835 create_undo(3, vec![], vec!["1", "2", "3"]),
836 ];
837 let expected_redos = vec![];
838 let mut engine = create_engine();
839 let mut writer = BufferWriter::new();
840 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
841 assert!(parse_line(&mut engine, &mut writer, "pop pop pop pop 999").is_err());
842 assert_eq!(engine.stack, expected_stack);
843 assert_eq!(engine.undos, expected_undos);
844 assert_eq!(engine.redos, expected_redos);
845 assert_eq!(writer.buffer, "Not enough values on stack\n");
846 }
847
848 #[test]
851 fn test_dup_operation_modifies_stack() {
852 let expected_stack = create_values(vec!["1", "2", "3", "3"]);
853 let expected_undos = vec![
854 create_undo(3, vec![], vec!["1", "2", "3"]),
855 create_undo(1, vec![], vec!["dup"]),
856 ];
857 let expected_redos = vec![];
858 let mut engine = create_engine();
859 let mut writer = BufferWriter::new();
860 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
861 assert!(parse_line(&mut engine, &mut writer, "dup").is_ok());
862 assert_eq!(engine.stack, expected_stack);
863 assert_eq!(engine.undos, expected_undos);
864 assert_eq!(engine.redos, expected_redos);
865 assert_eq!(writer.buffer, "");
866 }
867
868 #[test]
869 fn test_dup_operation_fails_cleanly() {
870 let expected_stack = create_values(vec!["1", "2", "3"]);
871 let expected_undos = vec![
872 create_undo(3, vec![], vec!["1", "2", "3"]),
873 ];
874 let expected_redos = vec![];
875 let mut engine = create_engine();
876 let mut writer = BufferWriter::new();
877 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
878 assert!(parse_line(&mut engine, &mut writer, "pop pop pop dup 999").is_err());
879 assert_eq!(engine.stack, expected_stack);
880 assert_eq!(engine.undos, expected_undos);
881 assert_eq!(engine.redos, expected_redos);
882 assert_eq!(writer.buffer, "Not enough values on stack\n");
883 }
884
885 #[test]
888 fn test_swap_operation_modifies_stack() {
889 let expected_stack = create_values(vec!["1", "3", "2"]);
890 let expected_undos = vec![
891 create_undo(3, vec![], vec!["1", "2", "3"]),
892 create_undo(2, vec!["2", "3"], vec!["swap"]),
893 ];
894 let expected_redos = vec![];
895 let mut engine = create_engine();
896 let mut writer = BufferWriter::new();
897 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
898 assert!(parse_line(&mut engine, &mut writer, "swap").is_ok());
899 assert_eq!(engine.stack, expected_stack);
900 assert_eq!(engine.undos, expected_undos);
901 assert_eq!(engine.redos, expected_redos);
902 assert_eq!(writer.buffer, "");
903 }
904
905 #[test]
906 fn test_swap_operation_fails_cleanly() {
907 let expected_stack = create_values(vec!["1", "2", "3"]);
908 let expected_undos = vec![
909 create_undo(3, vec![], vec!["1", "2", "3"]),
910 ];
911 let expected_redos = vec![];
912 let mut engine = create_engine();
913 let mut writer = BufferWriter::new();
914 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
915 assert!(parse_line(&mut engine, &mut writer, "pop pop swap 999").is_err());
916 assert_eq!(engine.stack, expected_stack);
917 assert_eq!(engine.undos, expected_undos);
918 assert_eq!(engine.redos, expected_redos);
919 assert_eq!(writer.buffer, "Not enough values on stack\n");
920 }
921
922 #[test]
925 fn test_cut_operation_copies_value() {
926 let expected_stack = vec![];
927 let expected_undos = vec![
928 create_undo(1, vec![], vec!["42"]),
929 create_undo(0, vec!["42"], vec!["cut"]),
930 ];
931 let expected_redos = vec![];
932 let mut engine = create_engine();
933 let mut writer = BufferWriter::new();
934 assert!(parse_line(&mut engine, &mut writer, "42").is_ok());
935 assert!(parse_line(&mut engine, &mut writer, "cut").is_ok());
936 assert_eq!(engine.stack, expected_stack);
937 assert_eq!(engine.undos, expected_undos);
938 assert_eq!(engine.redos, expected_redos);
939 assert_eq!(engine.clip, Some(create_value("42")));
940 assert_eq!(writer.buffer, "");
941 }
942
943 #[test]
944 fn test_cut_operation_fails_cleanly() {
945 let expected_stack = vec![];
946 let expected_undos = vec![];
947 let expected_redos = vec![];
948 let mut engine = create_engine();
949 let mut writer = BufferWriter::new();
950 assert!(parse_line(&mut engine, &mut writer, "cut").is_err());
951 assert_eq!(engine.stack, expected_stack);
952 assert_eq!(engine.undos, expected_undos);
953 assert_eq!(engine.redos, expected_redos);
954 assert_eq!(engine.clip, None);
955 assert_eq!(writer.buffer, "Not enough values on stack\n");
956 }
957
958 #[test]
961 fn test_copy_operation_copies_value() {
962 let expected_stack = create_values(vec!["42"]);
963 let expected_undos = vec![
964 create_undo(1, vec![], vec!["42"]),
965 ];
966 let expected_redos = vec![];
967 let mut engine = create_engine();
968 let mut writer = BufferWriter::new();
969 assert!(parse_line(&mut engine, &mut writer, "42").is_ok());
970 assert!(parse_line(&mut engine, &mut writer, "copy").is_ok());
971 assert_eq!(engine.stack, expected_stack);
972 assert_eq!(engine.undos, expected_undos);
973 assert_eq!(engine.redos, expected_redos);
974 assert_eq!(engine.clip, Some(create_value("42")));
975 assert_eq!(writer.buffer, "");
976 }
977
978 #[test]
979 fn test_copy_operation_fails_cleanly() {
980 let expected_stack = vec![];
981 let expected_undos = vec![];
982 let expected_redos = vec![];
983 let mut engine = create_engine();
984 let mut writer = BufferWriter::new();
985 assert!(parse_line(&mut engine, &mut writer, "copy").is_err());
986 assert_eq!(engine.stack, expected_stack);
987 assert_eq!(engine.undos, expected_undos);
988 assert_eq!(engine.redos, expected_redos);
989 assert_eq!(engine.clip, None);
990 assert_eq!(writer.buffer, "Not enough values on stack\n");
991 }
992
993 #[test]
996 fn test_paste_operation_copies_value() {
997 let expected_stack = create_values(vec!["42", "42"]);
998 let expected_undos = vec![
999 create_undo(1, vec![], vec!["42"]),
1000 create_undo(1, vec![], vec!["paste"]),
1001 ];
1002 let expected_redos = vec![];
1003 let mut engine = create_engine();
1004 let mut writer = BufferWriter::new();
1005 assert!(parse_line(&mut engine, &mut writer, "42").is_ok());
1006 assert!(parse_line(&mut engine, &mut writer, "copy").is_ok());
1007 assert!(parse_line(&mut engine, &mut writer, "paste").is_ok());
1008 assert_eq!(engine.stack, expected_stack);
1009 assert_eq!(engine.undos, expected_undos);
1010 assert_eq!(engine.redos, expected_redos);
1011 assert_eq!(engine.clip, Some(create_value("42")));
1012 assert_eq!(writer.buffer, "");
1013 }
1014
1015 #[test]
1016 fn test_paste_operation_fails_cleanly() {
1017 let expected_stack = create_values(vec!["42"]);
1018 let expected_undos = vec![
1019 create_undo(1, vec![], vec!["42"]),
1020 ];
1021 let expected_redos = vec![];
1022 let mut engine = create_engine();
1023 let mut writer = BufferWriter::new();
1024 assert!(parse_line(&mut engine, &mut writer, "42").is_ok());
1025 assert!(parse_line(&mut engine, &mut writer, "paste").is_err());
1026 assert_eq!(engine.stack, expected_stack);
1027 assert_eq!(engine.undos, expected_undos);
1028 assert_eq!(engine.redos, expected_redos);
1029 assert_eq!(engine.clip, None);
1030 assert_eq!(writer.buffer, "No value on clipboard\n");
1031 }
1032
1033 #[test]
1036 fn test_single_undo_resets_previous_line() {
1037 let expected_stack = create_values(vec!["4", "5", "6"]);
1038 let expected_undos = vec![
1039 create_undo(3, vec![], vec!["4", "5", "6"]),
1040 ];
1041 let expected_redos = vec![
1042 create_undo(2, vec!["11"], vec!["add"]),
1043 ];
1044 let mut engine = create_engine();
1045 let mut writer = BufferWriter::new();
1046 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1047 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1048 assert!(parse_line(&mut engine, &mut writer, "undo").is_ok());
1049 assert_eq!(engine.stack, expected_stack);
1050 assert_eq!(engine.undos, expected_undos);
1051 assert_eq!(engine.redos, expected_redos);
1052 assert_eq!(writer.buffer, "");
1053 }
1054
1055 #[test]
1056 fn test_double_undo_resets_previous_lines() {
1057 let expected_stack = vec![];
1058 let expected_undos = vec![];
1059 let expected_redos = vec![
1060 create_undo(2, vec!["11"], vec!["add"]),
1061 create_undo(0, vec!["4", "5", "6"], vec!["4", "5", "6"]),
1062 ];
1063 let mut engine = create_engine();
1064 let mut writer = BufferWriter::new();
1065 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1066 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1067 assert!(parse_line(&mut engine, &mut writer, "undo undo").is_ok());
1068 assert_eq!(engine.stack, expected_stack);
1069 assert_eq!(engine.undos, expected_undos);
1070 assert_eq!(engine.redos, expected_redos);
1071 assert_eq!(writer.buffer, "");
1072 }
1073
1074 #[test]
1075 fn test_single_undo_with_suffix_resets_previous_line() {
1076 let expected_stack = create_values(vec!["4", "30"]);
1077 let expected_undos = vec![
1078 create_undo(3, vec![], vec!["4", "5", "6"]),
1079 create_undo(1, vec!["5", "6"], vec!["mul"]),
1080 ];
1081 let expected_redos = vec![];
1082 let mut engine = create_engine();
1083 let mut writer = BufferWriter::new();
1084 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1085 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1086 assert!(parse_line(&mut engine, &mut writer, "undo mul").is_ok());
1087 assert_eq!(engine.stack, expected_stack);
1088 assert_eq!(engine.undos, expected_undos);
1089 assert_eq!(engine.redos, expected_redos);
1090 assert_eq!(writer.buffer, "");
1091 }
1092
1093 #[test]
1094 fn test_double_undo_with_suffix_resets_previous_lines() {
1095 let expected_stack = create_values(vec!["1", "6"]);
1096 let expected_undos = vec![
1097 create_undo(3, vec![], vec!["1", "2", "3"]),
1098 create_undo(1, vec!["2", "3"], vec!["mul"]),
1099 ];
1100 let expected_redos = vec![];
1101 let mut engine = create_engine();
1102 let mut writer = BufferWriter::new();
1103 assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
1104 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1105 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1106 assert!(parse_line(&mut engine, &mut writer, "undo undo mul").is_ok());
1107 assert_eq!(engine.stack, expected_stack);
1108 assert_eq!(engine.undos, expected_undos);
1109 assert_eq!(engine.redos, expected_redos);
1110 assert_eq!(writer.buffer, "");
1111 }
1112
1113 #[test]
1114 fn test_single_undo_with_prefix_resets_current_line() {
1115 let expected_stack = create_values(vec!["4", "11"]);
1116 let expected_undos = vec![
1117 create_undo(3, vec![], vec!["4", "5", "6"]),
1118 create_undo(1, vec!["5", "6"], vec!["add"]),
1119 ];
1120 let expected_redos = vec![
1121 create_undo(2, vec!["15"], vec!["add"]),
1122 ];
1123 let mut engine = create_engine();
1124 let mut writer = BufferWriter::new();
1125 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1126 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1127 assert!(parse_line(&mut engine, &mut writer, "add undo").is_ok());
1128 assert_eq!(engine.stack, expected_stack);
1129 assert_eq!(engine.undos, expected_undos);
1130 assert_eq!(engine.redos, expected_redos);
1131 assert_eq!(writer.buffer, "");
1132 }
1133
1134 #[test]
1135 fn test_double_undo_with_prefix_resets_current_and_previous_lines() {
1136 let expected_stack = create_values(vec!["4", "5", "6"]);
1137 let expected_undos = vec![
1138 create_undo(3, vec![], vec!["4", "5", "6"]),
1139 ];
1140 let expected_redos = vec![
1141 create_undo(2, vec!["15"], vec!["add"]),
1142 create_undo(2, vec!["11"], vec!["add"]),
1143 ];
1144 let mut engine = create_engine();
1145 let mut writer = BufferWriter::new();
1146 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1147 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1148 assert!(parse_line(&mut engine, &mut writer, "add undo undo").is_ok());
1149 assert_eq!(engine.stack, expected_stack);
1150 assert_eq!(engine.undos, expected_undos);
1151 assert_eq!(engine.redos, expected_redos);
1152 assert_eq!(writer.buffer, "");
1153 }
1154
1155 #[test]
1156 fn test_single_undo_with_prefix_and_suffix_resets_current_line() {
1157 let expected_stack = create_values(vec!["44"]);
1158 let expected_undos = vec![
1159 create_undo(3, vec![], vec!["4", "5", "6"]),
1160 create_undo(1, vec!["5", "6"], vec!["add"]),
1161 create_undo(1, vec!["4", "11"], vec!["mul"]),
1162 ];
1163 let expected_redos = vec![];
1164 let mut engine = create_engine();
1165 let mut writer = BufferWriter::new();
1166 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1167 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1168 assert!(parse_line(&mut engine, &mut writer, "add undo mul").is_ok());
1169 assert_eq!(engine.stack, expected_stack);
1170 assert_eq!(engine.undos, expected_undos);
1171 assert_eq!(engine.redos, expected_redos);
1172 assert_eq!(writer.buffer, "");
1173 }
1174
1175 #[test]
1176 fn test_double_undo_with_prefix_and_suffix_resets_current_and_previous_lines() {
1177 let expected_stack = create_values(vec!["4", "30"]);
1178 let expected_undos = vec![
1179 create_undo(3, vec![], vec!["4", "5", "6"]),
1180 create_undo(1, vec!["5", "6"], vec!["mul"]),
1181 ];
1182 let expected_redos = vec![];
1183 let mut engine = create_engine();
1184 let mut writer = BufferWriter::new();
1185 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1186 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1187 assert!(parse_line(&mut engine, &mut writer, "add undo undo mul").is_ok());
1188 assert_eq!(engine.stack, expected_stack);
1189 assert_eq!(engine.undos, expected_undos);
1190 assert_eq!(engine.redos, expected_redos);
1191 assert_eq!(writer.buffer, "");
1192 }
1193
1194 #[test]
1195 fn test_triple_undo_operation_fails_cleanly() {
1196 let expected_stack = vec![];
1197 let expected_undos = vec![];
1198 let expected_redos = vec![
1199 create_undo(2, vec!["11"], vec!["add"]),
1200 create_undo(0, vec!["4", "5", "6"], vec!["4", "5", "6"]),
1201 ];
1202 let mut engine = create_engine();
1203 let mut writer = BufferWriter::new();
1204 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1205 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1206 assert!(parse_line(&mut engine, &mut writer, "undo undo undo").is_err());
1207 assert_eq!(engine.stack, expected_stack);
1208 assert_eq!(engine.undos, expected_undos);
1209 assert_eq!(engine.redos, expected_redos);
1210 assert_eq!(writer.buffer, "Start of undo history\n");
1211 }
1212
1213 #[test]
1216 fn test_single_redo_operation_modifies_stack() {
1217 let expected_stack = create_values(vec!["4", "11"]);
1218 let expected_undos = vec![
1219 create_undo(3, vec![], vec!["4", "5", "6"]),
1220 create_undo(1, vec!["5", "6"], vec!["add"]),
1221 ];
1222 let expected_redos = vec![
1223 create_undo(2, vec!["15"], vec!["add"]),
1224 ];
1225 let mut engine = create_engine();
1226 let mut writer = BufferWriter::new();
1227 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1228 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1229 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1230 assert!(parse_line(&mut engine, &mut writer, "undo undo").is_ok());
1231 assert!(parse_line(&mut engine, &mut writer, "redo").is_ok());
1232 assert_eq!(engine.stack, expected_stack);
1233 assert_eq!(engine.undos, expected_undos);
1234 assert_eq!(engine.redos, expected_redos);
1235 assert_eq!(writer.buffer, "");
1236 }
1237
1238 #[test]
1239 fn test_double_redo_operation_modifies_stack() {
1240 let expected_stack = create_values(vec!["15"]);
1241 let expected_undos = vec![
1242 create_undo(3, vec![], vec!["4", "5", "6"]),
1243 create_undo(1, vec!["5", "6"], vec!["add"]),
1244 create_undo(1, vec!["4", "11"], vec!["add"]),
1245 ];
1246 let expected_redos = vec![];
1247 let mut engine = create_engine();
1248 let mut writer = BufferWriter::new();
1249 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1250 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1251 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1252 assert!(parse_line(&mut engine, &mut writer, "undo undo").is_ok());
1253 assert!(parse_line(&mut engine, &mut writer, "redo redo").is_ok());
1254 assert_eq!(engine.stack, expected_stack);
1255 assert_eq!(engine.undos, expected_undos);
1256 assert_eq!(engine.redos, expected_redos);
1257 assert_eq!(writer.buffer, "");
1258 }
1259
1260 #[test]
1261 fn test_single_redo_operation_with_prefix_fails_cleanly() {
1262 let expected_stack = create_values(vec!["4", "5", "6"]);
1263 let expected_undos = vec![
1264 create_undo(3, vec![], vec!["4", "5", "6"]),
1265 ];
1266 let expected_redos = vec![
1267 create_undo(2, vec!["15"], vec!["add"]),
1268 create_undo(2, vec!["11"], vec!["add"]),
1269 ];
1270 let mut engine = create_engine();
1271 let mut writer = BufferWriter::new();
1272 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1273 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1274 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1275 assert!(parse_line(&mut engine, &mut writer, "undo undo").is_ok());
1276 assert!(parse_line(&mut engine, &mut writer, "mul redo 999").is_err());
1277 assert_eq!(engine.stack, expected_stack);
1278 assert_eq!(engine.undos, expected_undos);
1279 assert_eq!(engine.redos, expected_redos);
1280 assert_eq!(writer.buffer, "End of undo history\n");
1281 }
1282
1283 #[test]
1284 fn test_triple_redo_operation_fails_cleanly() {
1285 let expected_stack = create_values(vec!["15"]);
1286 let expected_undos = vec![
1287 create_undo(3, vec![], vec!["4", "5", "6"]),
1288 create_undo(1, vec!["5", "6"], vec!["add"]),
1289 create_undo(1, vec!["4", "11"], vec!["add"]),
1290 ];
1291 let expected_redos = vec![];
1292 let mut engine = create_engine();
1293 let mut writer = BufferWriter::new();
1294 assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1295 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1296 assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1297 assert!(parse_line(&mut engine, &mut writer, "undo undo").is_ok());
1298 assert!(parse_line(&mut engine, &mut writer, "redo redo redo 999").is_err());
1299 assert_eq!(engine.stack, expected_stack);
1300 assert_eq!(engine.undos, expected_undos);
1301 assert_eq!(engine.redos, expected_redos);
1302 assert_eq!(writer.buffer, "End of undo history\n");
1303 }
1304
1305 #[test]
1308 fn test_prints_error_on_invalid_decimal() {
1309 let mut engine = create_engine();
1310 let mut writer = BufferWriter::new();
1311 assert!(parse_line(&mut engine, &mut writer, "xyz").is_err());
1312 assert_eq!(writer.buffer, "Invalid number or keyword: xyz\n");
1313 }
1314
1315 #[test]
1316 fn test_prints_error_on_invalid_hexadecimal() {
1317 let mut engine = create_engine();
1318 let mut writer = BufferWriter::new();
1319 engine.context.borrow_mut().set_hex();
1320 assert!(parse_line(&mut engine, &mut writer, "xyz").is_err());
1321 assert_eq!(writer.buffer, "Invalid number or keyword: xyz\n");
1322 }
1323
1324 #[test]
1325 fn test_shows_history_with_lower_limit() {
1326 let expected = "\
132734
132856 78 90
1329<==
133098 76
133154
1332";
1333 let mut engine = create_engine();
1334 let mut writer = BufferWriter::new();
1335 engine.undos.push(create_undo(0, vec![], vec!["12"]));
1336 engine.undos.push(create_undo(0, vec![], vec!["34"]));
1337 engine.undos.push(create_undo(0, vec![], vec!["56", "78", "90"]));
1338 engine.redos.push(create_undo(0, vec![], vec!["32", "10"]));
1339 engine.redos.push(create_undo(0, vec![], vec!["54"]));
1340 engine.redos.push(create_undo(0, vec![], vec!["98", "76"]));
1341 assert!(engine.limit_history(&mut writer, 2).is_ok());
1342 assert_eq!(writer.buffer, indent_multiline(expected));
1343 }
1344
1345 #[test]
1346 fn test_shows_history_with_higher_limit() {
1347 let expected = "\
134812
134934
135056 78 90
1351<==
135298 76
135354
135432 10
1355";
1356 let mut engine = create_engine();
1357 let mut writer = BufferWriter::new();
1358 engine.undos.push(create_undo(0, vec![], vec!["12"]));
1359 engine.undos.push(create_undo(0, vec![], vec!["34"]));
1360 engine.undos.push(create_undo(0, vec![], vec!["56", "78", "90"]));
1361 engine.redos.push(create_undo(0, vec![], vec!["32", "10"]));
1362 engine.redos.push(create_undo(0, vec![], vec!["54"]));
1363 engine.redos.push(create_undo(0, vec![], vec!["98", "76"]));
1364 assert!(engine.limit_history(&mut writer, 4).is_ok());
1365 assert_eq!(writer.buffer, indent_multiline(expected));
1366 }
1367
1368 #[test]
1369 fn test_shows_stack_with_no_values() {
1370 let mut engine = create_engine();
1371 let mut writer = BufferWriter::new();
1372 assert!(engine.show_stack(&mut writer).is_ok());
1373 assert_eq!(writer.buffer, "");
1374 }
1375
1376 #[test]
1377 fn test_shows_stack_as_decimal_with_ratios() {
1378 let expected = "\
137999999 # first
1380 123.45 # second
1381 3.142 # third
1382 3.142
1383";
1384 let mut engine = create_engine();
1385 let mut writer = BufferWriter::new();
1386 engine.stack.push(create_value("99999").with_comment("first"));
1387 engine.stack.push(create_value("123.45").with_comment("second"));
1388 engine.stack.push(create_value("3.142").with_comment("third"));
1389 engine.stack.push(create_value("3.142"));
1390 assert!(engine.show_stack(&mut writer).is_ok());
1391 assert_eq!(writer.buffer, indent_multiline(expected));
1392 }
1393
1394 #[test]
1395 fn test_shows_stack_as_hexadecimal_single() {
1396 let expected = "\
13970x7fffffff # first
13980x00000001 # second
13990x00000000 # third
14000x00000000
1401";
1402 let mut engine = create_engine();
1403 let mut writer = BufferWriter::new();
1404 engine.context.borrow_mut().format = Format::Base16(0);
1405 engine.context.borrow_mut().sep = false;
1406 engine.stack.push(create_value("2147483647").with_comment("first"));
1407 engine.stack.push(create_value("1").with_comment("second"));
1408 engine.stack.push(create_value("0").with_comment("third"));
1409 engine.stack.push(create_value("0"));
1410 assert!(engine.show_stack(&mut writer).is_ok());
1411 assert_eq!(writer.buffer, indent_multiline(expected));
1412 }
1413
1414 #[test]
1415 fn test_shows_stack_as_hexadecimal_double() {
1416 let expected = "\
14170x,00000001,00000000 # first
14180x,00000000,00000001 # second
14190x,00000000,00000000 # third
14200x,00000000,00000000
1421";
1422 let mut engine = create_engine();
1423 let mut writer = BufferWriter::new();
1424 engine.context.borrow_mut().format = Format::Base16(0);
1425 engine.context.borrow_mut().sep = true;
1426 engine.stack.push(create_value("4294967296").with_comment("first"));
1427 engine.stack.push(create_value("1").with_comment("second"));
1428 engine.stack.push(create_value("0").with_comment("third"));
1429 engine.stack.push(create_value("0"));
1430 assert!(engine.show_stack(&mut writer).is_ok());
1431 assert_eq!(writer.buffer, indent_multiline(expected));
1432 }
1433
1434 fn indent_multiline(lines: &str) -> String {
1435 lines.lines()
1436 .map(|x| format!(" {}\n", x))
1437 .collect::<Vec<String>>()
1438 .join("")
1439 }
1440
1441 pub fn create_value(number: &str) -> Value {
1442 Value::from_string(number).unwrap()
1443 }
1444
1445 pub fn create_values(values: Vec<&str>) -> Vec<Value> {
1446 values.iter().map(|x| create_value(x)).collect()
1447 }
1448
1449 fn create_engine() -> Engine<BufferWriter> {
1450 let config = Config::default();
1451 Engine::new(config).unwrap().with_interact(true)
1452 }
1453
1454 fn parse_line(
1455 engine: &mut Engine<BufferWriter>,
1456 writer: &mut BufferWriter,
1457 line: &str,
1458 ) -> MyResult<()> {
1459 let result = engine.parse_line(writer, line);
1460 if let Err(error) = &result {
1461 writeln!(writer, "{}", error)?;
1462 }
1463 result
1464 }
1465
1466 impl<W: Write> Engine<W> {
1467 pub fn with_interact(mut self, interact: bool) -> Self {
1468 self.interact = interact;
1469 self
1470 }
1471 }
1472}