Remove lazy_static dependency (#530)

This commit is contained in:
Koxiaet 2021-01-03 13:40:22 +00:00 committed by GitHub
parent df0c2358fd
commit 1418580fed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 91 additions and 77 deletions

View File

@ -34,7 +34,6 @@ event-stream = ["futures-core"]
#
[dependencies]
bitflags = "1.2"
lazy_static = "1.4"
parking_lot = "0.11"
# optional deps only added when requested

View File

@ -144,8 +144,7 @@ features = ["event-stream"]
| Dependency | Used for | Included |
| :----- | :----- | :-----
| `bitflags` | `KeyModifiers`, those are differ based on input.| always
| `lazy_static` | original console color, original terminal mode, saved cursor position, supports ANSI on windows, single event reader per application.| always
| `parking_lot` | used for an RW LOCK. | always
| `parking_lot` | locking `RwLock`s with a timeout, const mutexes. | always
| `libc` | UNIX terminal_size/raw modes/set_title and several other lowlevel functionality. | UNIX only
| `Mio` | event readiness polling, waking up poller | UNIX only
| `signal-hook`| signalhook is used to handle terminal resize SIGNAL with Mio. | UNIX only

View File

@ -1,7 +1,8 @@
use crossterm_winapi::{ConsoleMode, Handle};
use winapi::um::wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
use std::sync::atomic::{AtomicBool, Ordering};
use lazy_static::lazy_static;
use crossterm_winapi::{ConsoleMode, Handle};
use parking_lot::Once;
use winapi::um::wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
use crate::Result;
@ -27,17 +28,21 @@ fn enable_vt_processing() -> Result<()> {
Ok(())
}
lazy_static! {
static ref SUPPORTS_ANSI_ESCAPE_CODES: bool = {
static SUPPORTS_ANSI_ESCAPE_CODES: AtomicBool = AtomicBool::new(false);
static INITIALIZER: Once = Once::new();
/// Checks if the current terminal supports ansi escape sequences
pub fn supports_ansi() -> bool {
INITIALIZER.call_once(|| {
// Some terminals on Windows like GitBash can't use WinAPI calls directly
// so when we try to enable the ANSI-flag for Windows this won't work.
// Because of that we should check first if the TERM-variable is set
// and see if the current terminal is a terminal who does support ANSI.
std::env::var("TERM").map_or(false, |term| term != "dumb") || enable_vt_processing().is_ok()
};
}
let supported = std::env::var("TERM").map_or(false, |term| term != "dumb")
|| enable_vt_processing().is_ok();
/// Checks if the current terminal supports ansi escape sequences
pub fn supports_ansi() -> bool {
*SUPPORTS_ANSI_ESCAPE_CODES
SUPPORTS_ANSI_ESCAPE_CODES.store(supported, Ordering::SeqCst);
});
SUPPORTS_ANSI_ESCAPE_CODES.load(Ordering::SeqCst)
}

View File

@ -1,6 +1,8 @@
//! WinAPI related logic to cursor manipulation.
use std::{io, sync::Mutex};
use std::convert::TryFrom;
use std::io;
use std::sync::atomic::{AtomicU64, Ordering};
use crossterm_winapi::{is_true, Coord, Handle, HandleType, ScreenBuffer};
use winapi::{
@ -8,13 +10,13 @@ use winapi::{
um::wincon::{SetConsoleCursorInfo, SetConsoleCursorPosition, CONSOLE_CURSOR_INFO, COORD},
};
use lazy_static::lazy_static;
use crate::Result;
lazy_static! {
static ref SAVED_CURSOR_POS: Mutex<Option<(i16, i16)>> = Mutex::new(None);
}
/// The position of the cursor, written when you save the cursor's position.
///
/// This is `u64::MAX` initially. Otherwise, it stores the cursor's x position bit-shifted left 16
/// times or-ed with the cursor's y position, where both are `i16`s.
static SAVED_CURSOR_POS: AtomicU64 = AtomicU64::new(u64::MAX);
// The 'y' position of the cursor is not relative to the window but absolute to screen buffer.
// We can calculate the relative cursor position by subtracting the top position of the terminal window from the y position.
@ -176,7 +178,9 @@ impl ScreenBufferCursor {
}
fn restore_position(&self) -> Result<()> {
if let Some((x, y)) = *SAVED_CURSOR_POS.lock().unwrap() {
if let Ok(val) = u32::try_from(SAVED_CURSOR_POS.load(Ordering::Relaxed)) {
let x = (val >> 16) as i16;
let y = val as i16;
self.move_to(x, y)?;
}
@ -186,8 +190,8 @@ impl ScreenBufferCursor {
fn save_position(&self) -> Result<()> {
let position = self.position()?;
let mut locked_pos = SAVED_CURSOR_POS.lock().unwrap();
*locked_pos = Some((position.x, position.y));
let bits = u64::from(u32::from(position.x as u16) << 16 | u32::from(position.y as u16));
SAVED_CURSOR_POS.store(bits, Ordering::Relaxed);
Ok(())
}

View File

@ -75,16 +75,17 @@
use std::fmt;
use std::time::Duration;
use parking_lot::RwLock;
use bitflags::bitflags;
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{Command, Result};
use bitflags::bitflags;
use lazy_static::lazy_static;
use crate::{csi, Command, Result};
use filter::{EventFilter, Filter};
use read::InternalEventReader;
#[cfg(feature = "event-stream")]
pub use stream::EventStream;
use timeout::PollTimeout;
@ -97,10 +98,22 @@ mod stream;
pub(crate) mod sys;
mod timeout;
lazy_static! {
/// Static instance of `InternalEventReader`.
/// This needs to be static because there can be one event reader.
static ref INTERNAL_EVENT_READER: RwLock<read::InternalEventReader> = RwLock::new(read::InternalEventReader::default());
/// Static instance of `InternalEventReader`.
/// This needs to be static because there can be one event reader.
static INTERNAL_EVENT_READER: Mutex<Option<InternalEventReader>> = parking_lot::const_mutex(None);
fn lock_internal_event_reader() -> MappedMutexGuard<'static, InternalEventReader> {
MutexGuard::map(INTERNAL_EVENT_READER.lock(), |reader| {
reader.get_or_insert_with(InternalEventReader::default)
})
}
fn try_lock_internal_event_reader_for(
duration: Duration,
) -> Option<MappedMutexGuard<'static, InternalEventReader>> {
Some(MutexGuard::map(
INTERNAL_EVENT_READER.try_lock_for(duration)?,
|reader| reader.get_or_insert_with(InternalEventReader::default),
))
}
/// Checks if there is an [`Event`](enum.Event.html) available.
@ -201,13 +214,13 @@ where
{
let (mut reader, timeout) = if let Some(timeout) = timeout {
let poll_timeout = PollTimeout::new(Some(timeout));
if let Some(reader) = INTERNAL_EVENT_READER.try_write_for(timeout) {
if let Some(reader) = try_lock_internal_event_reader_for(timeout) {
(reader, poll_timeout.leftover())
} else {
return Ok(false);
}
} else {
(INTERNAL_EVENT_READER.write(), None)
(lock_internal_event_reader(), None)
};
reader.poll(timeout, filter)
}
@ -217,7 +230,7 @@ pub(crate) fn read_internal<F>(filter: &F) -> Result<InternalEvent>
where
F: Filter,
{
let mut reader = INTERNAL_EVENT_READER.write();
let mut reader = lock_internal_event_reader();
reader.read(filter)
}

View File

@ -15,8 +15,8 @@ use futures_core::stream::Stream;
use crate::Result;
use super::{
filter::EventFilter, poll_internal, read_internal, sys::Waker, Event, InternalEvent,
INTERNAL_EVENT_READER,
filter::EventFilter, lock_internal_event_reader, poll_internal, read_internal, sys::Waker,
Event, InternalEvent,
};
/// A stream of `Result<Event>`.
@ -60,7 +60,7 @@ impl Default for EventStream {
});
EventStream {
poll_internal_waker: INTERNAL_EVENT_READER.write().waker(),
poll_internal_waker: lock_internal_event_reader().waker(),
stream_wake_task_executed: Arc::new(AtomicBool::new(false)),
stream_wake_task_should_shutdown: Arc::new(AtomicBool::new(false)),
task_sender,

View File

@ -1,9 +1,9 @@
//! This is a WINDOWS specific implementation for input related action.
use std::sync::Mutex;
use std::convert::TryFrom;
use std::sync::atomic::{AtomicU64, Ordering};
use crossterm_winapi::{ConsoleMode, Handle};
use lazy_static::lazy_static;
use crate::Result;
@ -15,25 +15,24 @@ pub(crate) mod poll;
const ENABLE_MOUSE_MODE: u32 = 0x0010 | 0x0080 | 0x0008;
lazy_static! {
static ref ORIGINAL_CONSOLE_MODE: Mutex<Option<u32>> = Mutex::new(None);
}
/// This is a either `u64::MAX` if it's uninitialized or a valid `u32` that stores the original
/// console mode if it's initialized.
static ORIGINAL_CONSOLE_MODE: AtomicU64 = AtomicU64::new(u64::MAX);
/// Initializes the default console color. It will will be skipped if it has already been initialized.
fn init_original_console_mode(original_mode: u32) {
let mut lock = ORIGINAL_CONSOLE_MODE.lock().unwrap();
if lock.is_none() {
*lock = Some(original_mode);
}
let _ = ORIGINAL_CONSOLE_MODE.compare_exchange(
u64::MAX,
u64::from(original_mode),
Ordering::Relaxed,
Ordering::Relaxed,
);
}
/// Returns the original console color, make sure to call `init_console_color` before calling this function. Otherwise this function will panic.
fn original_console_mode() -> u32 {
u32::try_from(ORIGINAL_CONSOLE_MODE.load(Ordering::Relaxed))
// safe unwrap, initial console color was set with `init_console_color` in `WinApiColor::new()`
ORIGINAL_CONSOLE_MODE
.lock()
.unwrap()
.expect("Original console mode not set")
}

View File

@ -1,10 +1,9 @@
use std::sync::Mutex;
use std::convert::TryFrom;
use std::sync::atomic::{AtomicU32, Ordering};
use crossterm_winapi::{Console, Handle, HandleType, ScreenBuffer};
use winapi::um::wincon;
use lazy_static::lazy_static;
use crate::Result;
use super::super::{Color, Colored};
@ -70,7 +69,7 @@ pub(crate) fn set_background_color(bg_color: Color) -> Result<()> {
}
pub(crate) fn reset() -> Result<()> {
if let Some(original_color) = *ORIGINAL_CONSOLE_COLOR.lock().unwrap() {
if let Ok(original_color) = u16::try_from(ORIGINAL_CONSOLE_COLOR.load(Ordering::Relaxed)) {
Console::from(Handle::new(HandleType::CurrentOutputHandle)?)
.set_text_attribute(original_color)?;
}
@ -80,12 +79,10 @@ pub(crate) fn reset() -> Result<()> {
/// Initializes the default console color. It will will be skipped if it has already been initialized.
pub(crate) fn init_console_color() -> Result<()> {
let mut locked_pos = ORIGINAL_CONSOLE_COLOR.lock().unwrap();
if locked_pos.is_none() {
if ORIGINAL_CONSOLE_COLOR.load(Ordering::Relaxed) == u32::MAX {
let screen_buffer = ScreenBuffer::current()?;
let attr = screen_buffer.info()?.attributes();
*locked_pos = Some(attr);
ORIGINAL_CONSOLE_COLOR.store(u32::from(attr), Ordering::Relaxed);
}
Ok(())
@ -93,16 +90,14 @@ pub(crate) fn init_console_color() -> Result<()> {
/// Returns the original console color, make sure to call `init_console_color` before calling this function. Otherwise this function will panic.
pub(crate) fn original_console_color() -> u16 {
u16::try_from(ORIGINAL_CONSOLE_COLOR.load(Ordering::Relaxed))
// safe unwrap, initial console color was set with `init_console_color` in `WinApiColor::new()`
ORIGINAL_CONSOLE_COLOR
.lock()
.unwrap()
.expect("Initial console color not set")
}
lazy_static! {
static ref ORIGINAL_CONSOLE_COLOR: Mutex<Option<u16>> = Mutex::new(None);
}
// This is either a valid u16 in which case it stores the original console color or it is u32::MAX
// in which case it is uninitialized.
static ORIGINAL_CONSOLE_COLOR: AtomicU32 = AtomicU32::new(u32::MAX);
impl From<Colored> for u16 {
/// Returns the WinAPI color value (u16) from the `Colored` struct.
@ -180,6 +175,8 @@ impl From<Colored> for u16 {
#[cfg(test)]
mod tests {
use std::sync::atomic::Ordering;
use crate::style::sys::windows::set_foreground_color;
use super::{
@ -200,11 +197,11 @@ mod tests {
#[test]
fn test_original_console_color_is_set() {
assert!(ORIGINAL_CONSOLE_COLOR.lock().unwrap().is_none());
assert_eq!(ORIGINAL_CONSOLE_COLOR.load(Ordering::Relaxed), u32::MAX);
// will call `init_console_color`
set_foreground_color(Color::Blue).unwrap();
assert!(ORIGINAL_CONSOLE_COLOR.lock().unwrap().is_some());
assert_ne!(ORIGINAL_CONSOLE_COLOR.load(Ordering::Relaxed), u32::MAX);
}
}

View File

@ -2,25 +2,23 @@
use std::fs::File;
use std::os::unix::io::{IntoRawFd, RawFd};
use std::{io, mem, process, sync::Mutex};
use std::{io, mem, process};
use lazy_static::lazy_static;
use libc::{
cfmakeraw, ioctl, tcgetattr, tcsetattr, termios as Termios, winsize, STDOUT_FILENO, TCSANOW,
TIOCGWINSZ,
};
use parking_lot::Mutex;
use crate::error::{ErrorKind, Result};
use crate::event::sys::unix::file_descriptor::{tty_fd, FileDesc};
lazy_static! {
// Some(Termios) -> we're in the raw mode and this is the previous mode
// None -> we're not in the raw mode
static ref TERMINAL_MODE_PRIOR_RAW_MODE: Mutex<Option<Termios>> = Mutex::new(None);
}
// Some(Termios) -> we're in the raw mode and this is the previous mode
// None -> we're not in the raw mode
static TERMINAL_MODE_PRIOR_RAW_MODE: Mutex<Option<Termios>> = parking_lot::const_mutex(None);
pub(crate) fn is_raw_mode_enabled() -> bool {
TERMINAL_MODE_PRIOR_RAW_MODE.lock().unwrap().is_some()
TERMINAL_MODE_PRIOR_RAW_MODE.lock().is_some()
}
#[allow(clippy::useless_conversion)]
@ -49,7 +47,7 @@ pub(crate) fn size() -> Result<(u16, u16)> {
}
pub(crate) fn enable_raw_mode() -> Result<()> {
let mut original_mode = TERMINAL_MODE_PRIOR_RAW_MODE.lock().unwrap();
let mut original_mode = TERMINAL_MODE_PRIOR_RAW_MODE.lock();
if original_mode.is_some() {
return Ok(());
@ -70,7 +68,7 @@ pub(crate) fn enable_raw_mode() -> Result<()> {
}
pub(crate) fn disable_raw_mode() -> Result<()> {
let mut original_mode = TERMINAL_MODE_PRIOR_RAW_MODE.lock().unwrap();
let mut original_mode = TERMINAL_MODE_PRIOR_RAW_MODE.lock();
if let Some(original_mode_ios) = original_mode.as_ref() {
let tty = tty_fd()?;