rpn_cli/
engine.rs

1use crate::calc::context::{Context, Format};
2use crate::calc::undo::Undo;
3use crate::calc::value::{Value, ValueRef};
4use crate::config::Config;
5use crate::core::action;
6use crate::core::action::{Action, Actions};
7use crate::core::count::Count;
8use crate::core::helper::CommandEditor;
9use crate::core::interface::{Directive, Interface, Operation};
10use crate::core::stack::{BracketChars, StackItem, ValueStack};
11use crate::error::{EngineError, MyError, MyResult};
12use crate::util::text::create_padding;
13use fileinput::FileInput;
14use itertools::Itertools;
15use std::cell::RefCell;
16use std::fs::File;
17use std::io::{BufRead, BufReader, Write};
18use std::rc::Rc;
19use std::slice::Iter;
20
21const PAGE_LIMIT: usize = 10;
22
23pub struct Engine<W: Write> {
24    config: Config,
25    editor: CommandEditor,
26    interface: Rc<RefCell<Interface<W>>>,
27    context: Rc<RefCell<Context>>,
28    undos: Vec<Undo>,
29    redos: Vec<Undo>,
30    clip: Option<ValueRef>,
31    dirty: bool,
32    interact: bool,
33    chars: BracketChars,
34}
35
36// noinspection RsLift
37impl<W: Write> Engine<W> {
38    pub fn new(config: Config, chars: BracketChars) -> MyResult<Self> {
39        let interface = Rc::new(RefCell::new(Interface::build()));
40        let editor = interface.borrow().create_editor()?;
41        let context = Context::new()
42            .with_hex(config.hex)
43            .with_sep(config.sep)
44            .with_dp(config.dp);
45        let context = Rc::new(RefCell::new(context));
46        let undos = Vec::new();
47        let redos = Vec::new();
48        let engine = Self {
49            config,
50            editor,
51            interface,
52            context,
53            undos,
54            redos,
55            clip: None,
56            dirty: false,
57            interact: false,
58            chars,
59        };
60        Ok(engine)
61    }
62
63    pub fn parse_input(&mut self, writer: &mut W) -> MyResult<()> {
64        let mut stack = ValueStack::new(Vec::new());
65        if let Some(import) = &self.config.import {
66            let import = vec![String::from(import)];
67            self.import_file(writer, &mut stack, import)?;
68        }
69        if !self.config.values.is_empty() {
70            self.parse_values(writer, &mut stack)?;
71            if !self.config.mock {
72                self.show_simple(writer, &mut stack)?;
73            }
74        } else if !self.config.paths.is_empty() || atty::isnt(atty::Stream::Stdin) || atty::isnt(atty::Stream::Stdout) {
75            let reader = FileInput::new(&self.config.paths);
76            self.parse_files(writer, &mut stack, reader)?;
77            self.show_simple(writer, &mut stack)?;
78        } else {
79            self.parse_loop(writer, &mut stack)?;
80        }
81        Ok(())
82    }
83
84    fn parse_values(
85        &mut self,
86        writer: &mut W,
87        stack: &mut ValueStack,
88    ) -> MyResult<()> {
89        let values = self.config.values.drain(..).collect::<Vec<String>>();
90        if self.config.mock {
91            for (index, value) in values.iter().enumerate() {
92                self.interact = index + 1 == values.len();
93                self.interact_line(writer, stack, &value)?;
94            }
95        } else {
96            for value in values {
97                self.parse_line(writer, stack, &value)?;
98            }
99        }
100        Ok(())
101    }
102
103    fn parse_files(
104        &mut self,
105        writer: &mut W,
106        stack: &mut ValueStack,
107        reader: FileInput,
108    ) -> MyResult<()> {
109        let mut undo = Undo::default();
110        let mut redo = Undo::default();
111        let reader = BufReader::new(reader);
112        for line in reader.lines() {
113            let line = line?;
114            self.parse_inner(writer, stack, &mut undo, &mut redo, &line)?;
115        }
116        self.commit_undo(undo, redo);
117        Ok(())
118    }
119
120    fn parse_loop(
121        &mut self,
122        writer: &mut W,
123        stack: &mut ValueStack,
124    ) -> MyResult<()> {
125        self.interact = true;
126        loop {
127            let line = self.editor.readline("rpn> ")?;
128            self.editor.add_history_entry(&line)?;
129            self.interact_line(writer, stack, &line)?;
130        }
131    }
132
133    fn interact_line(
134        &mut self,
135        writer: &mut W,
136        stack: &mut ValueStack,
137        line: &str,
138    ) -> MyResult<()> {
139        let result = match self.parse_line(writer, stack, line) {
140            Ok(()) => {
141                if self.interact && self.dirty {
142                    self.limit_stack(writer, stack, Some(PAGE_LIMIT))?;
143                }
144                Ok(())
145            }
146            Err(MyError::Engine(error)) => {
147                if self.interact {
148                    writeln!(writer, "  {}", error)?;
149                }
150                Ok(())
151            }
152            Err(error) => {
153                Err(error)
154            }
155        };
156        self.dirty = false;
157        result
158    }
159
160    fn parse_line(
161        &mut self,
162        writer: &mut W,
163        stack: &mut ValueStack,
164        line: &str,
165    ) -> MyResult<()> {
166        let mut undo = Undo::default();
167        let mut redo = Undo::default();
168        self.parse_inner(writer, stack, &mut undo, &mut redo, line)?;
169        self.commit_undo(undo, redo);
170        Ok(())
171    }
172
173    fn parse_inner(
174        &mut self,
175        writer: &mut W,
176        stack: &mut ValueStack,
177        undo: &mut Undo,
178        redo: &mut Undo,
179        line: &str,
180    ) -> MyResult<()> {
181        let mut empty = true;
182        let (line, comment) = Self::split_comment(line);
183        let actions = Actions::new(&self.interface, line.split_ascii_whitespace());
184        for action in actions {
185            let action = match action {
186                Ok((action, keyword)) => self.apply_action(
187                    writer,
188                    stack,
189                    undo,
190                    redo,
191                    action,
192                    Some(keyword),
193                ),
194                Err(error) => Err(error),
195            };
196            if let Err(error) = action {
197                undo.apply_to(stack);
198                return Err(error);
199            }
200            empty = false;
201        }
202        if let Some(comment) = comment {
203            if let Err(error) = self.apply_comment(stack, comment) {
204                undo.apply_to(stack);
205                return Err(error);
206            }
207            empty = false;
208        }
209        self.dirty |= empty;
210        Ok(())
211    }
212
213    fn split_comment(line: &str) -> (&str, Option<&str>) {
214        if let Some(stop) = line.find('#') {
215            let start = stop + 1;
216            let values = line[..stop].trim();
217            let comment = line[start..].trim();
218            let comment = if comment.is_empty() { None } else { Some(comment) };
219            (values, comment)
220        } else {
221            let values = line.trim();
222            (values, None)
223        }
224    }
225
226    fn apply_action(
227        &mut self,
228        writer: &mut W,
229        stack: &mut ValueStack,
230        undo: &mut Undo,
231        redo: &mut Undo,
232        action: Action<W>,
233        keyword: Option<&str>,
234    ) -> MyResult<()> {
235        match action {
236            Action::Operation(operation) => {
237                match operation.as_ref() {
238                    Operation::ValueNone(function) => {
239                        let result = function()?;
240                        stack.push_single(undo, result, keyword);
241                        self.dirty = true;
242                    }
243                    Operation::ValueOne(function) => {
244                        let value = stack.pop_single(undo, None)?;
245                        let result = function(value)?;
246                        stack.push_single(undo, result, keyword);
247                        self.dirty = true;
248                    }
249                    Operation::ValueTwo(function) => {
250                        let (value1, value2) = stack.pop_double(undo, None)?;
251                        let result = function(value1, value2)?;
252                        stack.push_single(undo, result, keyword);
253                        self.dirty = true;
254                    }
255                    Operation::ValueAll(function) => {
256                        let (values, _) = stack.pop_series(undo, None);
257                        let result = function(values)?;
258                        stack.push_single(undo, result, keyword);
259                        self.dirty = true;
260                    }
261                    Operation::SeriesTwo(function) => {
262                        let (value1, value2) = stack.pop_double(undo, None)?;
263                        let results = function(value1, value2)?;
264                        self.dirty |= stack.push_series(undo, results, keyword);
265                    }
266                    Operation::SeriesThree(function) => {
267                        let (value1, value2, value3) = stack.pop_triple(undo, None)?;
268                        let results = function(value1, value2, value3)?;
269                        self.dirty |= stack.push_series(undo, results, keyword);
270                    }
271                    Operation::SeriesAll(function) => {
272                        let (values, as_series) = stack.pop_series(undo, None);
273                        let results = function(values)?;
274                        if as_series {
275                            self.dirty |= stack.push_series(undo, results, keyword);
276                        } else {
277                            self.dirty |= stack.push_singles(undo, results, keyword);
278                        }
279                    }
280                    Operation::TimeNow(function) => {
281                        let result = function(&self.config.now)?;
282                        stack.push_single(undo, result, keyword);
283                        self.dirty = true;
284                    }
285                    Operation::TimeCast(meaning) => {
286                        let value = stack.pop_single(undo, None)?;
287                        let result = value.borrow().apply_meaning(*meaning)?;
288                        stack.push_single(undo, result, keyword);
289                        self.dirty = true;
290                    }
291                    Operation::ContextNone(function) => {
292                        function(&mut self.context.borrow_mut());
293                        self.dirty = true;
294                    }
295                    Operation::ContextOne(function) => {
296                        let value = stack.pop_single(undo, keyword)?;
297                        function(&mut self.context.borrow_mut(), value);
298                        self.dirty = true;
299                    }
300                    Operation::EngineNone(function) => {
301                        if let Some(dirty) = function(self, writer, stack)? {
302                            self.dirty = dirty;
303                        }
304                    }
305                    Operation::EngineUndo(function, _, _) => {
306                        if let Some(dirty) = function(self, stack, undo, redo, keyword)? {
307                            self.dirty = dirty;
308                        }
309                    }
310                }
311            }
312            Action::Meaning(meaning) => {
313                let value = stack.pop_single(undo, None)?;
314                let result = value.borrow().apply_meaning(meaning)?;
315                stack.push_single(undo, result, keyword);
316                self.dirty = true;
317            }
318            Action::Directive(directive, tokens) => {
319                match directive.as_ref() {
320                    Directive::EngineOne(function, _) => {
321                        let token = tokens.into_iter().next();
322                        self.dirty |= function(self, writer, stack, token)?;
323                    }
324                    Directive::EngineAll(function, _) => {
325                        self.dirty |= function(self, writer, stack, tokens)?;
326                    }
327                    Directive::EngineApply(function, _) => {
328                        self.dirty |= function(self, writer, keyword, stack, undo, redo, tokens)?;
329                    }
330                }
331            }
332            Action::Definition(actions) => {
333                for action in actions {
334                    self.apply_action(writer, stack, undo, redo, action, None)?;
335                }
336                undo.merge(0, vec![], keyword);
337            }
338            Action::Value(value, dirty) => {
339                stack.push_single(undo, value, keyword);
340                self.dirty |= dirty;
341            }
342        }
343        Ok(())
344    }
345
346    fn apply_comment(
347        &mut self,
348        stack: &ValueStack,
349        comment: &str,
350    ) -> MyResult<()> {
351        let value = stack.peek_single()?;
352        value.borrow_mut().set_comment(comment);
353        self.dirty = true;
354        Ok(())
355    }
356
357    fn commit_undo(
358        &mut self,
359        undo: Undo,
360        redo: Undo,
361    ) {
362        if !undo.is_empty() {
363            self.undos.push(undo);
364            self.redos.clear();
365        } else if !redo.is_empty() {
366            self.redos.push(redo);
367        }
368    }
369
370    pub fn flat_values(
371        &mut self,
372        stack: &mut ValueStack,
373        undo: &mut Undo,
374        redo: &mut Undo,
375        keyword: Option<&str>,
376    ) -> MyResult<Option<bool>> {
377        if stack.items.iter().any(|item| matches!(item, StackItem::Series(_))) {
378            let items = stack.pop_stack(undo, None);
379            redo.clear();
380            stack.push_singles(undo, items, keyword);
381            Ok(Some(true))
382        } else {
383            Ok(None)
384        }
385    }
386
387    pub fn clear_values(
388        &mut self,
389        stack: &mut ValueStack,
390        undo: &mut Undo,
391        redo: &mut Undo,
392        keyword: Option<&str>,
393    ) -> MyResult<Option<bool>> {
394        let items = stack.wrapped_drain(..).collect();
395        undo.merge(0, items, keyword);
396        redo.clear();
397        Ok(Some(true))
398    }
399
400    pub fn pop_value(
401        &mut self,
402        stack: &mut ValueStack,
403        undo: &mut Undo,
404        redo: &mut Undo,
405        keyword: Option<&str>,
406    ) -> MyResult<Option<bool>> {
407        stack.pop_single(undo, keyword)?;
408        redo.clear();
409        Ok(Some(true))
410    }
411
412    pub fn dup_value(
413        &mut self,
414        stack: &mut ValueStack,
415        undo: &mut Undo,
416        redo: &mut Undo,
417        keyword: Option<&str>,
418    ) -> MyResult<Option<bool>> {
419        let value = stack.peek_single()?;
420        let value = Rc::new(RefCell::new(value.borrow().clone()));
421        stack.push_single(undo, value, keyword);
422        redo.clear();
423        Ok(Some(true))
424    }
425
426    pub fn swap_values(
427        &mut self,
428        stack: &mut ValueStack,
429        undo: &mut Undo,
430        redo: &mut Undo,
431        keyword: Option<&str>,
432    ) -> MyResult<Option<bool>> {
433        let (value1, value2) = stack.pop_double(undo, None)?;
434        stack.push_single(undo, value2, None);
435        stack.push_single(undo, value1, keyword);
436        redo.clear();
437        Ok(Some(true))
438    }
439
440    pub fn cut_value(
441        &mut self,
442        stack: &mut ValueStack,
443        undo: &mut Undo,
444        redo: &mut Undo,
445        keyword: Option<&str>,
446    ) -> MyResult<Option<bool>> {
447        let value = stack.pop_single(undo, keyword)?;
448        self.clip = Some(value);
449        redo.clear();
450        Ok(Some(true))
451    }
452
453    pub fn copy_value(
454        &mut self,
455        stack: &mut ValueStack,
456        _undo: &mut Undo,
457        _redo: &mut Undo,
458        _keyword: Option<&str>,
459    ) -> MyResult<Option<bool>> {
460        let value = stack.peek_single()?;
461        let value = Rc::new(RefCell::new(value.borrow().clone()));
462        self.clip = Some(value);
463        Ok(None)
464    }
465
466    pub fn paste_value(
467        &mut self,
468        stack: &mut ValueStack,
469        undo: &mut Undo,
470        redo: &mut Undo,
471        keyword: Option<&str>,
472    ) -> MyResult<Option<bool>> {
473        if let Some(clip) = &self.clip {
474            stack.push_single(undo, Rc::clone(clip), keyword);
475            redo.clear();
476            Ok(Some(true))
477        } else {
478            Err(MyError::from(EngineError::MissingClip))
479        }
480    }
481
482    pub fn import_file(
483        &mut self,
484        writer: &mut W,
485        stack: &mut ValueStack,
486        tokens: Vec<String>,
487    ) -> MyResult<bool> {
488        let reader = FileInput::new(&tokens);
489        self.parse_files(writer, stack, reader)?;
490        Ok(true)
491    }
492
493    pub fn export_file(
494        &mut self,
495        _writer: &mut W,
496        stack: &mut ValueStack,
497        tokens: Vec<String>,
498    ) -> MyResult<bool> {
499        if let Some(path) = tokens.first() {
500            let mut writer = File::create(path)?;
501            let sep = self.context.borrow_mut().swap_sep(false);
502            let result = self.write_simple(&mut writer, stack);
503            self.context.borrow_mut().swap_sep(sep);
504            result?;
505        }
506        Ok(false)
507    }
508
509    pub fn set_variable(
510        &mut self,
511        writer: &mut W,
512        stack: &mut ValueStack,
513        token: Option<String>,
514    ) -> MyResult<bool> {
515        if let Some(token) = token {
516            let value = stack.peek_single()?;
517            if self.interface.borrow_mut().insert_variable(token.clone(), Rc::clone(&value)) {
518                for (value, _) in stack.iter_stack() {
519                    Self::unassign_variable(value, &token);
520                }
521            }
522            self.reassign_variable(value, token);
523            self.interface.borrow().adjust_editor(&mut self.editor);
524            Ok(true)
525        } else {
526            let items = self.interface.borrow()
527                .get_variables()
528                .iter()
529                .sorted_by(|(lhs, _), (rhs, _)| String::cmp(lhs, rhs))
530                .map(|(_, value)| Rc::clone(value))
531                .map(|value| StackItem::Single(value))
532                .collect::<Vec<_>>();
533            let mut stack = ValueStack::new(items);
534            self.show_stack(writer, &mut stack)?;
535            Ok(false)
536        }
537    }
538
539    fn unassign_variable(value: ValueRef, token: &str) {
540        let mut inner = value.borrow_mut();
541        if let Some(previous) = &inner.variable {
542            if previous == token {
543                inner.variable = None;
544            }
545        }
546    }
547
548    fn reassign_variable(&mut self, value: ValueRef, token: String) {
549        let mut inner = value.borrow_mut();
550        if let Some(previous) = &inner.variable {
551            if previous != &token {
552                self.interface.borrow_mut().remove_variable(previous);
553            }
554        }
555        inner.variable = Some(token);
556    }
557
558    pub fn define_function(
559        &mut self,
560        writer: &mut W,
561        _stack: &mut ValueStack,
562        tokens: Vec<String>,
563    ) -> MyResult<bool> {
564        let mut tokens = tokens.iter();
565        if let Some(keyword) = tokens.next() {
566            let description = tokens.clone().join(" ");
567            let actions = self.parse_actions(tokens)?;
568            if !actions.is_empty() {
569                let (input, output) = action::fold_actions(&actions);
570                self.interface.borrow_mut().insert_definition(
571                    keyword,
572                    actions,
573                    input,
574                    output,
575                    description,
576                );
577            } else {
578                self.interface.borrow_mut().remove_definition(keyword);
579            }
580            self.interface.borrow().adjust_editor(&mut self.editor);
581        } else {
582            self.interface.borrow().show_definitions(writer, self.interact)?;
583        }
584        Ok(false)
585    }
586
587    pub fn apply_all(
588        &mut self,
589        writer: &mut W,
590        keyword: Option<&str>,
591        stack: &mut ValueStack,
592        undo: &mut Undo,
593        _redo: &mut Undo,
594        tokens: Vec<String>,
595    ) -> MyResult<bool> {
596        let actions = self.parse_actions(tokens.iter())?;
597        let (input, output) = action::fold_actions(&actions);
598        if let (Count::N(1), Count::N(1)) = (input, output) {
599            let (input_values, as_series) = stack.pop_series(undo, None);
600            let mut output_values = Vec::new();
601            let mut temp_undo = Undo::new(0, vec![], vec![]);
602            let mut temp_redo = Undo::new(0, vec![], vec![]);
603            for value in input_values {
604                let mut temp_stack = ValueStack::new(Vec::new());
605                temp_stack.push_single(&mut temp_undo, value, None);
606                for action in &actions {
607                    self.apply_action(
608                        writer,
609                        &mut temp_stack,
610                        &mut temp_undo,
611                        &mut temp_redo,
612                        action.clone(),
613                        None,
614                    )?;
615                }
616                let (mut temp_values, _) = temp_stack.pop_series(&mut temp_undo, None);
617                output_values.append(&mut temp_values);
618            }
619            if !output_values.is_empty() {
620                if as_series {
621                    stack.push_series(undo, output_values, None);
622                } else {
623                    stack.push_singles(undo, output_values, None);
624                }
625                undo.add_tokens(keyword, tokens);
626                Ok(true)
627            } else {
628                Ok(false)
629            }
630        } else {
631            Err(MyError::Engine(EngineError::BadApplyOp(input, output)))
632        }
633    }
634
635    fn parse_actions(
636        &mut self,
637        tokens: Iter<String>,
638    ) -> MyResult<Vec<Action<W>>> {
639        let tokens = tokens.map(String::as_ref);
640        let actions = Actions::new(&self.interface, tokens);
641        actions
642            .map(|result| result.map(|(x, _)| x))
643            .collect::<MyResult<Vec<Action<W>>>>()
644    }
645
646    pub fn undo_stack(
647        &mut self,
648        stack: &mut ValueStack,
649        undo: &mut Undo,
650        redo: &mut Undo,
651        _keyword: Option<&str>,
652    ) -> MyResult<Option<bool>> {
653        if !undo.is_empty() {
654            self.redos.push(undo.apply_to(stack));
655            redo.clear();
656            Ok(Some(true))
657        } else if let Some(mut undo) = self.undos.pop() {
658            self.redos.push(undo.apply_to(stack));
659            redo.clear();
660            Ok(Some(true))
661        } else {
662            Err(MyError::from(EngineError::MissingUndo))
663        }
664    }
665
666    pub fn redo_stack(
667        &mut self,
668        stack: &mut ValueStack,
669        undo: &mut Undo,
670        redo: &mut Undo,
671        _keyword: Option<&str>,
672    ) -> MyResult<Option<bool>> {
673        if undo.is_empty() {
674            if !redo.is_empty() {
675                self.undos.push(redo.apply_to(stack));
676                return Ok(Some(true));
677            } else if let Some(mut redo) = self.redos.pop() {
678                self.undos.push(redo.apply_to(stack));
679                return Ok(Some(true));
680            }
681        }
682        Err(MyError::from(EngineError::MissingRedo))
683    }
684
685    pub fn show_history(
686        &mut self,
687        writer: &mut W,
688        _stack: &mut ValueStack,
689    ) -> MyResult<Option<bool>> {
690        if self.interact {
691            self.limit_history(writer, PAGE_LIMIT)?;
692        }
693        Ok(Some(false))
694    }
695
696    fn limit_history(&mut self, writer: &mut W, limit: usize) -> MyResult<()> {
697        if self.undos.is_empty() {
698            writeln!(writer, "  <==")?;
699        } else {
700            if self.undos.len() > limit {
701                writeln!(writer, "  ...")?;
702            }
703            for (index, undo) in self.undos.iter().rev().enumerate().take(limit).rev() {
704                if index == 0 {
705                    writeln!(writer, "  {} <==", undo)?;
706                } else {
707                    writeln!(writer, "  {}", undo)?;
708                }
709            }
710        }
711        for redo in self.redos.iter().rev().take(limit) {
712            writeln!(writer, "  {}", redo)?;
713        }
714        if self.redos.len() > limit {
715            writeln!(writer, "  ...")?;
716        }
717        Ok(())
718    }
719
720    fn show_simple(
721        &mut self,
722        writer: &mut W,
723        stack: &mut ValueStack,
724    ) -> Result<(), MyError> {
725        if self.config.sum {
726            let mut undo = Undo::new(0, vec![], vec![]);
727            let (values, _) = stack.pop_series(&mut undo, None);
728            let result = Value::calc_sum(values)?;
729            stack.push_single(&mut undo, result, None);
730        }
731        self.write_simple(writer, stack)?;
732        Ok(())
733    }
734
735    fn write_simple<V: Write>(
736        &mut self,
737        writer: &mut V,
738        stack: &mut ValueStack,
739    ) -> MyResult<()> {
740        self.measure_hexadecimal(stack);
741        let context = self.context.borrow();
742        for (value, _) in stack.iter_stack() {
743            let (integer, fraction, _, _, _) = value.borrow().to_strings(&context);
744            writeln!(writer, "{}{}", integer, fraction)?;
745        }
746        Ok(())
747    }
748
749    pub fn show_stack(
750        &mut self,
751        writer: &mut W,
752        stack: &mut ValueStack,
753    ) -> MyResult<Option<bool>> {
754        self.limit_stack(writer, stack, None)?;
755        Ok(Some(false))
756    }
757
758    fn limit_stack(
759        &mut self,
760        writer: &mut W,
761        stack: &mut ValueStack,
762        limit: Option<usize>,
763    ) -> MyResult<()> {
764        if self.interact {
765            self.measure_hexadecimal(stack);
766            let context = self.context.borrow();
767            let table = match limit {
768                Some(limit) if limit < stack.total_len() => {
769                    // It is necessary to collect intermediate results
770                    // into a vector, or the double ended iterator is
771                    // not called.
772                    writeln!(writer, "  ...")?;
773                    stack.iter_stack()
774                        .rev()
775                        .take(limit)
776                        .collect::<Vec<_>>()
777                        .into_iter()
778                        .rev()
779                        .map(|(value, style)| (value.borrow().to_strings(&context), style))
780                        .collect::<Vec<_>>()
781                }
782                _ => {
783                    stack.iter_stack()
784                        .map(|(value, style)| (value.borrow().to_strings(&context), style))
785                        .collect::<Vec<_>>()
786                }
787            };
788            let integer_width = table.iter()
789                .map(|((x, _, _, _, _), _)| x.len())
790                .max()
791                .unwrap_or_default();
792            let fraction_width = table.iter()
793                .map(|((_, x, _, _, _), _)| x.len())
794                .max()
795                .unwrap_or_default();
796            for ((integer, fraction, meaning, variable, comment), style) in table {
797                let padding = create_padding(' ', integer_width + 1, integer.len(), 0);
798                let prefix = self.chars.get_prefix(style).unwrap_or(' ');
799                let suffix = self.chars.get_suffix(style);
800                write!(writer, "{}{}{}{}", prefix, padding, integer, fraction)?;
801                if suffix.is_some() || meaning.is_some() || variable.is_some() || comment.is_some() {
802                    let padding = create_padding(' ', fraction_width, fraction.len(), 0);
803                    write!(writer, "{}", padding)?;
804                }
805                if let Some(suffix) = suffix {
806                    write!(writer, " {}", suffix)?;
807                }
808                if let Some(meaning) = meaning {
809                    write!(writer, " {}", meaning)?;
810                }
811                if let Some(variable) = variable {
812                    write!(writer, " = {}", variable)?;
813                }
814                if let Some(comment) = comment {
815                    write!(writer, " # {}", comment)?;
816                }
817                writeln!(writer)?;
818            }
819        }
820        Ok(())
821    }
822
823    fn measure_hexadecimal(&mut self, stack: &ValueStack) {
824        let mut context = self.context.borrow_mut();
825        if let Format::Base16(_) = context.format {
826            let chunks = stack.iter_stack()
827                .map(|(value, _)| value.borrow().measure_hexadecimal())
828                .max()
829                .unwrap_or_default();
830            context.format = Format::Base16(chunks);
831        }
832    }
833
834    pub fn show_units(
835        &mut self,
836        writer: &mut W,
837        _stack: &mut ValueStack,
838    ) -> MyResult<Option<bool>> {
839        self.interface.borrow().show_units(writer, self.interact)?;
840        Ok(Some(false))
841    }
842
843    pub fn show_help(
844        &mut self,
845        writer: &mut W,
846        _stack: &mut ValueStack,
847    ) -> MyResult<Option<bool>> {
848        self.interface.borrow().show_help(writer, self.interact)?;
849        Ok(Some(false))
850    }
851}
852
853// noinspection DuplicatedCode
854#[cfg(test)]
855pub mod tests {
856    use crate::calc::context::Format;
857    use crate::calc::meaning::AreaKind::*;
858    use crate::calc::meaning::DataKind::*;
859    use crate::calc::meaning::DeltaKind::*;
860    use crate::calc::meaning::LengthKind::*;
861    use crate::calc::meaning::MassKind::*;
862    use crate::calc::meaning::Meaning::*;
863    use crate::calc::meaning::PrefixKind::*;
864    use crate::calc::meaning::SpeedKind::*;
865    use crate::calc::meaning::TempKind::*;
866    use crate::calc::meaning::VolumeKind::*;
867    use crate::calc::undo::tests::create_undo;
868    use crate::calc::value::tests::{parse_ref, parse_value};
869    use crate::calc::value::{Value, ValueRef};
870    use crate::config::Config;
871    use crate::core::stack::tests::{parse_item, parse_items, parse_series};
872    use crate::core::stack::{BracketChars, ValueStack};
873    use crate::engine::Engine;
874    use crate::error::MyResult;
875    use crate::util::text::tests::BufferWriter;
876    use pretty_assertions::assert_eq;
877    use std::cell::RefCell;
878    use std::collections::HashMap;
879    use std::io::Write;
880    use std::rc::Rc;
881
882    #[test]
883    fn test_split_comment_finds_first_hash() {
884        assert_eq!(Engine::<BufferWriter>::split_comment("\tone two three\t"), ("one two three", None));
885        assert_eq!(Engine::<BufferWriter>::split_comment("\tone two three #\t"), ("one two three", None));
886        assert_eq!(Engine::<BufferWriter>::split_comment("\tone # two # three\t"), ("one", Some("two # three")));
887    }
888
889    // VALUE CREATION
890
891    #[test]
892    fn test_create_values_modifies_stack() {
893        let expected_items = parse_items(vec!["1", "2", "3", "4", "5", "6"]);
894        let expected_undos = vec![
895            create_undo(3, vec![], vec!["1", "2", "3"]),
896            create_undo(3, vec![], vec!["4", "5", "6"]),
897        ];
898        let expected_redos = vec![];
899        let mut engine = create_engine();
900        let mut writer = BufferWriter::new();
901        let mut stack = ValueStack::new(Vec::new());
902        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
903        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
904        assert_eq!(stack.items, expected_items);
905        assert_eq!(engine.undos, expected_undos);
906        assert_eq!(engine.redos, expected_redos);
907        assert_eq!(writer.buffer, "");
908    }
909
910    #[test]
911    fn test_comment_modifies_current_line() {
912        let expected_items = vec![
913            parse_item("1"),
914            parse_item("2"),
915            parse_item("3"),
916            parse_item("42").with_comment("the answer"),
917        ];
918        let expected_undos = vec![
919            create_undo(2, vec![], vec!["1", "2"]),
920            create_undo(2, vec![], vec!["3", "42"]),
921        ];
922        let expected_redos = vec![];
923        let mut engine = create_engine();
924        let mut writer = BufferWriter::new();
925        let mut stack = ValueStack::new(Vec::new());
926        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2").is_ok());
927        assert!(parse_line(&mut engine, &mut writer, &mut stack, "3 42 # the answer").is_ok());
928        assert_eq!(stack.items, expected_items);
929        assert_eq!(engine.undos, expected_undos);
930        assert_eq!(engine.redos, expected_redos);
931        assert_eq!(writer.buffer, "");
932    }
933
934    #[test]
935    fn test_comment_modifies_previous_line() {
936        let expected_items = vec![
937            parse_item("1"),
938            parse_item("2"),
939            parse_item("3"),
940            parse_item("42").with_comment("the answer"),
941        ];
942        let expected_undos = vec![
943            create_undo(4, vec![], vec!["1", "2", "3", "42"]),
944        ];
945        let expected_redos = vec![];
946        let mut engine = create_engine();
947        let mut writer = BufferWriter::new();
948        let mut stack = ValueStack::new(Vec::new());
949        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3 42").is_ok());
950        assert!(parse_line(&mut engine, &mut writer, &mut stack, "# the answer").is_ok());
951        assert_eq!(stack.items, expected_items);
952        assert_eq!(engine.undos, expected_undos);
953        assert_eq!(engine.redos, expected_redos);
954        assert_eq!(writer.buffer, "");
955    }
956
957    #[test]
958    fn test_comment_fails_cleanly() {
959        let expected_items = vec![];
960        let expected_undos = vec![];
961        let expected_redos = vec![];
962        let mut engine = create_engine();
963        let mut writer = BufferWriter::new();
964        let mut stack = ValueStack::new(Vec::new());
965        assert!(parse_line(&mut engine, &mut writer, &mut stack, "# the answer").is_err());
966        assert_eq!(stack.items, expected_items);
967        assert_eq!(engine.undos, expected_undos);
968        assert_eq!(engine.redos, expected_redos);
969        assert_eq!(writer.buffer, "Not enough values on stack\n");
970    }
971
972    // CAST OPERATIONS
973
974    #[test]
975    fn test_cast_to_synbol_modifies_stack() {
976        let expected_items = vec![
977            parse_item("1").with_meaning(Delta(Second(Unit))),
978            parse_item("1").with_meaning(Length(Metre(Kilo))),
979            parse_item("1").with_meaning(Area(Square(Metre(Unit)))),
980            parse_item("1").with_meaning(Volume(Cubic(Metre(Unit)))),
981            parse_item("1").with_meaning(Speed(Ratio(Metre(Unit), Second(Unit)))),
982            parse_item("1").with_meaning(Volume(Litre(Milli))),
983            parse_item("1").with_meaning(Mass(Gram(Micro))),
984            parse_item("1").with_meaning(Temp(Kelvin(Unit))),
985            parse_item("1").with_meaning(Data(Byte(Mega))),
986        ];
987        let expected_undos = vec![
988            create_undo(1, vec![], vec!["1", "s"]),
989            create_undo(1, vec![], vec!["1", "km"]),
990            create_undo(1, vec![], vec!["1", "m^2"]),
991            create_undo(1, vec![], vec!["1", "m^3"]),
992            create_undo(1, vec![], vec!["1", "m/s"]),
993            create_undo(1, vec![], vec!["1", "ml"]),
994            create_undo(1, vec![], vec!["1", "ug"]),
995            create_undo(1, vec![], vec!["1", "K"]),
996            create_undo(1, vec![], vec!["1", "MB"]),
997        ];
998        let expected_redos = vec![];
999        let mut engine = create_engine();
1000        let mut writer = BufferWriter::new();
1001        let mut stack = ValueStack::new(Vec::new());
1002        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 s").is_ok());
1003        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 km").is_ok());
1004        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 m^2").is_ok());
1005        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 m^3").is_ok());
1006        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 m/s").is_ok());
1007        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 ml").is_ok());
1008        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 ug").is_ok());
1009        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 K").is_ok());
1010        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 MB").is_ok());
1011        assert_eq!(stack.items, expected_items);
1012        assert_eq!(engine.undos, expected_undos);
1013        assert_eq!(engine.redos, expected_redos);
1014        assert_eq!(writer.buffer, "");
1015    }
1016
1017    #[test]
1018    fn test_cast_to_name_modifies_stack() {
1019        let expected_items = vec![
1020            parse_item("1").with_meaning(Delta(Second(Unit))),
1021            parse_item("1").with_meaning(Length(Metre(Kilo))),
1022            parse_item("1").with_meaning(Area(Square(Metre(Unit)))),
1023            parse_item("1").with_meaning(Volume(Cubic(Metre(Unit)))),
1024            parse_item("1").with_meaning(Speed(Ratio(Metre(Unit), Second(Unit)))),
1025            parse_item("1").with_meaning(Volume(Litre(Milli))),
1026            parse_item("1").with_meaning(Mass(Gram(Micro))),
1027            parse_item("1").with_meaning(Temp(Kelvin(Unit))),
1028            parse_item("1").with_meaning(Data(Byte(Mega))),
1029        ];
1030        let expected_undos = vec![
1031            create_undo(1, vec![], vec!["1", "second"]),
1032            create_undo(1, vec![], vec!["1", "kilometre"]),
1033            create_undo(1, vec![], vec!["1", "square-metre"]),
1034            create_undo(1, vec![], vec!["1", "cubic-metre"]),
1035            create_undo(1, vec![], vec!["1", "metre/second"]),
1036            create_undo(1, vec![], vec!["1", "millilitre"]),
1037            create_undo(1, vec![], vec!["1", "microgram"]),
1038            create_undo(1, vec![], vec!["1", "kelvin"]),
1039            create_undo(1, vec![], vec!["1", "megabyte"]),
1040        ];
1041        let expected_redos = vec![];
1042        let mut engine = create_engine();
1043        let mut writer = BufferWriter::new();
1044        let mut stack = ValueStack::new(Vec::new());
1045        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 second").is_ok());
1046        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 kilometre").is_ok());
1047        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 square-metre").is_ok());
1048        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 cubic-metre").is_ok());
1049        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 metre/second").is_ok());
1050        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 millilitre").is_ok());
1051        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 microgram").is_ok());
1052        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 kelvin").is_ok());
1053        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 megabyte").is_ok());
1054        assert_eq!(stack.items, expected_items);
1055        assert_eq!(engine.undos, expected_undos);
1056        assert_eq!(engine.redos, expected_redos);
1057        assert_eq!(writer.buffer, "");
1058    }
1059
1060    #[test]
1061    fn test_invalid_cast_fails_cleanly() {
1062        let expected_items = vec![];
1063        let expected_undos = vec![];
1064        let expected_redos = vec![];
1065        let mut engine = create_engine();
1066        let mut writer = BufferWriter::new();
1067        let mut stack = ValueStack::new(Vec::new());
1068        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 km ug").is_err());
1069        assert_eq!(stack.items, expected_items);
1070        assert_eq!(engine.undos, expected_undos);
1071        assert_eq!(engine.redos, expected_redos);
1072        assert_eq!(writer.buffer, "Unsupported cast: kilometre to microgram\n");
1073    }
1074
1075    // UNKNOWN OPERATIONS
1076
1077    #[test]
1078    fn test_unknown_operation_fails_cleanly() {
1079        let expected_items = parse_items(vec!["1", "2", "3"]);
1080        let expected_undos = vec![
1081            create_undo(3, vec![], vec!["1", "2", "3"]),
1082        ];
1083        let expected_redos = vec![];
1084        let mut engine = create_engine();
1085        let mut writer = BufferWriter::new();
1086        let mut stack = ValueStack::new(Vec::new());
1087        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
1088        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 xyz 999").is_err());
1089        assert_eq!(stack.items, expected_items);
1090        assert_eq!(engine.undos, expected_undos);
1091        assert_eq!(engine.redos, expected_redos);
1092        assert_eq!(writer.buffer, "Invalid number or keyword: xyz\n");
1093    }
1094
1095    // NULLARY OPERATIONS
1096
1097    #[test]
1098    fn test_nullary_operation_modifies_stack() {
1099        let expected_undos = vec![
1100            create_undo(1, vec![], vec!["now"]),
1101        ];
1102        let expected_redos = vec![];
1103        let mut engine = create_engine();
1104        let mut writer = BufferWriter::new();
1105        let mut stack = ValueStack::new(Vec::new());
1106        assert!(parse_line(&mut engine, &mut writer, &mut stack, "now").is_ok());
1107        assert_eq!(stack.wrapped_len(), 1);
1108        assert_eq!(engine.undos, expected_undos);
1109        assert_eq!(engine.redos, expected_redos);
1110        assert_eq!(writer.buffer, "");
1111    }
1112
1113    // UNARY OPERATIONS
1114
1115    #[test]
1116    fn test_unary_operation_modifies_stack() {
1117        let expected_items = parse_items(vec!["1", "-2"]);
1118        let expected_undos = vec![
1119            create_undo(3, vec![], vec!["1", "2", "3"]),
1120            create_undo(1, vec!["2", "3"], vec!["pop", "neg"]),
1121        ];
1122        let expected_redos = vec![];
1123        let mut engine = create_engine();
1124        let mut writer = BufferWriter::new();
1125        let mut stack = ValueStack::new(Vec::new());
1126        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
1127        assert!(parse_line(&mut engine, &mut writer, &mut stack, "pop neg").is_ok());
1128        assert_eq!(stack.items, expected_items);
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_unary_operation_fails_cleanly() {
1136        let expected_items = parse_items(vec!["1", "2", "3"]);
1137        let expected_undos = vec![
1138            create_undo(3, vec![], vec!["1", "2", "3"]),
1139        ];
1140        let expected_redos = vec![];
1141        let mut engine = create_engine();
1142        let mut writer = BufferWriter::new();
1143        let mut stack = ValueStack::new(Vec::new());
1144        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
1145        assert!(parse_line(&mut engine, &mut writer, &mut stack, "pop pop pop neg 999").is_err());
1146        assert_eq!(stack.items, expected_items);
1147        assert_eq!(engine.undos, expected_undos);
1148        assert_eq!(engine.redos, expected_redos);
1149        assert_eq!(writer.buffer, "Not enough values on stack\n");
1150    }
1151
1152    // BINARY OPERATIONS
1153
1154    #[test]
1155    fn test_binary_operation_modifies_stack() {
1156        let expected_items = parse_items(vec!["1", "5"]);
1157        let expected_undos = vec![
1158            create_undo(3, vec![], vec!["1", "2", "3"]),
1159            create_undo(1, vec!["2", "3"], vec!["add"]),
1160        ];
1161        let expected_redos = vec![];
1162        let mut engine = create_engine();
1163        let mut writer = BufferWriter::new();
1164        let mut stack = ValueStack::new(Vec::new());
1165        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
1166        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1167        assert_eq!(stack.items, expected_items);
1168        assert_eq!(engine.undos, expected_undos);
1169        assert_eq!(engine.redos, expected_redos);
1170        assert_eq!(writer.buffer, "");
1171    }
1172
1173    #[test]
1174    fn test_binary_operation_fails_cleanly() {
1175        let expected_items = parse_items(vec!["1", "2", "3"]);
1176        let expected_undos = vec![
1177            create_undo(3, vec![], vec!["1", "2", "3"]),
1178        ];
1179        let expected_redos = vec![];
1180        let mut engine = create_engine();
1181        let mut writer = BufferWriter::new();
1182        let mut stack = ValueStack::new(Vec::new());
1183        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
1184        assert!(parse_line(&mut engine, &mut writer, &mut stack, "pop pop add 999").is_err());
1185        assert_eq!(stack.items, expected_items);
1186        assert_eq!(engine.undos, expected_undos);
1187        assert_eq!(engine.redos, expected_redos);
1188        assert_eq!(writer.buffer, "Not enough values on stack\n");
1189    }
1190
1191    // SERIES OPERATIONS
1192
1193    #[test]
1194    fn test_series_to_value_operation_modifies_stack() {
1195        let expected_items = parse_items(vec!["6"]);
1196        let expected_undos = vec![
1197            create_undo(3, vec![], vec!["1", "2", "3"]),
1198            create_undo(1, vec!["1", "2", "3"], vec!["sum"]),
1199        ];
1200        let expected_redos = vec![];
1201        let mut engine = create_engine();
1202        let mut writer = BufferWriter::new();
1203        let mut stack = ValueStack::new(Vec::new());
1204        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
1205        assert!(parse_line(&mut engine, &mut writer, &mut stack, "sum").is_ok());
1206        assert_eq!(stack.items, expected_items);
1207        assert_eq!(engine.undos, expected_undos);
1208        assert_eq!(engine.redos, expected_redos);
1209        assert_eq!(writer.buffer, "");
1210    }
1211
1212    #[test]
1213    fn test_binary_to_series_operation_modifies_stack() {
1214        let expected_items = parse_items(vec!["[1 2 3 4 5]"]);
1215        let expected_undos = vec![
1216            create_undo(2, vec![], vec!["1", "5"]),
1217            create_undo(1, vec!["1", "5"], vec!["seq"]),
1218        ];
1219        let expected_redos = vec![];
1220        let mut engine = create_engine();
1221        let mut writer = BufferWriter::new();
1222        let mut stack = ValueStack::new(Vec::new());
1223        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 5").is_ok());
1224        assert!(parse_line(&mut engine, &mut writer, &mut stack, "seq").is_ok());
1225        assert_eq!(stack.items, expected_items);
1226        assert_eq!(engine.undos, expected_undos);
1227        assert_eq!(engine.redos, expected_redos);
1228        assert_eq!(writer.buffer, "");
1229    }
1230
1231    #[test]
1232    fn test_binary_to_series_operation_fails_cleanly() {
1233        let expected_items = parse_items(vec!["1", "5"]);
1234        let expected_undos = vec![
1235            create_undo(2, vec![], vec!["1", "5"]),
1236        ];
1237        let expected_redos = vec![];
1238        let mut engine = create_engine();
1239        let mut writer = BufferWriter::new();
1240        let mut stack = ValueStack::new(Vec::new());
1241        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 5").is_ok());
1242        assert!(parse_line(&mut engine, &mut writer, &mut stack, "pop seq 999").is_err());
1243        assert_eq!(stack.items, expected_items);
1244        assert_eq!(engine.undos, expected_undos);
1245        assert_eq!(engine.redos, expected_redos);
1246        assert_eq!(writer.buffer, "Not enough values on stack\n");
1247    }
1248
1249    #[test]
1250    fn test_series_to_series_operation_modifies_stack() {
1251        let expected_items = parse_items(vec!["5", "4", "3", "2", "1"]);
1252        let expected_undos = vec![
1253            create_undo(5, vec![], vec!["1", "2", "3", "4", "5"]),
1254            create_undo(5, vec!["1", "2", "3", "4", "5"], vec!["rev"]),
1255        ];
1256        let expected_redos = vec![];
1257        let mut engine = create_engine();
1258        let mut writer = BufferWriter::new();
1259        let mut stack = ValueStack::new(Vec::new());
1260        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3 4 5").is_ok());
1261        assert!(parse_line(&mut engine, &mut writer, &mut stack, "rev").is_ok());
1262        assert_eq!(stack.items, expected_items);
1263        assert_eq!(engine.undos, expected_undos);
1264        assert_eq!(engine.redos, expected_redos);
1265        assert_eq!(writer.buffer, "");
1266    }
1267
1268    #[test]
1269    fn test_series_to_series_operation_modifies_series() {
1270        let expected_items = parse_items(vec!["1", "2", "[5 4 3]"]);
1271        let expected_undos = vec![
1272            create_undo(3, vec![], vec!["1", "2", "3", "5", "seq"]),
1273            create_undo(1, vec!["[3 4 5]"], vec!["rev"]),
1274        ];
1275        let expected_redos = vec![];
1276        let mut engine = create_engine();
1277        let mut writer = BufferWriter::new();
1278        let mut stack = ValueStack::new(Vec::new());
1279        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3 5 seq").is_ok());
1280        assert!(parse_line(&mut engine, &mut writer, &mut stack, "rev").is_ok());
1281        assert_eq!(stack.items, expected_items);
1282        assert_eq!(engine.undos, expected_undos);
1283        assert_eq!(engine.redos, expected_redos);
1284        assert_eq!(writer.buffer, "");
1285    }
1286
1287    // APPLY OPERATIONS
1288
1289    #[test]
1290    fn test_apply_unary_operation_modifies_empty() {
1291        let expected_items = vec![];
1292        let expected_undos = vec![];
1293        let expected_redos = vec![];
1294        let mut engine = create_engine();
1295        let mut writer = BufferWriter::new();
1296        let mut stack = ValueStack::new(Vec::new());
1297        assert!(parse_line(&mut engine, &mut writer, &mut stack, "apply 2 pow").is_ok());
1298        assert_eq!(stack.items, expected_items);
1299        assert_eq!(engine.undos, expected_undos);
1300        assert_eq!(engine.redos, expected_redos);
1301        assert_eq!(writer.buffer, "");
1302    }
1303
1304    #[test]
1305    fn test_apply_unary_operation_modifies_stack() {
1306        let expected_items = parse_items(vec!["1", "4", "9", "16", "25", "36"]);
1307        let expected_undos = vec![
1308            create_undo(3, vec![], vec!["1", "2", "5", "seq", "6"]),
1309            create_undo(6, vec!["1", "[2 3 4 5]", "6"], vec!["apply", "2", "pow"]),
1310        ];
1311        let expected_redos = vec![];
1312        let mut engine = create_engine();
1313        let mut writer = BufferWriter::new();
1314        let mut stack = ValueStack::new(Vec::new());
1315        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 5 seq 6").is_ok());
1316        assert!(parse_line(&mut engine, &mut writer, &mut stack, "apply 2 pow").is_ok());
1317        assert_eq!(stack.items, expected_items);
1318        assert_eq!(engine.undos, expected_undos);
1319        assert_eq!(engine.redos, expected_redos);
1320        assert_eq!(writer.buffer, "");
1321    }
1322
1323    #[test]
1324    fn test_apply_unary_operation_modifies_series() {
1325        let expected_items = parse_items(vec!["1", "2", "3", "[16 25 36]"]);
1326        let expected_undos = vec![
1327            create_undo(4, vec![], vec!["1", "2", "3", "4", "6", "seq"]),
1328            create_undo(1, vec!["[4 5 6]"], vec!["apply", "2", "pow"]),
1329        ];
1330        let expected_redos = vec![];
1331        let mut engine = create_engine();
1332        let mut writer = BufferWriter::new();
1333        let mut stack = ValueStack::new(Vec::new());
1334        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3 4 6 seq").is_ok());
1335        assert!(parse_line(&mut engine, &mut writer, &mut stack, "apply 2 pow").is_ok());
1336        assert_eq!(stack.items, expected_items);
1337        assert_eq!(engine.undos, expected_undos);
1338        assert_eq!(engine.redos, expected_redos);
1339        assert_eq!(writer.buffer, "");
1340    }
1341
1342    #[test]
1343    fn test_apply_nullary_operation_fails_cleanly() {
1344        let expected_items = vec![];
1345        let expected_undos = vec![];
1346        let expected_redos = vec![];
1347        let mut engine = create_engine();
1348        let mut writer = BufferWriter::new();
1349        let mut stack = ValueStack::new(Vec::new());
1350        assert!(parse_line(&mut engine, &mut writer, &mut stack, "apply now").is_err());
1351        assert_eq!(stack.items, expected_items);
1352        assert_eq!(engine.undos, expected_undos);
1353        assert_eq!(engine.redos, expected_redos);
1354        assert_eq!(writer.buffer, "Unsupported apply: - to N\n");
1355    }
1356
1357    #[test]
1358    fn test_apply_binary_operation_fails_cleanly() {
1359        let expected_items = vec![];
1360        let expected_undos = vec![];
1361        let expected_redos = vec![];
1362        let mut engine = create_engine();
1363        let mut writer = BufferWriter::new();
1364        let mut stack = ValueStack::new(Vec::new());
1365        assert!(parse_line(&mut engine, &mut writer, &mut stack, "apply add").is_err());
1366        assert_eq!(stack.items, expected_items);
1367        assert_eq!(engine.undos, expected_undos);
1368        assert_eq!(engine.redos, expected_redos);
1369        assert_eq!(writer.buffer, "Unsupported apply: N N to N\n");
1370    }
1371
1372    #[test]
1373    fn test_apply_series_operation_fails_cleanly() {
1374        let expected_items = vec![];
1375        let expected_undos = vec![];
1376        let expected_redos = vec![];
1377        let mut engine = create_engine();
1378        let mut writer = BufferWriter::new();
1379        let mut stack = ValueStack::new(Vec::new());
1380        assert!(parse_line(&mut engine, &mut writer, &mut stack, "apply sum").is_err());
1381        assert_eq!(stack.items, expected_items);
1382        assert_eq!(engine.undos, expected_undos);
1383        assert_eq!(engine.redos, expected_redos);
1384        assert_eq!(writer.buffer, "Unsupported apply: * to N\n");
1385    }
1386
1387    // CAST OPERATIONS
1388
1389    #[test]
1390    fn test_cast_modifies_current_line() {
1391        let expected_items = vec![
1392            parse_item("1"),
1393            parse_item("2"),
1394            parse_item("3"),
1395            parse_item("5025.678").with_meaning(Delta(HMS)),
1396        ];
1397        let expected_undos = vec![
1398            create_undo(2, vec![], vec!["1", "2"]),
1399            create_undo(2, vec![], vec!["3", "5025.678", "delta"]),
1400        ];
1401        let expected_redos = vec![];
1402        let mut engine = create_engine();
1403        let mut writer = BufferWriter::new();
1404        let mut stack = ValueStack::new(Vec::new());
1405        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2").is_ok());
1406        assert!(parse_line(&mut engine, &mut writer, &mut stack, "3 5025.678 delta").is_ok());
1407        assert_eq!(stack.items, expected_items);
1408        assert_eq!(engine.undos, expected_undos);
1409        assert_eq!(engine.redos, expected_redos);
1410        assert_eq!(writer.buffer, "");
1411    }
1412
1413    #[test]
1414    fn test_cast_modifies_previous_line() {
1415        let expected_items = vec![
1416            parse_item("1"),
1417            parse_item("2"),
1418            parse_item("3"),
1419            parse_item("5025.678").with_meaning(Delta(HMS)),
1420        ];
1421        let expected_undos = vec![
1422            create_undo(4, vec![], vec!["1", "2", "3", "5025.678"]),
1423            create_undo(1, vec!["5025.678"], vec!["delta"]),
1424        ];
1425        let expected_redos = vec![];
1426        let mut engine = create_engine();
1427        let mut writer = BufferWriter::new();
1428        let mut stack = ValueStack::new(Vec::new());
1429        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3 5025.678").is_ok());
1430        assert!(parse_line(&mut engine, &mut writer, &mut stack, "delta").is_ok());
1431        assert_eq!(stack.items, expected_items);
1432        assert_eq!(engine.undos, expected_undos);
1433        assert_eq!(engine.redos, expected_redos);
1434        assert_eq!(writer.buffer, "");
1435    }
1436
1437    #[test]
1438    fn test_cast_fails_cleanly() {
1439        let expected_items = vec![];
1440        let expected_undos = vec![];
1441        let expected_redos = vec![];
1442        let mut engine = create_engine();
1443        let mut writer = BufferWriter::new();
1444        let mut stack = ValueStack::new(Vec::new());
1445        assert!(parse_line(&mut engine, &mut writer, &mut stack, "delta").is_err());
1446        assert_eq!(stack.items, expected_items);
1447        assert_eq!(engine.undos, expected_undos);
1448        assert_eq!(engine.redos, expected_redos);
1449        assert_eq!(writer.buffer, "Not enough values on stack\n");
1450    }
1451
1452    // FLAT OPERATIONS
1453
1454    #[test]
1455    fn test_flat_operation_leaves_stack_no_series() {
1456        let expected_items = parse_items(vec!["1", "2", "3", "4", "5"]);
1457        let expected_undos = vec![
1458            create_undo(5, vec![], vec!["1", "2", "3", "4", "5"]),
1459        ];
1460        let expected_redos = vec![];
1461        let mut engine = create_engine();
1462        let mut writer = BufferWriter::new();
1463        let mut stack = ValueStack::new(Vec::new());
1464        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3 4 5").is_ok());
1465        assert!(parse_line(&mut engine, &mut writer, &mut stack, "flat").is_ok());
1466        assert_eq!(stack.items, expected_items);
1467        assert_eq!(engine.undos, expected_undos);
1468        assert_eq!(engine.redos, expected_redos);
1469        assert_eq!(writer.buffer, "");
1470    }
1471
1472    #[test]
1473    fn test_flat_operation_modifies_stack_with_series() {
1474        let expected_items = parse_items(vec!["1", "2", "3", "4", "5", "6", "7", "8"]);
1475        let expected_undos = vec![
1476            create_undo(5, vec![], vec!["1", "2", "3", "seq", "4", "5", "7", "seq", "8"]),
1477            create_undo(8, vec!["1", "[2 3]", "4", "[5 6 7]", "8"], vec!["flat"]),
1478        ];
1479        let expected_redos = vec![];
1480        let mut engine = create_engine();
1481        let mut writer = BufferWriter::new();
1482        let mut stack = ValueStack::new(Vec::new());
1483        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3 seq 4 5 7 seq 8").is_ok());
1484        assert!(parse_line(&mut engine, &mut writer, &mut stack, "flat").is_ok());
1485        assert_eq!(stack.items, expected_items);
1486        assert_eq!(engine.undos, expected_undos);
1487        assert_eq!(engine.redos, expected_redos);
1488        assert_eq!(writer.buffer, "");
1489    }
1490
1491    // CLEAR OPERATIONS
1492
1493    #[test]
1494    fn test_clear_operation_modifies_stack() {
1495        let expected_items = vec![];
1496        let expected_undos = vec![
1497            create_undo(3, vec![], vec!["1", "2", "3"]),
1498            create_undo(0, vec!["1", "2", "3"], vec!["clear"]),
1499        ];
1500        let expected_redos = vec![];
1501        let mut engine = create_engine();
1502        let mut writer = BufferWriter::new();
1503        let mut stack = ValueStack::new(Vec::new());
1504        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
1505        assert!(parse_line(&mut engine, &mut writer, &mut stack, "clear").is_ok());
1506        assert_eq!(stack.items, expected_items);
1507        assert_eq!(engine.undos, expected_undos);
1508        assert_eq!(engine.redos, expected_redos);
1509        assert_eq!(writer.buffer, "");
1510    }
1511
1512    // POP OPERATIONS
1513
1514    #[test]
1515    fn test_pop_operation_modifies_stack() {
1516        let expected_items = parse_items(vec!["1", "2"]);
1517        let expected_undos = vec![
1518            create_undo(3, vec![], vec!["1", "2", "3"]),
1519            create_undo(0, vec!["3"], vec!["pop"]),
1520        ];
1521        let expected_redos = vec![];
1522        let mut engine = create_engine();
1523        let mut writer = BufferWriter::new();
1524        let mut stack = ValueStack::new(Vec::new());
1525        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
1526        assert!(parse_line(&mut engine, &mut writer, &mut stack, "pop").is_ok());
1527        assert_eq!(stack.items, expected_items);
1528        assert_eq!(engine.undos, expected_undos);
1529        assert_eq!(engine.redos, expected_redos);
1530        assert_eq!(writer.buffer, "");
1531    }
1532
1533    #[test]
1534    fn test_pop_operation_fails_cleanly() {
1535        let expected_items = parse_items(vec!["1", "2", "3"]);
1536        let expected_undos = vec![
1537            create_undo(3, vec![], vec!["1", "2", "3"]),
1538        ];
1539        let expected_redos = vec![];
1540        let mut engine = create_engine();
1541        let mut writer = BufferWriter::new();
1542        let mut stack = ValueStack::new(Vec::new());
1543        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
1544        assert!(parse_line(&mut engine, &mut writer, &mut stack, "pop pop pop pop 999").is_err());
1545        assert_eq!(stack.items, expected_items);
1546        assert_eq!(engine.undos, expected_undos);
1547        assert_eq!(engine.redos, expected_redos);
1548        assert_eq!(writer.buffer, "Not enough values on stack\n");
1549    }
1550
1551    // DUP OPERATIONS
1552
1553    #[test]
1554    fn test_dup_operation_modifies_stack() {
1555        let expected_items = vec![
1556            parse_item("1"),
1557            parse_item("2"),
1558            parse_item("3").with_comment("comment").with_variable("x"),
1559            parse_item("3").with_comment("comment"),
1560        ];
1561        let expected_undos = vec![
1562            create_undo(3, vec![], vec!["1", "2", "3"]),
1563            create_undo(1, vec![], vec!["dup"]),
1564        ];
1565        let expected_redos = vec![];
1566        let mut engine = create_engine();
1567        let mut writer = BufferWriter::new();
1568        let mut stack = ValueStack::new(Vec::new());
1569        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3 = x # comment").is_ok());
1570        assert!(parse_line(&mut engine, &mut writer, &mut stack, "dup").is_ok());
1571        assert_eq!(stack.items, expected_items);
1572        assert_eq!(engine.undos, expected_undos);
1573        assert_eq!(engine.redos, expected_redos);
1574        assert_eq!(writer.buffer, "");
1575    }
1576
1577    #[test]
1578    fn test_dup_operation_fails_cleanly() {
1579        let expected_items = vec![
1580            parse_item("1"),
1581            parse_item("2"),
1582            parse_item("3").with_comment("comment").with_variable("x"),
1583        ];
1584        let expected_undos = vec![
1585            create_undo(3, vec![], vec!["1", "2", "3"]),
1586        ];
1587        let expected_redos = vec![];
1588        let mut engine = create_engine();
1589        let mut writer = BufferWriter::new();
1590        let mut stack = ValueStack::new(Vec::new());
1591        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3 = x # comment").is_ok());
1592        assert!(parse_line(&mut engine, &mut writer, &mut stack, "pop pop pop dup 999").is_err());
1593        assert_eq!(stack.items, expected_items);
1594        assert_eq!(engine.undos, expected_undos);
1595        assert_eq!(engine.redos, expected_redos);
1596        assert_eq!(writer.buffer, "Not enough values on stack\n");
1597    }
1598
1599    // SWAP OPERATIONS
1600
1601    #[test]
1602    fn test_swap_operation_modifies_stack() {
1603        let expected_items = parse_items(vec!["1", "3", "2"]);
1604        let expected_undos = vec![
1605            create_undo(3, vec![], vec!["1", "2", "3"]),
1606            create_undo(2, vec!["2", "3"], vec!["swap"]),
1607        ];
1608        let expected_redos = vec![];
1609        let mut engine = create_engine();
1610        let mut writer = BufferWriter::new();
1611        let mut stack = ValueStack::new(Vec::new());
1612        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
1613        assert!(parse_line(&mut engine, &mut writer, &mut stack, "swap").is_ok());
1614        assert_eq!(stack.items, expected_items);
1615        assert_eq!(engine.undos, expected_undos);
1616        assert_eq!(engine.redos, expected_redos);
1617        assert_eq!(writer.buffer, "");
1618    }
1619
1620    #[test]
1621    fn test_swap_operation_fails_cleanly() {
1622        let expected_items = parse_items(vec!["1", "2", "3"]);
1623        let expected_undos = vec![
1624            create_undo(3, vec![], vec!["1", "2", "3"]),
1625        ];
1626        let expected_redos = vec![];
1627        let mut engine = create_engine();
1628        let mut writer = BufferWriter::new();
1629        let mut stack = ValueStack::new(Vec::new());
1630        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
1631        assert!(parse_line(&mut engine, &mut writer, &mut stack, "pop pop swap 999").is_err());
1632        assert_eq!(stack.items, expected_items);
1633        assert_eq!(engine.undos, expected_undos);
1634        assert_eq!(engine.redos, expected_redos);
1635        assert_eq!(writer.buffer, "Not enough values on stack\n");
1636    }
1637
1638    // CUT OPERATIONS
1639
1640    #[test]
1641    fn test_cut_operation_copies_value() {
1642        let expected_items = vec![];
1643        let expected_undos = vec![
1644            create_undo(1, vec![], vec!["42"]),
1645            create_undo(0, vec!["42"], vec!["cut"]),
1646        ];
1647        let expected_redos = vec![];
1648        let mut engine = create_engine();
1649        let mut writer = BufferWriter::new();
1650        let mut stack = ValueStack::new(Vec::new());
1651        assert!(parse_line(&mut engine, &mut writer, &mut stack, "42").is_ok());
1652        assert!(parse_line(&mut engine, &mut writer, &mut stack, "cut").is_ok());
1653        assert_eq!(stack.items, expected_items);
1654        assert_eq!(engine.undos, expected_undos);
1655        assert_eq!(engine.redos, expected_redos);
1656        assert_eq!(engine.clip, Some(parse_ref("42")));
1657        assert_eq!(writer.buffer, "");
1658    }
1659
1660    #[test]
1661    fn test_cut_operation_fails_cleanly() {
1662        let expected_items = vec![];
1663        let expected_undos = vec![];
1664        let expected_redos = vec![];
1665        let mut engine = create_engine();
1666        let mut writer = BufferWriter::new();
1667        let mut stack = ValueStack::new(Vec::new());
1668        assert!(parse_line(&mut engine, &mut writer, &mut stack, "cut").is_err());
1669        assert_eq!(stack.items, expected_items);
1670        assert_eq!(engine.undos, expected_undos);
1671        assert_eq!(engine.redos, expected_redos);
1672        assert_eq!(engine.clip, None);
1673        assert_eq!(writer.buffer, "Not enough values on stack\n");
1674    }
1675
1676    // COPY OPERATIONS
1677
1678    #[test]
1679    fn test_copy_operation_copies_value() {
1680        let expected_items = vec![
1681            parse_item("42").with_comment("comment").with_variable("x"),
1682        ];
1683        let expected_undos = vec![
1684            create_undo(1, vec![], vec!["42"]),
1685        ];
1686        let expected_redos = vec![];
1687        let mut engine = create_engine();
1688        let mut writer = BufferWriter::new();
1689        let mut stack = ValueStack::new(Vec::new());
1690        assert!(parse_line(&mut engine, &mut writer, &mut stack, "42 = x # comment").is_ok());
1691        assert!(parse_line(&mut engine, &mut writer, &mut stack, "copy").is_ok());
1692        assert_eq!(stack.items, expected_items);
1693        assert_eq!(engine.undos, expected_undos);
1694        assert_eq!(engine.redos, expected_redos);
1695        assert_eq!(engine.clip, Some(make_ref(parse_value("42").with_comment("comment"))));
1696        assert_eq!(writer.buffer, "");
1697    }
1698
1699    #[test]
1700    fn test_copy_operation_fails_cleanly() {
1701        let expected_items = vec![];
1702        let expected_undos = vec![];
1703        let expected_redos = vec![];
1704        let mut engine = create_engine();
1705        let mut writer = BufferWriter::new();
1706        let mut stack = ValueStack::new(Vec::new());
1707        assert!(parse_line(&mut engine, &mut writer, &mut stack, "copy").is_err());
1708        assert_eq!(stack.items, expected_items);
1709        assert_eq!(engine.undos, expected_undos);
1710        assert_eq!(engine.redos, expected_redos);
1711        assert_eq!(engine.clip, None);
1712        assert_eq!(writer.buffer, "Not enough values on stack\n");
1713    }
1714
1715    // PASTE OPERATIONS
1716
1717    #[test]
1718    fn test_paste_operation_copies_value() {
1719        let expected_items = parse_items(vec!["42", "42"]);
1720        let expected_undos = vec![
1721            create_undo(1, vec![], vec!["42"]),
1722            create_undo(1, vec![], vec!["paste"]),
1723        ];
1724        let expected_redos = vec![];
1725        let mut engine = create_engine();
1726        let mut writer = BufferWriter::new();
1727        let mut stack = ValueStack::new(Vec::new());
1728        assert!(parse_line(&mut engine, &mut writer, &mut stack, "42").is_ok());
1729        assert!(parse_line(&mut engine, &mut writer, &mut stack, "copy").is_ok());
1730        assert!(parse_line(&mut engine, &mut writer, &mut stack, "paste").is_ok());
1731        assert_eq!(stack.items, expected_items);
1732        assert_eq!(engine.undos, expected_undos);
1733        assert_eq!(engine.redos, expected_redos);
1734        assert_eq!(engine.clip, Some(parse_ref("42")));
1735        assert_eq!(writer.buffer, "");
1736    }
1737
1738    #[test]
1739    fn test_paste_operation_fails_cleanly() {
1740        let expected_items = parse_items(vec!["42"]);
1741        let expected_undos = vec![
1742            create_undo(1, vec![], vec!["42"]),
1743        ];
1744        let expected_redos = vec![];
1745        let mut engine = create_engine();
1746        let mut writer = BufferWriter::new();
1747        let mut stack = ValueStack::new(Vec::new());
1748        assert!(parse_line(&mut engine, &mut writer, &mut stack, "42").is_ok());
1749        assert!(parse_line(&mut engine, &mut writer, &mut stack, "paste").is_err());
1750        assert_eq!(stack.items, expected_items);
1751        assert_eq!(engine.undos, expected_undos);
1752        assert_eq!(engine.redos, expected_redos);
1753        assert_eq!(engine.clip, None);
1754        assert_eq!(writer.buffer, "No value on clipboard\n");
1755    }
1756
1757    // UNDO OPERATIONS
1758
1759    #[test]
1760    fn test_single_undo_resets_previous_line() {
1761        let expected_items = parse_items(vec!["4", "5", "6"]);
1762        let expected_undos = vec![
1763            create_undo(3, vec![], vec!["4", "5", "6"]),
1764        ];
1765        let expected_redos = vec![
1766            create_undo(2, vec!["11"], vec!["add"]),
1767        ];
1768        let mut engine = create_engine();
1769        let mut writer = BufferWriter::new();
1770        let mut stack = ValueStack::new(Vec::new());
1771        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
1772        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1773        assert!(parse_line(&mut engine, &mut writer, &mut stack, "undo").is_ok());
1774        assert_eq!(stack.items, expected_items);
1775        assert_eq!(engine.undos, expected_undos);
1776        assert_eq!(engine.redos, expected_redos);
1777        assert_eq!(writer.buffer, "");
1778    }
1779
1780    #[test]
1781    fn test_double_undo_resets_previous_lines() {
1782        let expected_items = vec![];
1783        let expected_undos = vec![];
1784        let expected_redos = vec![
1785            create_undo(2, vec!["11"], vec!["add"]),
1786            create_undo(0, vec!["4", "5", "6"], vec!["4", "5", "6"]),
1787        ];
1788        let mut engine = create_engine();
1789        let mut writer = BufferWriter::new();
1790        let mut stack = ValueStack::new(Vec::new());
1791        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
1792        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1793        assert!(parse_line(&mut engine, &mut writer, &mut stack, "undo undo").is_ok());
1794        assert_eq!(stack.items, expected_items);
1795        assert_eq!(engine.undos, expected_undos);
1796        assert_eq!(engine.redos, expected_redos);
1797        assert_eq!(writer.buffer, "");
1798    }
1799
1800    #[test]
1801    fn test_single_undo_with_suffix_resets_previous_line() {
1802        let expected_items = parse_items(vec!["4", "30"]);
1803        let expected_undos = vec![
1804            create_undo(3, vec![], vec!["4", "5", "6"]),
1805            create_undo(1, vec!["5", "6"], vec!["mul"]),
1806        ];
1807        let expected_redos = vec![];
1808        let mut engine = create_engine();
1809        let mut writer = BufferWriter::new();
1810        let mut stack = ValueStack::new(Vec::new());
1811        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
1812        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1813        assert!(parse_line(&mut engine, &mut writer, &mut stack, "undo mul").is_ok());
1814        assert_eq!(stack.items, expected_items);
1815        assert_eq!(engine.undos, expected_undos);
1816        assert_eq!(engine.redos, expected_redos);
1817        assert_eq!(writer.buffer, "");
1818    }
1819
1820    #[test]
1821    fn test_double_undo_with_suffix_resets_previous_lines() {
1822        let expected_items = parse_items(vec!["1", "6"]);
1823        let expected_undos = vec![
1824            create_undo(3, vec![], vec!["1", "2", "3"]),
1825            create_undo(1, vec!["2", "3"], vec!["mul"]),
1826        ];
1827        let expected_redos = vec![];
1828        let mut engine = create_engine();
1829        let mut writer = BufferWriter::new();
1830        let mut stack = ValueStack::new(Vec::new());
1831        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
1832        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
1833        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1834        assert!(parse_line(&mut engine, &mut writer, &mut stack, "undo undo mul").is_ok());
1835        assert_eq!(stack.items, expected_items);
1836        assert_eq!(engine.undos, expected_undos);
1837        assert_eq!(engine.redos, expected_redos);
1838        assert_eq!(writer.buffer, "");
1839    }
1840
1841    #[test]
1842    fn test_single_undo_with_prefix_resets_current_line() {
1843        let expected_items = parse_items(vec!["4", "11"]);
1844        let expected_undos = vec![
1845            create_undo(3, vec![], vec!["4", "5", "6"]),
1846            create_undo(1, vec!["5", "6"], vec!["add"]),
1847        ];
1848        let expected_redos = vec![
1849            create_undo(2, vec!["15"], vec!["add"]),
1850        ];
1851        let mut engine = create_engine();
1852        let mut writer = BufferWriter::new();
1853        let mut stack = ValueStack::new(Vec::new());
1854        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
1855        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1856        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add undo").is_ok());
1857        assert_eq!(stack.items, expected_items);
1858        assert_eq!(engine.undos, expected_undos);
1859        assert_eq!(engine.redos, expected_redos);
1860        assert_eq!(writer.buffer, "");
1861    }
1862
1863    #[test]
1864    fn test_double_undo_with_prefix_resets_current_and_previous_lines() {
1865        let expected_items = parse_items(vec!["4", "5", "6"]);
1866        let expected_undos = vec![
1867            create_undo(3, vec![], vec!["4", "5", "6"]),
1868        ];
1869        let expected_redos = vec![
1870            create_undo(2, vec!["15"], vec!["add"]),
1871            create_undo(2, vec!["11"], vec!["add"]),
1872        ];
1873        let mut engine = create_engine();
1874        let mut writer = BufferWriter::new();
1875        let mut stack = ValueStack::new(Vec::new());
1876        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
1877        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1878        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add undo undo").is_ok());
1879        assert_eq!(stack.items, expected_items);
1880        assert_eq!(engine.undos, expected_undos);
1881        assert_eq!(engine.redos, expected_redos);
1882        assert_eq!(writer.buffer, "");
1883    }
1884
1885    #[test]
1886    fn test_single_undo_with_prefix_and_suffix_resets_current_line() {
1887        let expected_items = parse_items(vec!["44"]);
1888        let expected_undos = vec![
1889            create_undo(3, vec![], vec!["4", "5", "6"]),
1890            create_undo(1, vec!["5", "6"], vec!["add"]),
1891            create_undo(1, vec!["4", "11"], vec!["mul"]),
1892        ];
1893        let expected_redos = vec![];
1894        let mut engine = create_engine();
1895        let mut writer = BufferWriter::new();
1896        let mut stack = ValueStack::new(Vec::new());
1897        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
1898        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1899        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add undo mul").is_ok());
1900        assert_eq!(stack.items, expected_items);
1901        assert_eq!(engine.undos, expected_undos);
1902        assert_eq!(engine.redos, expected_redos);
1903        assert_eq!(writer.buffer, "");
1904    }
1905
1906    #[test]
1907    fn test_double_undo_with_prefix_and_suffix_resets_current_and_previous_lines() {
1908        let expected_items = parse_items(vec!["4", "30"]);
1909        let expected_undos = vec![
1910            create_undo(3, vec![], vec!["4", "5", "6"]),
1911            create_undo(1, vec!["5", "6"], vec!["mul"]),
1912        ];
1913        let expected_redos = vec![];
1914        let mut engine = create_engine();
1915        let mut writer = BufferWriter::new();
1916        let mut stack = ValueStack::new(Vec::new());
1917        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
1918        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1919        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add undo undo mul").is_ok());
1920        assert_eq!(stack.items, expected_items);
1921        assert_eq!(engine.undos, expected_undos);
1922        assert_eq!(engine.redos, expected_redos);
1923        assert_eq!(writer.buffer, "");
1924    }
1925
1926    #[test]
1927    fn test_triple_undo_operation_fails_cleanly() {
1928        let expected_items = vec![];
1929        let expected_undos = vec![];
1930        let expected_redos = vec![
1931            create_undo(2, vec!["11"], vec!["add"]),
1932            create_undo(0, vec!["4", "5", "6"], vec!["4", "5", "6"]),
1933        ];
1934        let mut engine = create_engine();
1935        let mut writer = BufferWriter::new();
1936        let mut stack = ValueStack::new(Vec::new());
1937        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
1938        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1939        assert!(parse_line(&mut engine, &mut writer, &mut stack, "undo undo undo").is_err());
1940        assert_eq!(stack.items, expected_items);
1941        assert_eq!(engine.undos, expected_undos);
1942        assert_eq!(engine.redos, expected_redos);
1943        assert_eq!(writer.buffer, "Start of undo history\n");
1944    }
1945
1946    // REDO OPERATIONS
1947
1948    #[test]
1949    fn test_single_redo_operation_modifies_stack() {
1950        let expected_items = parse_items(vec!["4", "11"]);
1951        let expected_undos = vec![
1952            create_undo(3, vec![], vec!["4", "5", "6"]),
1953            create_undo(1, vec!["5", "6"], vec!["add"]),
1954        ];
1955        let expected_redos = vec![
1956            create_undo(2, vec!["15"], vec!["add"]),
1957        ];
1958        let mut engine = create_engine();
1959        let mut writer = BufferWriter::new();
1960        let mut stack = ValueStack::new(Vec::new());
1961        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
1962        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1963        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1964        assert!(parse_line(&mut engine, &mut writer, &mut stack, "undo undo").is_ok());
1965        assert!(parse_line(&mut engine, &mut writer, &mut stack, "redo").is_ok());
1966        assert_eq!(stack.items, expected_items);
1967        assert_eq!(engine.undos, expected_undos);
1968        assert_eq!(engine.redos, expected_redos);
1969        assert_eq!(writer.buffer, "");
1970    }
1971
1972    #[test]
1973    fn test_double_redo_operation_modifies_stack() {
1974        let expected_items = parse_items(vec!["15"]);
1975        let expected_undos = vec![
1976            create_undo(3, vec![], vec!["4", "5", "6"]),
1977            create_undo(1, vec!["5", "6"], vec!["add"]),
1978            create_undo(1, vec!["4", "11"], vec!["add"]),
1979        ];
1980        let expected_redos = vec![];
1981        let mut engine = create_engine();
1982        let mut writer = BufferWriter::new();
1983        let mut stack = ValueStack::new(Vec::new());
1984        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
1985        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1986        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
1987        assert!(parse_line(&mut engine, &mut writer, &mut stack, "undo undo").is_ok());
1988        assert!(parse_line(&mut engine, &mut writer, &mut stack, "redo redo").is_ok());
1989        assert_eq!(stack.items, expected_items);
1990        assert_eq!(engine.undos, expected_undos);
1991        assert_eq!(engine.redos, expected_redos);
1992        assert_eq!(writer.buffer, "");
1993    }
1994
1995    #[test]
1996    fn test_single_redo_operation_with_prefix_fails_cleanly() {
1997        let expected_items = parse_items(vec!["4", "5", "6"]);
1998        let expected_undos = vec![
1999            create_undo(3, vec![], vec!["4", "5", "6"]),
2000        ];
2001        let expected_redos = vec![
2002            create_undo(2, vec!["15"], vec!["add"]),
2003            create_undo(2, vec!["11"], vec!["add"]),
2004        ];
2005        let mut engine = create_engine();
2006        let mut writer = BufferWriter::new();
2007        let mut stack = ValueStack::new(Vec::new());
2008        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
2009        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
2010        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
2011        assert!(parse_line(&mut engine, &mut writer, &mut stack, "undo undo").is_ok());
2012        assert!(parse_line(&mut engine, &mut writer, &mut stack, "mul redo 999").is_err());
2013        assert_eq!(stack.items, expected_items);
2014        assert_eq!(engine.undos, expected_undos);
2015        assert_eq!(engine.redos, expected_redos);
2016        assert_eq!(writer.buffer, "End of undo history\n");
2017    }
2018
2019    #[test]
2020    fn test_triple_redo_operation_fails_cleanly() {
2021        let expected_items = parse_items(vec!["15"]);
2022        let expected_undos = vec![
2023            create_undo(3, vec![], vec!["4", "5", "6"]),
2024            create_undo(1, vec!["5", "6"], vec!["add"]),
2025            create_undo(1, vec!["4", "11"], vec!["add"]),
2026        ];
2027        let expected_redos = vec![];
2028        let mut engine = create_engine();
2029        let mut writer = BufferWriter::new();
2030        let mut stack = ValueStack::new(Vec::new());
2031        assert!(parse_line(&mut engine, &mut writer, &mut stack, "4 5 6").is_ok());
2032        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
2033        assert!(parse_line(&mut engine, &mut writer, &mut stack, "add").is_ok());
2034        assert!(parse_line(&mut engine, &mut writer, &mut stack, "undo undo").is_ok());
2035        assert!(parse_line(&mut engine, &mut writer, &mut stack, "redo redo redo 999").is_err());
2036        assert_eq!(stack.items, expected_items);
2037        assert_eq!(engine.undos, expected_undos);
2038        assert_eq!(engine.redos, expected_redos);
2039        assert_eq!(writer.buffer, "End of undo history\n");
2040    }
2041
2042    // VARIABLE ASSIGNMENT
2043
2044    #[test]
2045    fn test_variable_not_assigned_by_default() {
2046        let expected_items = vec![
2047            parse_item("1"),
2048            parse_item("2"),
2049            parse_item("3"),
2050        ];
2051        let expected_variables = HashMap::new();
2052        let mut engine = create_engine();
2053        let mut writer = BufferWriter::new();
2054        let mut stack = ValueStack::new(Vec::new());
2055        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
2056        assert_eq!(stack.items, expected_items);
2057        assert_eq!(engine.interface.borrow().get_variables(), &expected_variables);
2058    }
2059
2060    #[test]
2061    fn test_variable_is_assigned_to_new_entry() {
2062        let expected_items = vec![
2063            parse_item("1"),
2064            parse_item("2").with_variable("foo"),
2065            parse_item("3"),
2066        ];
2067        let expected_variables = HashMap::from([
2068            (String::from("foo"), make_ref(parse_value("2").with_variable("foo"))),
2069        ]);
2070        let mut engine = create_engine();
2071        let mut writer = BufferWriter::new();
2072        let mut stack = ValueStack::new(Vec::new());
2073        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2").is_ok());
2074        assert!(parse_line(&mut engine, &mut writer, &mut stack, "set foo").is_ok());
2075        assert!(parse_line(&mut engine, &mut writer, &mut stack, "3").is_ok());
2076        assert_eq!(stack.items, expected_items);
2077        assert_eq!(engine.interface.borrow().get_variables(), &expected_variables);
2078    }
2079
2080    #[test]
2081    fn test_variable_is_reassigned_to_new_entry() {
2082        let expected_items = vec![
2083            parse_item("1"),
2084            parse_item("2"),
2085            parse_item("3").with_variable("foo"),
2086        ];
2087        let expected_variables = HashMap::from([
2088            (String::from("foo"), make_ref(parse_value("3").with_variable("foo"))),
2089        ]);
2090        let mut engine = create_engine();
2091        let mut writer = BufferWriter::new();
2092        let mut stack = ValueStack::new(Vec::new());
2093        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2").is_ok());
2094        assert!(parse_line(&mut engine, &mut writer, &mut stack, "set foo").is_ok());
2095        assert!(parse_line(&mut engine, &mut writer, &mut stack, "3").is_ok());
2096        assert!(parse_line(&mut engine, &mut writer, &mut stack, "set foo").is_ok());
2097        assert_eq!(stack.items, expected_items);
2098        assert_eq!(engine.interface.borrow().get_variables(), &expected_variables);
2099    }
2100
2101    #[test]
2102    fn test_variable_is_replaced_with_same_name() {
2103        let expected_items = vec![
2104            parse_item("1"),
2105            parse_item("2"),
2106            parse_item("3").with_variable("foo"),
2107        ];
2108        let expected_variables = HashMap::from([
2109            (String::from("foo"), make_ref(parse_value("3").with_variable("foo"))),
2110        ]);
2111        let mut engine = create_engine();
2112        let mut writer = BufferWriter::new();
2113        let mut stack = ValueStack::new(Vec::new());
2114        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
2115        assert!(parse_line(&mut engine, &mut writer, &mut stack, "set foo").is_ok());
2116        assert!(parse_line(&mut engine, &mut writer, &mut stack, "set foo").is_ok());
2117        assert_eq!(stack.items, expected_items);
2118        assert_eq!(engine.interface.borrow().get_variables(), &expected_variables);
2119    }
2120
2121    #[test]
2122    fn test_variable_is_replaced_with_new_name() {
2123        let expected_items = vec![
2124            parse_item("1"),
2125            parse_item("2"),
2126            parse_item("3").with_variable("bar"),
2127        ];
2128        let expected_variables = HashMap::from([
2129            (String::from("bar"), make_ref(parse_value("3").with_variable("bar"))),
2130        ]);
2131        let mut engine = create_engine();
2132        let mut writer = BufferWriter::new();
2133        let mut stack = ValueStack::new(Vec::new());
2134        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 2 3").is_ok());
2135        assert!(parse_line(&mut engine, &mut writer, &mut stack, "set foo").is_ok());
2136        assert!(parse_line(&mut engine, &mut writer, &mut stack, "set bar").is_ok());
2137        assert_eq!(stack.items, expected_items);
2138        assert_eq!(engine.interface.borrow().get_variables(), &expected_variables);
2139    }
2140
2141    #[test]
2142    fn test_variable_assignment_fails_cleanly() {
2143        let expected_variables = HashMap::new();
2144        let mut engine = create_engine();
2145        let mut writer = BufferWriter::new();
2146        let mut stack = ValueStack::new(Vec::new());
2147        assert!(parse_line(&mut engine, &mut writer, &mut stack, "set foo").is_err());
2148        assert_eq!(engine.interface.borrow().get_variables(), &expected_variables);
2149        assert_eq!(writer.buffer, "Not enough values on stack\n");
2150    }
2151
2152    #[test]
2153    fn test_variables_are_assigned_on_same_line() {
2154        let expected_items = vec![
2155            parse_item("1").with_variable("foo"),
2156            parse_item("2").with_variable("bar"),
2157            parse_item("3").with_variable("baz"),
2158        ];
2159        let expected_variables = HashMap::from([
2160            (String::from("foo"), make_ref(parse_value("1").with_variable("foo"))),
2161            (String::from("bar"), make_ref(parse_value("2").with_variable("bar"))),
2162            (String::from("baz"), make_ref(parse_value("3").with_variable("baz"))),
2163        ]);
2164        let mut engine = create_engine();
2165        let mut writer = BufferWriter::new();
2166        let mut stack = ValueStack::new(Vec::new());
2167        assert!(parse_line(&mut engine, &mut writer, &mut stack, "1 = foo 2 = bar 3 = baz").is_ok());
2168        assert_eq!(stack.items, expected_items);
2169        assert_eq!(engine.interface.borrow().get_variables(), &expected_variables);
2170    }
2171
2172    // TEXT OUTPUT
2173
2174    #[test]
2175    fn test_prints_error_on_invalid_decimal() {
2176        let mut engine = create_engine();
2177        let mut writer = BufferWriter::new();
2178        let mut stack = ValueStack::new(Vec::new());
2179        assert!(parse_line(&mut engine, &mut writer, &mut stack, "xyz").is_err());
2180        assert_eq!(writer.buffer, "Invalid number or keyword: xyz\n");
2181    }
2182
2183    #[test]
2184    fn test_prints_error_on_invalid_hexadecimal() {
2185        let mut engine = create_engine();
2186        let mut writer = BufferWriter::new();
2187        let mut stack = ValueStack::new(Vec::new());
2188        engine.context.borrow_mut().set_hex();
2189        assert!(parse_line(&mut engine, &mut writer, &mut stack, "xyz").is_err());
2190        assert_eq!(writer.buffer, "Invalid number or keyword: xyz\n");
2191    }
2192
2193    #[test]
2194    fn test_shows_history_from_start() {
2195        let expected = "\
2196<==
2197111
2198222
2199333 444 555
2200666 777
2201...
2202";
2203        let mut engine = create_engine();
2204        let mut writer = BufferWriter::new();
2205        engine.redos.insert(0, create_undo(0, vec![], vec!["111"]));
2206        engine.redos.insert(0, create_undo(0, vec![], vec!["222"]));
2207        engine.redos.insert(0, create_undo(0, vec![], vec!["333", "444", "555"]));
2208        engine.redos.insert(0, create_undo(0, vec![], vec!["666", "777"]));
2209        engine.redos.insert(0, create_undo(0, vec![], vec!["888"]));
2210        engine.redos.insert(0, create_undo(0, vec![], vec!["999"]));
2211        assert!(engine.limit_history(&mut writer, 4).is_ok());
2212        assert_eq!(writer.buffer, indent_multiline(expected));
2213    }
2214
2215    #[test]
2216    fn test_shows_history_with_lower_limit() {
2217        let expected = "\
2218...
2219222
2220333 444 555 <==
2221666 777
2222888
2223...
2224";
2225        let mut engine = create_engine();
2226        let mut writer = BufferWriter::new();
2227        engine.undos.push(create_undo(0, vec![], vec!["111"]));
2228        engine.undos.push(create_undo(0, vec![], vec!["222"]));
2229        engine.undos.push(create_undo(0, vec![], vec!["333", "444", "555"]));
2230        engine.redos.insert(0, create_undo(0, vec![], vec!["666", "777"]));
2231        engine.redos.insert(0, create_undo(0, vec![], vec!["888"]));
2232        engine.redos.insert(0, create_undo(0, vec![], vec!["999"]));
2233        assert!(engine.limit_history(&mut writer, 2).is_ok());
2234        assert_eq!(writer.buffer, indent_multiline(expected));
2235    }
2236
2237    #[test]
2238    fn test_shows_history_with_equal_limit() {
2239        let expected = "\
2240111
2241222
2242333 444 555 <==
2243666 777
2244888
2245999
2246";
2247        let mut engine = create_engine();
2248        let mut writer = BufferWriter::new();
2249        engine.undos.push(create_undo(0, vec![], vec!["111"]));
2250        engine.undos.push(create_undo(0, vec![], vec!["222"]));
2251        engine.undos.push(create_undo(0, vec![], vec!["333", "444", "555"]));
2252        engine.redos.insert(0, create_undo(0, vec![], vec!["666", "777"]));
2253        engine.redos.insert(0, create_undo(0, vec![], vec!["888"]));
2254        engine.redos.insert(0, create_undo(0, vec![], vec!["999"]));
2255        assert!(engine.limit_history(&mut writer, 3).is_ok());
2256        assert_eq!(writer.buffer, indent_multiline(expected));
2257    }
2258
2259    #[test]
2260    fn test_shows_history_with_higher_limit() {
2261        let expected = "\
2262111
2263222
2264333 444 555 <==
2265666 777
2266888
2267999
2268";
2269        let mut engine = create_engine();
2270        let mut writer = BufferWriter::new();
2271        engine.undos.push(create_undo(0, vec![], vec!["111"]));
2272        engine.undos.push(create_undo(0, vec![], vec!["222"]));
2273        engine.undos.push(create_undo(0, vec![], vec!["333", "444", "555"]));
2274        engine.redos.insert(0, create_undo(0, vec![], vec!["666", "777"]));
2275        engine.redos.insert(0, create_undo(0, vec![], vec!["888"]));
2276        engine.redos.insert(0, create_undo(0, vec![], vec!["999"]));
2277        assert!(engine.limit_history(&mut writer, 4).is_ok());
2278        assert_eq!(writer.buffer, indent_multiline(expected));
2279    }
2280
2281    #[test]
2282    fn test_shows_history_to_end() {
2283        let expected = "\
2284...
2285333 444 555
2286666 777
2287888
2288999 <==
2289";
2290        let mut engine = create_engine();
2291        let mut writer = BufferWriter::new();
2292        engine.undos.push(create_undo(0, vec![], vec!["111"]));
2293        engine.undos.push(create_undo(0, vec![], vec!["222"]));
2294        engine.undos.push(create_undo(0, vec![], vec!["333", "444", "555"]));
2295        engine.undos.push(create_undo(0, vec![], vec!["666", "777"]));
2296        engine.undos.push(create_undo(0, vec![], vec!["888"]));
2297        engine.undos.push(create_undo(0, vec![], vec!["999"]));
2298        assert!(engine.limit_history(&mut writer, 4).is_ok());
2299        assert_eq!(writer.buffer, indent_multiline(expected));
2300    }
2301
2302    #[test]
2303    fn test_shows_stack_with_no_values() {
2304        let mut engine = create_engine();
2305        let mut writer = BufferWriter::new();
2306        let mut stack = ValueStack::new(Vec::new());
2307        assert!(engine.show_stack(&mut writer, &mut stack).is_ok());
2308        assert_eq!(writer.buffer, "");
2309    }
2310
2311    #[test]
2312    fn test_shows_stack_as_decimal_no_sep() {
2313        let expected = "\
231499999
231599999     # integer value
231699999     = foo
231799999     = bar # integer value
2318  123.45  m/s
2319  123.45  m^3 # decimal value
2320  123.45  m^2 = baz
2321  123.45  km = qux # decimal value
2322    3.142
2323    3.142 # decimal value
2324    3.142 = quux
2325    3.142 = quuux # decimal value
2326";
2327        let mut engine = create_engine();
2328        let mut writer = BufferWriter::new();
2329        let mut stack = ValueStack::new(Vec::new());
2330        stack.wrapped_push(parse_item("99999"));
2331        stack.wrapped_push(parse_item("99999").with_comment("integer value"));
2332        stack.wrapped_push(parse_item("99999").with_variable("foo"));
2333        stack.wrapped_push(parse_item("99999").with_variable("bar").with_comment("integer value"));
2334        stack.wrapped_push(parse_item("123.45").with_meaning(Speed(Ratio(Metre(Unit), Second(Unit)))));
2335        stack.wrapped_push(parse_item("123.45").with_meaning(Volume(Cubic(Metre(Unit)))).with_comment("decimal value"));
2336        stack.wrapped_push(parse_item("123.45").with_meaning(Area(Square(Metre(Unit)))).with_variable("baz"));
2337        stack.wrapped_push(parse_item("123.45").with_meaning(Length(Metre(Kilo))).with_variable("qux").with_comment("decimal value"));
2338        stack.wrapped_push(parse_item("3.142"));
2339        stack.wrapped_push(parse_item("3.142").with_comment("decimal value"));
2340        stack.wrapped_push(parse_item("3.142").with_variable("quux"));
2341        stack.wrapped_push(parse_item("3.142").with_variable("quuux").with_comment("decimal value"));
2342        assert!(engine.show_stack(&mut writer, &mut stack).is_ok());
2343        assert_eq!(writer.buffer, indent_multiline(expected));
2344    }
2345
2346    #[test]
2347    fn test_shows_stack_as_decimal_with_sep() {
2348        let expected = "\
234999,999
235099,999     # integer value
235199,999     = foo
235299,999     = bar # integer value
2353   123.45  m/s
2354   123.45  m^3 # decimal value
2355   123.45  m^2 = baz
2356   123.45  km = qux # decimal value
2357     3.142
2358     3.142 # decimal value
2359     3.142 = quux
2360     3.142 = quuux # decimal value
2361";
2362        let mut engine = create_engine();
2363        let mut writer = BufferWriter::new();
2364        let mut stack = ValueStack::new(Vec::new());
2365        engine.context.borrow_mut().sep = true;
2366        stack.wrapped_push(parse_item("99999"));
2367        stack.wrapped_push(parse_item("99999").with_comment("integer value"));
2368        stack.wrapped_push(parse_item("99999").with_variable("foo"));
2369        stack.wrapped_push(parse_item("99999").with_variable("bar").with_comment("integer value"));
2370        stack.wrapped_push(parse_item("123.45").with_meaning(Speed(Ratio(Metre(Unit), Second(Unit)))));
2371        stack.wrapped_push(parse_item("123.45").with_meaning(Volume(Cubic(Metre(Unit)))).with_comment("decimal value"));
2372        stack.wrapped_push(parse_item("123.45").with_meaning(Area(Square(Metre(Unit)))).with_variable("baz"));
2373        stack.wrapped_push(parse_item("123.45").with_meaning(Length(Metre(Kilo))).with_variable("qux").with_comment("decimal value"));
2374        stack.wrapped_push(parse_item("3.142"));
2375        stack.wrapped_push(parse_item("3.142").with_comment("decimal value"));
2376        stack.wrapped_push(parse_item("3.142").with_variable("quux"));
2377        stack.wrapped_push(parse_item("3.142").with_variable("quuux").with_comment("decimal value"));
2378        assert!(engine.show_stack(&mut writer, &mut stack).is_ok());
2379        assert_eq!(writer.buffer, indent_multiline(expected));
2380    }
2381
2382    #[test]
2383    fn test_shows_stack_as_single_hexadecimal_no_sep() {
2384        let expected = "\
23850x7fffffff
23860x7fffffff # large value
23870x7fffffff = foo
23880x7fffffff = bar # large value
23890x00000001
23900x00000001 # small value
23910x00000001 = baz
23920x00000001 = qux # small value
2393";
2394        let mut engine = create_engine();
2395        let mut writer = BufferWriter::new();
2396        let mut stack = ValueStack::new(Vec::new());
2397        engine.context.borrow_mut().format = Format::Base16(0);
2398        engine.context.borrow_mut().sep = false;
2399        stack.wrapped_push(parse_item("2147483647"));
2400        stack.wrapped_push(parse_item("2147483647").with_comment("large value"));
2401        stack.wrapped_push(parse_item("2147483647").with_variable("foo"));
2402        stack.wrapped_push(parse_item("2147483647").with_variable("bar").with_comment("large value"));
2403        stack.wrapped_push(parse_item("1"));
2404        stack.wrapped_push(parse_item("1").with_comment("small value"));
2405        stack.wrapped_push(parse_item("1").with_variable("baz"));
2406        stack.wrapped_push(parse_item("1").with_variable("qux").with_comment("small value"));
2407        assert!(engine.show_stack(&mut writer, &mut stack).is_ok());
2408        assert_eq!(writer.buffer, indent_multiline(expected));
2409    }
2410
2411    #[test]
2412    fn test_shows_stack_as_double_hexadecimal_with_sep() {
2413        let expected = "\
24140x,00000001,00000000
24150x,00000001,00000000 # large value
24160x,00000001,00000000 = foo
24170x,00000001,00000000 = bar # large value
24180x,00000000,00000001
24190x,00000000,00000001 # small value
24200x,00000000,00000001 = baz
24210x,00000000,00000001 = qux # small value
2422";
2423        let mut engine = create_engine();
2424        let mut writer = BufferWriter::new();
2425        let mut stack = ValueStack::new(Vec::new());
2426        engine.context.borrow_mut().format = Format::Base16(0);
2427        engine.context.borrow_mut().sep = true;
2428        stack.wrapped_push(parse_item("4294967296"));
2429        stack.wrapped_push(parse_item("4294967296").with_comment("large value"));
2430        stack.wrapped_push(parse_item("4294967296").with_variable("foo"));
2431        stack.wrapped_push(parse_item("4294967296").with_variable("bar").with_comment("large value"));
2432        stack.wrapped_push(parse_item("1"));
2433        stack.wrapped_push(parse_item("1").with_comment("small value"));
2434        stack.wrapped_push(parse_item("1").with_variable("baz"));
2435        stack.wrapped_push(parse_item("1").with_variable("qux").with_comment("small value"));
2436        assert!(engine.show_stack(&mut writer, &mut stack).is_ok());
2437        assert_eq!(writer.buffer, indent_multiline(expected));
2438    }
2439
2440    #[test]
2441    fn test_shows_stack_with_lower_limit() {
2442        let expected = "\
2443_ ...
2444| 0.25  |
2445[ 0.375 ]
2446( 0.5   )
2447[ 0.625 ]
2448_ 0.75
2449_ 0.875
2450";
2451        let mut engine = create_engine();
2452        let mut writer = BufferWriter::new();
2453        let mut stack = ValueStack::new(Vec::new());
2454        stack.wrapped_push(parse_item("-0.25"));
2455        stack.wrapped_push(parse_item("-0.125"));
2456        stack.wrapped_push(parse_series(vec![
2457            "0",
2458            "0.125",
2459            "0.25",
2460            "0.375",
2461        ]));
2462        stack.wrapped_push(parse_series(vec![
2463            "0.5",
2464            "0.625",
2465        ]));
2466        stack.wrapped_push(parse_item("0.75"));
2467        stack.wrapped_push(parse_item("0.875"));
2468        assert!(engine.limit_stack(&mut writer, &mut stack, Some(6)).is_ok());
2469        assert_eq!(writer.buffer, replace_multiline(expected));
2470    }
2471
2472    #[test]
2473    fn test_shows_stack_with_equal_limit() {
2474        let expected = "\
2475_ -0.25
2476_ -0.125
2477(  0     )
2478|  0.125 |
2479|  0.25  |
2480[  0.375 ]
2481(  0.5   )
2482[  0.625 ]
2483_  0.75
2484_  0.875
2485";
2486        let mut engine = create_engine();
2487        let mut writer = BufferWriter::new();
2488        let mut stack = ValueStack::new(Vec::new());
2489        stack.wrapped_push(parse_item("-0.25"));
2490        stack.wrapped_push(parse_item("-0.125"));
2491        stack.wrapped_push(parse_series(vec![
2492            "0",
2493            "0.125",
2494            "0.25",
2495            "0.375",
2496        ]));
2497        stack.wrapped_push(parse_series(vec![
2498            "0.5",
2499            "0.625",
2500        ]));
2501        stack.wrapped_push(parse_item("0.75"));
2502        stack.wrapped_push(parse_item("0.875"));
2503        assert!(engine.limit_stack(&mut writer, &mut stack, Some(10)).is_ok());
2504        assert_eq!(writer.buffer, replace_multiline(expected));
2505    }
2506
2507    #[test]
2508    fn test_shows_stack_with_higher_limit() {
2509        let expected = "\
2510_ -0.25
2511_ -0.125
2512(  0     )
2513|  0.125 |
2514|  0.25  |
2515[  0.375 ]
2516(  0.5   )
2517[  0.625 ]
2518_  0.75
2519_  0.875
2520";
2521        let mut engine = create_engine();
2522        let mut writer = BufferWriter::new();
2523        let mut stack = ValueStack::new(Vec::new());
2524        stack.wrapped_push(parse_item("-0.25"));
2525        stack.wrapped_push(parse_item("-0.125"));
2526        stack.wrapped_push(parse_series(vec![
2527            "0",
2528            "0.125",
2529            "0.25",
2530            "0.375",
2531        ]));
2532        stack.wrapped_push(parse_series(vec![
2533            "0.5",
2534            "0.625",
2535        ]));
2536        stack.wrapped_push(parse_item("0.75"));
2537        stack.wrapped_push(parse_item("0.875"));
2538        assert!(engine.limit_stack(&mut writer, &mut stack, Some(12)).is_ok());
2539        assert_eq!(writer.buffer, replace_multiline(expected));
2540    }
2541
2542    #[test]
2543    fn test_shows_stack_with_no_limit() {
2544        let expected = "\
2545_ -0.25
2546_ -0.125
2547(  0     )
2548|  0.125 |
2549|  0.25  |
2550[  0.375 ]
2551(  0.5   )
2552[  0.625 ]
2553_  0.75
2554_  0.875
2555";
2556        let mut engine = create_engine();
2557        let mut writer = BufferWriter::new();
2558        let mut stack = ValueStack::new(Vec::new());
2559        stack.wrapped_push(parse_item("-0.25"));
2560        stack.wrapped_push(parse_item("-0.125"));
2561        stack.wrapped_push(parse_series(vec![
2562            "0",
2563            "0.125",
2564            "0.25",
2565            "0.375",
2566        ]));
2567        stack.wrapped_push(parse_series(vec![
2568            "0.5",
2569            "0.625",
2570        ]));
2571        stack.wrapped_push(parse_item("0.75"));
2572        stack.wrapped_push(parse_item("0.875"));
2573        assert!(engine.limit_stack(&mut writer, &mut stack, None).is_ok());
2574        assert_eq!(writer.buffer, replace_multiline(expected));
2575    }
2576
2577    #[test]
2578    fn test_shows_variables_sorted_by_name() {
2579        let expected = "\
25805 = five
25814 = four
25821 = one
25833 = three
25842 = two
2585";
2586        let mut engine = create_engine();
2587        let mut writer = BufferWriter::new();
2588        let mut stack = ValueStack::new(Vec::new());
2589        engine.interface.borrow_mut().insert_variable(String::from("one"), make_ref(parse_value("1").with_variable("one")));
2590        engine.interface.borrow_mut().insert_variable(String::from("two"), make_ref(parse_value("2").with_variable("two")));
2591        engine.interface.borrow_mut().insert_variable(String::from("three"), make_ref(parse_value("3").with_variable("three")));
2592        engine.interface.borrow_mut().insert_variable(String::from("four"), make_ref(parse_value("4").with_variable("four")));
2593        engine.interface.borrow_mut().insert_variable(String::from("five"), make_ref(parse_value("5").with_variable("five")));
2594        assert!(parse_line(&mut engine, &mut writer, &mut stack, "set").is_ok());
2595        assert_eq!(writer.buffer, indent_multiline(expected));
2596    }
2597
2598    fn make_ref(value: Value) -> ValueRef {
2599        Rc::new(RefCell::new(value))
2600    }
2601
2602    fn indent_multiline(lines: &str) -> String {
2603        lines.lines()
2604            .map(|x| format!("  {}\n", x))
2605            .collect::<Vec<String>>()
2606            .join("")
2607    }
2608
2609    fn replace_multiline(lines: &str) -> String {
2610        lines.lines()
2611            .map(|x| x.replace("_", " "))
2612            .map(|x| format!("{}\n", x))
2613            .collect::<Vec<String>>()
2614            .join("")
2615    }
2616
2617    fn create_engine() -> Engine<BufferWriter> {
2618        let config = Config::default();
2619        let chars = BracketChars {
2620            open: ('(', ')'),
2621            middle: ('|', '|'),
2622            close: ('[', ']'),
2623        };
2624        Engine::new(config, chars).unwrap().with_interact(true)
2625    }
2626
2627    fn parse_line(
2628        engine: &mut Engine<BufferWriter>,
2629        writer: &mut BufferWriter,
2630        stack: &mut ValueStack,
2631        line: &str,
2632    ) -> MyResult<()> {
2633        let result = engine.parse_line(writer, stack, line);
2634        if let Err(error) = &result {
2635            writeln!(writer, "{}", error)?;
2636        }
2637        result
2638    }
2639
2640    impl<W: Write> Engine<W> {
2641        pub fn with_interact(mut self, interact: bool) -> Self {
2642            self.interact = interact;
2643            self
2644        }
2645    }
2646}