diff --git a/.github/workflows/crossterm_test.yml b/.github/workflows/crossterm_test.yml index 2b04bc0..c5cbe95 100644 --- a/.github/workflows/crossterm_test.yml +++ b/.github/workflows/crossterm_test.yml @@ -57,7 +57,7 @@ jobs: run: cargo test --lib --features serde -- --nocapture --test-threads 1 continue-on-error: ${{ matrix.can-fail }} - name: Test event-stream feature - run: cargo test --lib --features event-stream -- --nocapture --test-threads 1 + run: cargo test --lib --features "event-stream,events" -- --nocapture --test-threads 1 continue-on-error: ${{ matrix.can-fail }} - name: Test all features run: cargo test --all-features -- --nocapture --test-threads 1 @@ -68,7 +68,7 @@ jobs: continue-on-error: ${{ matrix.can-fail }} - name: Test no default features with windows feature enabled if: matrix.os == 'windows-2019' - run: cargo test --no-default-features --features windows -- --nocapture --test-threads 1 + run: cargo test --no-default-features --features "windows" -- --nocapture --test-threads 1 - name: Test Packaging if: matrix.rust == 'stable' run: cargo package diff --git a/Cargo.toml b/Cargo.toml index 50af01c..79d9d88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,12 +26,12 @@ all-features = true # Features # [features] -default = ["bracketed-paste", "windows"] +default = ["bracketed-paste", "windows", "events"] windows = ["winapi", "crossterm_winapi"] bracketed-paste = [] -event-stream = ["futures-core"] +event-stream = ["futures-core", "events"] use-dev-tty = ["filedescriptor"] - +events = ["mio", "signal-hook", "signal-hook-mio"] # # Shared dependencies # @@ -59,10 +59,10 @@ crossterm_winapi = { version = "0.9", optional = true } # [target.'cfg(unix)'.dependencies] libc = "0.2" -signal-hook = { version = "0.3.13" } +signal-hook = { version = "0.3.13", optional = true } filedescriptor = { version = "0.8", optional = true } -mio = { version = "0.8", features = ["os-poll"] } -signal-hook-mio = { version = "0.2.3", features = ["support-v0_8"] } +mio = { version = "0.8", features = ["os-poll"], optional = true } +signal-hook-mio = { version = "0.2.3", features = ["support-v0_8"], optional = true } # # Dev dependencies (examples, ...) @@ -79,12 +79,28 @@ serde_json = "1.0" # [[example]] name = "event-read" -required-features = ["bracketed-paste"] +required-features = ["bracketed-paste", "events"] + +[[example]] +name = "event-match-modifiers" +required-features = ["bracketed-paste", "events"] + +[[example]] +name = "event-poll-read" +required-features = ["bracketed-paste", "events"] [[example]] name = "event-stream-async-std" -required-features = ["event-stream"] +required-features = ["event-stream", "events"] [[example]] name = "event-stream-tokio" -required-features = ["event-stream"] +required-features = ["event-stream", "events"] + +[[example]] +name = "event-read-char-line" +required-features = ["events"] + +[[example]] +name = "stderr" +required-features = ["events"] diff --git a/README.md b/README.md index 009fd2d..29298d3 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,12 @@ features = ["event-stream"] |:---------------|:---------------------------------------------| | `event-stream` | `futures::Stream` producing `Result`. | | `serde` | (De)serializing of events. | +| `events` | Reading input/system events (enabled by default) | +| `filedescriptor` | Use raw filedescriptor for all events rather then mio dependency | + + +To use crossterm as a very tin layer you can disable the `events` feature or use `filedescriptor` feature. +This can disable `mio` / `signal-hook` / `signal-hook-mio` dependencies. ### Dependency Justification @@ -151,9 +157,9 @@ features = ["event-stream"] |:---------------|:---------------------------------------------------------------------------------|:--------------------------------------| | `bitflags` | `KeyModifiers`, those are differ based on input. | always | | `parking_lot` | locking `RwLock`s with a timeout, const mutexes. | always | -| `libc` | UNIX terminal_size/raw modes/set_title and several other low level functionality. | UNIX only | -| `Mio` | event readiness polling, waking up poller | UNIX only | -| `signal-hook` | signal-hook is used to handle terminal resize SIGNAL with Mio. | UNIX only | +| `libc` | UNIX terminal_size/raw modes/set_title and several other low level functionality. | optional (`events` feature), UNIX only | +| `Mio` | event readiness polling, waking up poller | optional (`events` feature), UNIX only | +| `signal-hook` | signal-hook is used to handle terminal resize SIGNAL with Mio. | optional (`events` feature),UNIX only | | `winapi` | Used for low-level windows system calls which ANSI codes can't replace | windows only | | `futures-core` | For async stream of events | only with `event-stream` feature flag | | `serde` | ***ser***ializing and ***de***serializing of events | only with `serde` feature flag | diff --git a/src/cursor.rs b/src/cursor.rs index 4d0f898..99ba330 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -48,10 +48,11 @@ use std::fmt; use crate::Result; use crate::{csi, impl_display, Command}; -pub use sys::position; - pub(crate) mod sys; +#[cfg(feature = "events")] +pub use sys::position; + /// A command that moves the terminal cursor to the given position (column, row). /// /// # Notes @@ -426,13 +427,14 @@ impl_display!(for DisableBlinking); impl_display!(for SetCursorStyle); #[cfg(test)] +#[cfg(feature = "events")] mod tests { use std::io::{self, stdout}; use crate::execute; use super::{ - position, MoveDown, MoveLeft, MoveRight, MoveTo, MoveUp, RestorePosition, SavePosition, + sys::position, MoveDown, MoveLeft, MoveRight, MoveTo, MoveUp, RestorePosition, SavePosition, }; // Test is disabled, because it's failing on Travis diff --git a/src/cursor/sys.rs b/src/cursor/sys.rs index b63a2bb..f85a95c 100644 --- a/src/cursor/sys.rs +++ b/src/cursor/sys.rs @@ -1,6 +1,7 @@ //! This module provides platform related functions. #[cfg(unix)] +#[cfg(feature = "events")] pub use self::unix::position; #[cfg(windows)] pub use self::windows::position; @@ -14,4 +15,5 @@ pub(crate) use self::windows::{ pub(crate) mod windows; #[cfg(unix)] +#[cfg(feature = "events")] pub(crate) mod unix; diff --git a/src/event.rs b/src/event.rs index c1180b2..71f600a 100644 --- a/src/event.rs +++ b/src/event.rs @@ -80,37 +80,38 @@ //! Check the [examples](https://github.com/crossterm-rs/crossterm/tree/master/examples) folder for more of //! them (`event-*`). +pub(crate) mod filter; +pub(crate) mod read; +pub(crate) mod source; +#[cfg(feature = "event-stream")] +pub(crate) mod stream; +pub(crate) mod sys; +pub(crate) mod timeout; + +#[cfg(feature = "event-stream")] +pub use stream::EventStream; + +use crate::event::{ + filter::{EventFilter, Filter}, + read::InternalEventReader, + timeout::PollTimeout, +}; +use crate::{csi, Command}; +use parking_lot::{MappedMutexGuard, Mutex, MutexGuard}; use std::fmt; -use std::hash::{Hash, Hasher}; -#[cfg(windows)] -use std::io; use std::time::Duration; -use bitflags::bitflags; -use parking_lot::{MappedMutexGuard, Mutex, MutexGuard}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use crate::{csi, Command, Result}; -use filter::{EventFilter, Filter}; -use read::InternalEventReader; -#[cfg(feature = "event-stream")] -pub use stream::EventStream; -use timeout::PollTimeout; - -pub(crate) mod filter; -mod read; -mod source; -#[cfg(feature = "event-stream")] -mod stream; -pub(crate) mod sys; -mod timeout; +use bitflags::bitflags; +use std::hash::{Hash, Hasher}; /// Static instance of `InternalEventReader`. /// This needs to be static because there can be one event reader. static INTERNAL_EVENT_READER: Mutex> = parking_lot::const_mutex(None); -fn lock_internal_event_reader() -> MappedMutexGuard<'static, InternalEventReader> { +pub(crate) fn lock_internal_event_reader() -> MappedMutexGuard<'static, InternalEventReader> { MutexGuard::map(INTERNAL_EVENT_READER.lock(), |reader| { reader.get_or_insert_with(InternalEventReader::default) }) @@ -164,7 +165,7 @@ fn try_lock_internal_event_reader_for( /// poll(Duration::from_millis(100)) /// } /// ``` -pub fn poll(timeout: Duration) -> Result { +pub fn poll(timeout: Duration) -> crate::Result { poll_internal(Some(timeout), &EventFilter) } @@ -207,7 +208,7 @@ pub fn poll(timeout: Duration) -> Result { /// } /// } /// ``` -pub fn read() -> Result { +pub fn read() -> crate::Result { match read_internal(&EventFilter)? { InternalEvent::Event(event) => Ok(event), #[cfg(unix)] @@ -216,7 +217,7 @@ pub fn read() -> Result { } /// Polls to check if there are any `InternalEvent`s that can be read within the given duration. -pub(crate) fn poll_internal(timeout: Option, filter: &F) -> Result +pub(crate) fn poll_internal(timeout: Option, filter: &F) -> crate::Result where F: Filter, { @@ -234,7 +235,7 @@ where } /// Reads a single `InternalEvent`. -pub(crate) fn read_internal(filter: &F) -> Result +pub(crate) fn read_internal(filter: &F) -> crate::Result where F: Filter, { @@ -242,12 +243,42 @@ where reader.read(filter) } +bitflags! { + /// Represents special flags that tell compatible terminals to add extra information to keyboard events. + /// + /// See for more information. + /// + /// Alternate keys and Unicode codepoints are not yet supported by crossterm. + #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] + pub struct KeyboardEnhancementFlags: u8 { + /// Represent Escape and modified keys using CSI-u sequences, so they can be unambiguously + /// read. + const DISAMBIGUATE_ESCAPE_CODES = 0b0000_0001; + /// Add extra events with [`KeyEvent.kind`] set to [`KeyEventKind::Repeat`] or + /// [`KeyEventKind::Release`] when keys are autorepeated or released. + const REPORT_EVENT_TYPES = 0b0000_0010; + // Send [alternate keycodes](https://sw.kovidgoyal.net/kitty/keyboard-protocol/#key-codes) + // in addition to the base keycode. The alternate keycode overrides the base keycode in + // resulting `KeyEvent`s. + const REPORT_ALTERNATE_KEYS = 0b0000_0100; + /// Represent all keyboard events as CSI-u sequences. This is required to get repeat/release + /// events for plain-text keys. + const REPORT_ALL_KEYS_AS_ESCAPE_CODES = 0b0000_1000; + // Send the Unicode codepoint as well as the keycode. + // + // *Note*: this is not yet supported by crossterm. + // const REPORT_ASSOCIATED_TEXT = 0b0001_0000; + } +} + /// A command that enables mouse event capturing. /// /// Mouse events can be captured with [read](./fn.read.html)/[poll](./fn.poll.html). +#[cfg(feature = "events")] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct EnableMouseCapture; +#[cfg(feature = "events")] impl Command for EnableMouseCapture { fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { f.write_str(concat!( @@ -265,7 +296,7 @@ impl Command for EnableMouseCapture { } #[cfg(windows)] - fn execute_winapi(&self) -> Result<()> { + fn execute_winapi(&self) -> crate::Result<()> { sys::windows::enable_mouse_capture() } @@ -294,7 +325,7 @@ impl Command for DisableMouseCapture { } #[cfg(windows)] - fn execute_winapi(&self) -> Result<()> { + fn execute_winapi(&self) -> crate::Result<()> { sys::windows::disable_mouse_capture() } @@ -304,31 +335,81 @@ impl Command for DisableMouseCapture { } } -bitflags! { - /// Represents special flags that tell compatible terminals to add extra information to keyboard events. - /// - /// See for more information. - /// - /// Alternate keys and Unicode codepoints are not yet supported by crossterm. - #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] - pub struct KeyboardEnhancementFlags: u8 { - /// Represent Escape and modified keys using CSI-u sequences, so they can be unambiguously - /// read. - const DISAMBIGUATE_ESCAPE_CODES = 0b0000_0001; - /// Add extra events with [`KeyEvent.kind`] set to [`KeyEventKind::Repeat`] or - /// [`KeyEventKind::Release`] when keys are autorepeated or released. - const REPORT_EVENT_TYPES = 0b0000_0010; - // Send [alternate keycodes](https://sw.kovidgoyal.net/kitty/keyboard-protocol/#key-codes) - // in addition to the base keycode. The alternate keycode overrides the base keycode in - // resulting `KeyEvent`s. - const REPORT_ALTERNATE_KEYS = 0b0000_0100; - /// Represent all keyboard events as CSI-u sequences. This is required to get repeat/release - /// events for plain-text keys. - const REPORT_ALL_KEYS_AS_ESCAPE_CODES = 0b0000_1000; - // Send the Unicode codepoint as well as the keycode. - // - // *Note*: this is not yet supported by crossterm. - // const REPORT_ASSOCIATED_TEXT = 0b0001_0000; +/// A command that enables focus event emission. +/// +/// It should be paired with [`DisableFocusChange`] at the end of execution. +/// +/// Focus events can be captured with [read](./fn.read.html)/[poll](./fn.poll.html). +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct EnableFocusChange; + +impl Command for EnableFocusChange { + fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { + f.write_str(csi!("?1004h")) + } + + #[cfg(windows)] + fn execute_winapi(&self) -> crate::Result<()> { + // Focus events are always enabled on Windows + Ok(()) + } +} + +/// A command that disables focus event emission. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DisableFocusChange; + +impl Command for DisableFocusChange { + fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { + f.write_str(csi!("?1004l")) + } + + #[cfg(windows)] + fn execute_winapi(&self) -> crate::Result<()> { + // Focus events can't be disabled on Windows + Ok(()) + } +} + +/// A command that enables [bracketed paste mode](https://en.wikipedia.org/wiki/Bracketed-paste). +/// +/// It should be paired with [`DisableBracketedPaste`] at the end of execution. +/// +/// This is not supported in older Windows terminals without +/// [virtual terminal sequences](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences). +#[cfg(feature = "bracketed-paste")] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct EnableBracketedPaste; + +#[cfg(feature = "bracketed-paste")] +impl Command for EnableBracketedPaste { + fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { + f.write_str(csi!("?2004h")) + } + + #[cfg(windows)] + fn execute_winapi(&self) -> crate::Result<()> { + Err(std::io::Error::new( + std::io::ErrorKind::Unsupported, + "Bracketed paste not implemented in the legacy Windows API.", + )) + } +} + +/// A command that disables bracketed paste mode. +#[cfg(feature = "bracketed-paste")] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DisableBracketedPaste; + +#[cfg(feature = "bracketed-paste")] +impl Command for DisableBracketedPaste { + fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { + f.write_str(csi!("?2004l")) + } + + #[cfg(windows)] + fn execute_winapi(&self) -> crate::Result<()> { + Ok(()) } } @@ -377,7 +458,9 @@ impl Command for PushKeyboardEnhancementFlags { } #[cfg(windows)] - fn execute_winapi(&self) -> Result<()> { + fn execute_winapi(&self) -> crate::Result<()> { + use std::io; + Err(io::Error::new( io::ErrorKind::Unsupported, "Keyboard progressive enhancement not implemented for the legacy Windows API.", @@ -404,7 +487,9 @@ impl Command for PopKeyboardEnhancementFlags { } #[cfg(windows)] - fn execute_winapi(&self) -> Result<()> { + fn execute_winapi(&self) -> crate::Result<()> { + use std::io; + Err(io::Error::new( io::ErrorKind::Unsupported, "Keyboard progressive enhancement not implemented for the legacy Windows API.", @@ -417,84 +502,6 @@ impl Command for PopKeyboardEnhancementFlags { } } -/// A command that enables focus event emission. -/// -/// It should be paired with [`DisableFocusChange`] at the end of execution. -/// -/// Focus events can be captured with [read](./fn.read.html)/[poll](./fn.poll.html). -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct EnableFocusChange; - -impl Command for EnableFocusChange { - fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { - f.write_str(csi!("?1004h")) - } - - #[cfg(windows)] - fn execute_winapi(&self) -> Result<()> { - // Focus events are always enabled on Windows - Ok(()) - } -} - -/// A command that disables focus event emission. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct DisableFocusChange; - -impl Command for DisableFocusChange { - fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { - f.write_str(csi!("?1004l")) - } - - #[cfg(windows)] - fn execute_winapi(&self) -> Result<()> { - // Focus events can't be disabled on Windows - Ok(()) - } -} - -/// A command that enables [bracketed paste mode](https://en.wikipedia.org/wiki/Bracketed-paste). -/// -/// It should be paired with [`DisableBracketedPaste`] at the end of execution. -/// -/// This is not supported in older Windows terminals without -/// [virtual terminal sequences](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences). -#[cfg(feature = "bracketed-paste")] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct EnableBracketedPaste; - -#[cfg(feature = "bracketed-paste")] -impl Command for EnableBracketedPaste { - fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { - f.write_str(csi!("?2004h")) - } - - #[cfg(windows)] - fn execute_winapi(&self) -> Result<()> { - Err(io::Error::new( - io::ErrorKind::Unsupported, - "Bracketed paste not implemented in the legacy Windows API.", - )) - } -} - -/// A command that disables bracketed paste mode. -#[cfg(feature = "bracketed-paste")] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct DisableBracketedPaste; - -#[cfg(feature = "bracketed-paste")] -impl Command for DisableBracketedPaste { - fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { - f.write_str(csi!("?2004l")) - } - - #[cfg(windows)] - fn execute_winapi(&self) -> Result<()> { - Ok(()) - } -} - /// Represents an event. #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(not(feature = "bracketed-paste"), derive(Copy))] diff --git a/src/event/read.rs b/src/event/read.rs index 72b0830..446163f 100644 --- a/src/event/read.rs +++ b/src/event/read.rs @@ -1,12 +1,14 @@ use std::{collections::vec_deque::VecDeque, io, time::Duration}; #[cfg(unix)] -use super::source::unix::UnixInternalEventSource; +use crate::event::source::unix::UnixInternalEventSource; #[cfg(windows)] -use super::source::windows::WindowsEventSource; +use crate::event::source::windows::WindowsEventSource; #[cfg(feature = "event-stream")] -use super::sys::Waker; -use super::{filter::Filter, source::EventSource, timeout::PollTimeout, InternalEvent, Result}; +use crate::event::sys::Waker; +use crate::event::{filter::Filter, source::EventSource, timeout::PollTimeout, InternalEvent}; +use crate::Result; + /// Can be used to read `InternalEvent`s. pub(crate) struct InternalEventReader { events: VecDeque, diff --git a/src/event/source/unix/mio.rs b/src/event/source/unix/mio.rs index 67bda37..7e0075e 100644 --- a/src/event/source/unix/mio.rs +++ b/src/event/source/unix/mio.rs @@ -8,14 +8,9 @@ use crate::Result; #[cfg(feature = "event-stream")] use crate::event::sys::Waker; use crate::event::{ - source::EventSource, - sys::unix::{ - file_descriptor::{tty_fd, FileDesc}, - parse::parse_event, - }, - timeout::PollTimeout, - Event, InternalEvent, + source::EventSource, sys::unix::parse::parse_event, timeout::PollTimeout, Event, InternalEvent, }; +use crate::terminal::sys::file_descriptor::{tty_fd, FileDesc}; // Tokens to identify file descriptor const TTY_TOKEN: Token = Token(0); diff --git a/src/event/source/unix/tty.rs b/src/event/source/unix/tty.rs index ca77e3d..aacfcad 100644 --- a/src/event/source/unix/tty.rs +++ b/src/event/source/unix/tty.rs @@ -11,15 +11,8 @@ use filedescriptor::{poll, pollfd, POLLIN}; #[cfg(feature = "event-stream")] use crate::event::sys::Waker; - -use crate::event::{ - source::EventSource, - sys::unix::{ - file_descriptor::{tty_fd, FileDesc}, - parse::parse_event, - }, - InternalEvent, -}; +use crate::event::{source::EventSource, sys::unix::parse::parse_event, InternalEvent}; +use crate::terminal::sys::file_descriptor::{tty_fd, FileDesc}; /// Holds a prototypical Waker and a receiver we can wait on when doing select(). #[cfg(feature = "event-stream")] diff --git a/src/event/source/windows.rs b/src/event/source/windows.rs index 32deb79..9c05bb3 100644 --- a/src/event/source/windows.rs +++ b/src/event/source/windows.rs @@ -8,12 +8,12 @@ use crate::event::{ }; #[cfg(feature = "event-stream")] -use super::super::sys::Waker; -use super::super::{ +use crate::event::sys::Waker; +use crate::event::{ source::EventSource, sys::windows::parse::{handle_key_event, handle_mouse_event}, timeout::PollTimeout, - InternalEvent, Result, + InternalEvent, }; pub(crate) struct WindowsEventSource { @@ -24,7 +24,7 @@ pub(crate) struct WindowsEventSource { } impl WindowsEventSource { - pub(crate) fn new() -> Result { + pub(crate) fn new() -> crate::Result { let console = Console::from(Handle::current_in_handle()?); Ok(WindowsEventSource { console, @@ -41,7 +41,7 @@ impl WindowsEventSource { } impl EventSource for WindowsEventSource { - fn try_read(&mut self, timeout: Option) -> Result> { + fn try_read(&mut self, timeout: Option) -> crate::Result> { let poll_timeout = PollTimeout::new(timeout); loop { diff --git a/src/event/stream.rs b/src/event/stream.rs index 602d54a..c15d045 100644 --- a/src/event/stream.rs +++ b/src/event/stream.rs @@ -14,7 +14,7 @@ use futures_core::stream::Stream; use crate::Result; -use super::{ +use crate::event::{ filter::EventFilter, lock_internal_event_reader, poll_internal, read_internal, sys::Waker, Event, InternalEvent, }; diff --git a/src/event/sys/unix.rs b/src/event/sys/unix.rs index 19321f6..2106ca0 100644 --- a/src/event/sys/unix.rs +++ b/src/event/sys/unix.rs @@ -1,5 +1,5 @@ #[cfg(feature = "event-stream")] pub(crate) mod waker; -pub(crate) mod file_descriptor; +#[cfg(feature = "events")] pub(crate) mod parse; diff --git a/src/event/sys/unix/waker/mio.rs b/src/event/sys/unix/waker/mio.rs index 4509e9b..da4b4e3 100644 --- a/src/event/sys/unix/waker/mio.rs +++ b/src/event/sys/unix/waker/mio.rs @@ -1,6 +1,6 @@ use std::sync::{Arc, Mutex}; -use mio::{Registry, Token}; +use ::mio::{Registry, Token}; use crate::Result; @@ -8,7 +8,7 @@ use crate::Result; /// This type wraps `mio::Waker`, for more information see its documentation. #[derive(Clone, Debug)] pub(crate) struct Waker { - inner: Arc>, + inner: Arc>, } impl Waker { diff --git a/src/event/sys/windows.rs b/src/event/sys/windows.rs index af20497..60b8c5e 100644 --- a/src/event/sys/windows.rs +++ b/src/event/sys/windows.rs @@ -8,11 +8,10 @@ use crossterm_winapi::{ConsoleMode, Handle}; use crate::Result; -#[cfg(feature = "event-stream")] -pub(crate) mod waker; - pub(crate) mod parse; pub(crate) mod poll; +#[cfg(feature = "event-stream")] +pub(crate) mod waker; const ENABLE_MOUSE_MODE: u32 = 0x0010 | 0x0080 | 0x0008; diff --git a/src/event/sys/windows/parse.rs b/src/event/sys/windows/parse.rs index beb0b51..8bd867d 100644 --- a/src/event/sys/windows/parse.rs +++ b/src/event/sys/windows/parse.rs @@ -1,4 +1,4 @@ -use crossterm_winapi::{ControlKeyState, EventFlags, KeyEventRecord, MouseEvent, ScreenBuffer}; +use crossterm_winapi::{ControlKeyState, EventFlags, KeyEventRecord, ScreenBuffer}; use winapi::um::{ wincon::{ CAPSLOCK_ON, LEFT_ALT_PRESSED, LEFT_CTRL_PRESSED, RIGHT_ALT_PRESSED, RIGHT_CTRL_PRESSED, @@ -13,7 +13,10 @@ use winapi::um::{ }; use crate::{ - event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseButton, MouseEventKind}, + event::{ + Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseButton, MouseEvent, + MouseEventKind, + }, Result, }; @@ -25,7 +28,7 @@ pub struct MouseButtonsPressed { } pub(crate) fn handle_mouse_event( - mouse_event: MouseEvent, + mouse_event: crossterm_winapi::MouseEvent, buttons_pressed: &MouseButtonsPressed, ) -> Option { if let Ok(Some(event)) = parse_mouse_event_record(&mouse_event, buttons_pressed) { @@ -304,9 +307,9 @@ pub fn parse_relative_y(y: i16) -> Result { } fn parse_mouse_event_record( - event: &MouseEvent, + event: &crossterm_winapi::MouseEvent, buttons_pressed: &MouseButtonsPressed, -) -> Result> { +) -> Result> { let modifiers = KeyModifiers::from(&event.control_key_state); let xpos = event.mouse_position.x as u16; @@ -363,7 +366,7 @@ fn parse_mouse_event_record( _ => None, }; - Ok(kind.map(|kind| crate::event::MouseEvent { + Ok(kind.map(|kind| MouseEvent { kind, column: xpos, row: ypos, diff --git a/src/lib.rs b/src/lib.rs index d8d9f86..5e9e66f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -242,6 +242,7 @@ pub use crate::{ /// A module to work with the terminal cursor pub mod cursor; /// A module to read events. +#[cfg(feature = "events")] pub mod event; /// A module to apply attributes and colors on your text. pub mod style; diff --git a/src/terminal.rs b/src/terminal.rs index 282454d..36ccda1 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -98,6 +98,7 @@ use crate::{csi, impl_display, Result}; pub(crate) mod sys; +#[cfg(feature = "events")] pub use sys::supports_keyboard_enhancement; /// Tells whether the raw mode is enabled. diff --git a/src/terminal/sys.rs b/src/terminal/sys.rs index c856c69..527e194 100644 --- a/src/terminal/sys.rs +++ b/src/terminal/sys.rs @@ -1,10 +1,12 @@ //! This module provides platform related functions. #[cfg(unix)] +#[cfg(feature = "events")] pub use self::unix::supports_keyboard_enhancement; #[cfg(unix)] pub(crate) use self::unix::{disable_raw_mode, enable_raw_mode, is_raw_mode_enabled, size}; #[cfg(windows)] +#[cfg(feature = "events")] pub use self::windows::supports_keyboard_enhancement; #[cfg(windows)] pub(crate) use self::windows::{ @@ -15,5 +17,7 @@ pub(crate) use self::windows::{ #[cfg(windows)] mod windows; +#[cfg(unix)] +pub mod file_descriptor; #[cfg(unix)] mod unix; diff --git a/src/event/sys/unix/file_descriptor.rs b/src/terminal/sys/file_descriptor.rs similarity index 100% rename from src/event/sys/unix/file_descriptor.rs rename to src/terminal/sys/file_descriptor.rs diff --git a/src/terminal/sys/unix.rs b/src/terminal/sys/unix.rs index b084b74..c0119da 100644 --- a/src/terminal/sys/unix.rs +++ b/src/terminal/sys/unix.rs @@ -1,21 +1,18 @@ //! UNIX related logic for terminal manipulation. -use std::fs::File; -use std::io::Write; -use std::os::unix::io::{IntoRawFd, RawFd}; -use std::time::Duration; -use std::{io, mem, process}; - +use crate::terminal::sys::file_descriptor::{tty_fd, FileDesc}; use libc::{ cfmakeraw, ioctl, tcgetattr, tcsetattr, termios as Termios, winsize, STDOUT_FILENO, TCSANOW, TIOCGWINSZ, }; use parking_lot::Mutex; +use std::fs::File; + +use std::os::unix::io::{IntoRawFd, RawFd}; + +use std::{io, mem, process}; use crate::error::Result; -use crate::event::filter::{KeyboardEnhancementFlagsFilter, PrimaryDeviceAttributesFilter}; -use crate::event::sys::unix::file_descriptor::{tty_fd, FileDesc}; -use crate::event::{poll_internal, read_internal, InternalEvent}; // Some(Termios) -> we're in the raw mode and this is the previous mode // None -> we're not in the raw mode @@ -96,6 +93,7 @@ pub(crate) fn disable_raw_mode() -> Result<()> { /// /// On unix systems, this function will block and possibly time out while /// [`crossterm::event::read`](crate::event::read) or [`crossterm::event::poll`](crate::event::poll) are being called. +#[cfg(feature = "events")] pub fn supports_keyboard_enhancement() -> Result { if is_raw_mode_enabled() { read_supports_keyboard_enhancement_raw() @@ -104,6 +102,7 @@ pub fn supports_keyboard_enhancement() -> Result { } } +#[cfg(feature = "events")] fn read_supports_keyboard_enhancement_flags() -> Result { enable_raw_mode()?; let flags = read_supports_keyboard_enhancement_raw(); @@ -111,7 +110,15 @@ fn read_supports_keyboard_enhancement_flags() -> Result { flags } +#[cfg(feature = "events")] fn read_supports_keyboard_enhancement_raw() -> Result { + use crate::event::{ + filter::{KeyboardEnhancementFlagsFilter, PrimaryDeviceAttributesFilter}, + poll_internal, read_internal, InternalEvent, + }; + use std::io::Write; + use std::time::Duration; + // This is the recommended method for testing support for the keyboard enhancement protocol. // We send a query for the flags supported by the terminal and then the primary device attributes // query. If we receive the primary device attributes response but not the keyboard enhancement diff --git a/src/terminal/sys/windows.rs b/src/terminal/sys/windows.rs index b5592b7..9cf4b1d 100644 --- a/src/terminal/sys/windows.rs +++ b/src/terminal/sys/windows.rs @@ -61,6 +61,7 @@ pub(crate) fn size() -> Result<(u16, u16)> { /// Queries the terminal's support for progressive keyboard enhancement. /// /// This always returns `Ok(false)` on Windows. +#[cfg(feature = "events")] pub fn supports_keyboard_enhancement() -> Result { Ok(false) }