Skip to main content

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}