minus/core/mod.rs
1use std::collections::VecDeque;
2
3pub mod commands;
4pub mod ev_handler;
5#[cfg(any(feature = "dynamic_output", feature = "static_output"))]
6pub mod init;
7pub mod utils;
8
9// TODO: Global statics aren't great and this one, in particular, is making it hard to run tests
10// (since most non-unit tests will end up setting this, which then needs to be unset for the next
11// test). Figure out how to get rid of this.
12pub static RUNMODE: parking_lot::Mutex<RunMode> = parking_lot::const_mutex(RunMode::Uninitialized);
13
14use commands::Command;
15
16/// A [`VecDeque`] to hold [Command]s to be executed after the current command has been executed
17///
18/// Many [`Command`]s in minus require additional commands to be executed once the current command's
19/// main objective has ben completed. For example the [`SetLineNumbers`](Command::SetLineNumbers)
20/// requires the text data to be reformatted and repainted on the screen. Hence it can push that
21/// command to this to be executed once it itself has completed executing.
22///
23/// This also takes into account [RUNMODE] before inserting data. The means that it will ensure that
24/// [RUNMODE] is not uninitialized before pushing any data into the queue. Hence it is best used
25/// case is while declaring handlers for [`Command::UserInput`].
26///
27/// This is a FIFO type hence the command that enters first gets executed first.
28pub struct CommandQueue(VecDeque<Command>);
29
30impl CommandQueue {
31 /// Create a new `CommandQueue` with default size of 10.
32 pub fn new() -> Self {
33 Self(VecDeque::with_capacity(10))
34 }
35 /// Create a new `CommandQueue` with zero memory allocation.
36 ///
37 /// This is useful when we have to pass this type to [`handle_event`](ev_handler::handle_event)
38 /// but it is sure that this won't be used.
39 pub fn new_zero() -> Self {
40 Self(VecDeque::with_capacity(0))
41 }
42 /// Returns true if the queue is empty.
43 pub fn is_empty(&self) -> bool {
44 self.0.is_empty()
45 }
46
47 /// Store `value` for processing later
48 pub fn push_back(&mut self, value: Command) {
49 self.0.push_back(value);
50 }
51
52 /// Pop the next commands for processing
53 pub fn pop_front(&mut self) -> Option<Command> {
54 self.0.pop_front()
55 }
56}
57
58/// Define the modes in which minus can run
59#[derive(Copy, Clone, PartialEq, Eq, Debug)]
60pub enum RunMode {
61 #[cfg(feature = "static_output")]
62 Static,
63 #[cfg(feature = "dynamic_output")]
64 Dynamic,
65 Uninitialized,
66}
67
68impl RunMode {
69 /// Returns true if minus hasn't started
70 ///
71 /// # Example
72 /// ```
73 /// use minus::RunMode;
74 ///
75 /// let runmode = RunMode::Uninitialized;
76 /// assert_eq!(runmode.is_uninitialized(), true);
77 /// ```
78 #[must_use]
79 pub fn is_uninitialized(self) -> bool {
80 self == Self::Uninitialized
81 }
82}