rpn_cli/
engine.rs

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
30// noinspection RsLift
31impl<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// noinspection DuplicatedCode
562#[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    // VALUE CREATION
582
583    #[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    // UNKNOWN OPERATIONS
662
663    #[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    // NULLARY OPERATIONS
681
682    #[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    // UNARY OPERATIONS
698
699    #[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    // BINARY OPERATIONS
735
736    #[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    // SERIES OPERATIONS
772
773    #[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    // CLEAR OPERATIONS
792
793    #[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    // POP OPERATIONS
812
813    #[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    // DUP OPERATIONS
849
850    #[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    // SWAP OPERATIONS
886
887    #[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    // CUT OPERATIONS
923
924    #[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    // COPY OPERATIONS
959
960    #[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    // PASTE OPERATIONS
994
995    #[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    // UNDO OPERATIONS
1034
1035    #[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    // REDO OPERATIONS
1214
1215    #[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    // TEXT OUTPUT
1306
1307    #[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}