Remove lazy_static dependency (#530)
This commit is contained in:
		
							parent
							
								
									df0c2358fd
								
							
						
					
					
						commit
						1418580fed
					
				| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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) | ||||
| } | ||||
|  | ||||
| @ -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(()) | ||||
|     } | ||||
|  | ||||
							
								
								
									
										33
									
								
								src/event.rs
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								src/event.rs
									
									
									
									
									
								
							| @ -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) | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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") | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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()?; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user