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
36impl<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 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#[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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}