crossterm/
event.rs

1//! # Event
2//!
3//! The `event` module provides the functionality to read keyboard, mouse and terminal resize events.
4//!
5//! * The [`read`](fn.read.html) function returns an [`Event`](enum.Event.html) immediately
6//! (if available) or blocks until an [`Event`](enum.Event.html) is available.
7//!
8//! * The [`poll`](fn.poll.html) function allows you to check if there is or isn't an [`Event`](enum.Event.html) available
9//! within the given period of time. In other words - if subsequent call to the [`read`](fn.read.html)
10//! function will block or not.
11//!
12//! It's **not allowed** to call these functions from different threads or combine them with the
13//! [`EventStream`](struct.EventStream.html). You're allowed to either:
14//!
15//! * use the [`read`](fn.read.html) & [`poll`](fn.poll.html) functions on any, but same, thread
16//! * or the [`EventStream`](struct.EventStream.html).
17//!
18//! **Make sure to enable [raw mode](../terminal/index.html#raw-mode) in order for keyboard events to work properly**
19//!
20//! ## Mouse and Focus Events
21//!
22//! Mouse and focus events are not enabled by default. You have to enable them with the
23//! [`EnableMouseCapture`](struct.EnableMouseCapture.html) / [`EnableFocusChange`](struct.EnableFocusChange.html) command.
24//! See [Command API](../index.html#command-api) for more information.
25//!
26//! ## Examples
27//!
28//! Blocking read:
29//!
30//! ```no_run
31//! #![cfg(feature = "bracketed-paste")]
32//! use crossterm::{
33//!     event::{
34//!         read, DisableBracketedPaste, DisableFocusChange, DisableMouseCapture, EnableBracketedPaste,
35//!         EnableFocusChange, EnableMouseCapture, Event,
36//!     },
37//!     execute,
38//! };
39//!
40//! fn print_events() -> std::io::Result<()> {
41//!     execute!(
42//!          std::io::stdout(),
43//!          EnableBracketedPaste,
44//!          EnableFocusChange,
45//!          EnableMouseCapture
46//!     )?;
47//!     loop {
48//!         // `read()` blocks until an `Event` is available
49//!         match read()? {
50//!             Event::FocusGained => println!("FocusGained"),
51//!             Event::FocusLost => println!("FocusLost"),
52//!             Event::Key(event) => println!("{:?}", event),
53//!             Event::Mouse(event) => println!("{:?}", event),
54//!             #[cfg(feature = "bracketed-paste")]
55//!             Event::Paste(data) => println!("{:?}", data),
56//!             Event::Resize(width, height) => println!("New size {}x{}", width, height),
57//!         }
58//!     }
59//!     execute!(
60//!         std::io::stdout(),
61//!         DisableBracketedPaste,
62//!         DisableFocusChange,
63//!         DisableMouseCapture
64//!     )?;
65//!     Ok(())
66//! }
67//! ```
68//!
69//! Non-blocking read:
70//!
71//! ```no_run
72//! #![cfg(feature = "bracketed-paste")]
73//! use std::{time::Duration, io};
74//!
75//! use crossterm::{
76//!     event::{
77//!         poll, read, DisableBracketedPaste, DisableFocusChange, DisableMouseCapture,
78//!         EnableBracketedPaste, EnableFocusChange, EnableMouseCapture, Event,
79//!     },
80//!     execute,
81//! };
82//!
83//! fn print_events() -> io::Result<()> {
84//!     execute!(
85//!          std::io::stdout(),
86//!          EnableBracketedPaste,
87//!          EnableFocusChange,
88//!          EnableMouseCapture
89//!     )?;
90//!     loop {
91//!         // `poll()` waits for an `Event` for a given time period
92//!         if poll(Duration::from_millis(500))? {
93//!             // It's guaranteed that the `read()` won't block when the `poll()`
94//!             // function returns `true`
95//!             match read()? {
96//!                 Event::FocusGained => println!("FocusGained"),
97//!                 Event::FocusLost => println!("FocusLost"),
98//!                 Event::Key(event) => println!("{:?}", event),
99//!                 Event::Mouse(event) => println!("{:?}", event),
100//!                 #[cfg(feature = "bracketed-paste")]
101//!                 Event::Paste(data) => println!("Pasted {:?}", data),
102//!                 Event::Resize(width, height) => println!("New size {}x{}", width, height),
103//!             }
104//!         } else {
105//!             // Timeout expired and no `Event` is available
106//!         }
107//!     }
108//!     execute!(
109//!         std::io::stdout(),
110//!         DisableBracketedPaste,
111//!         DisableFocusChange,
112//!         DisableMouseCapture
113//!     )?;
114//!     Ok(())
115//! }
116//! ```
117//!
118//! Check the [examples](https://github.com/crossterm-rs/crossterm/tree/master/examples) folder for more of
119//! them (`event-*`).
120
121pub(crate) mod filter;
122pub(crate) mod read;
123pub(crate) mod source;
124#[cfg(feature = "event-stream")]
125pub(crate) mod stream;
126pub(crate) mod sys;
127pub(crate) mod timeout;
128
129#[cfg(feature = "derive-more")]
130use derive_more::derive::IsVariant;
131#[cfg(feature = "event-stream")]
132pub use stream::EventStream;
133
134use crate::event::{
135    filter::{EventFilter, Filter},
136    read::InternalEventReader,
137    timeout::PollTimeout,
138};
139use crate::{csi, Command};
140use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
141use std::fmt::{self, Display};
142use std::time::Duration;
143
144use bitflags::bitflags;
145use std::hash::{Hash, Hasher};
146
147/// Static instance of `InternalEventReader`.
148/// This needs to be static because there can be one event reader.
149static INTERNAL_EVENT_READER: Mutex<Option<InternalEventReader>> = parking_lot::const_mutex(None);
150
151pub(crate) fn lock_internal_event_reader() -> MappedMutexGuard<'static, InternalEventReader> {
152    MutexGuard::map(INTERNAL_EVENT_READER.lock(), |reader| {
153        reader.get_or_insert_with(InternalEventReader::default)
154    })
155}
156fn try_lock_internal_event_reader_for(
157    duration: Duration,
158) -> Option<MappedMutexGuard<'static, InternalEventReader>> {
159    Some(MutexGuard::map(
160        INTERNAL_EVENT_READER.try_lock_for(duration)?,
161        |reader| reader.get_or_insert_with(InternalEventReader::default),
162    ))
163}
164
165/// Checks if there is an [`Event`](enum.Event.html) available.
166///
167/// Returns `Ok(true)` if an [`Event`](enum.Event.html) is available otherwise it returns `Ok(false)`.
168///
169/// `Ok(true)` guarantees that subsequent call to the [`read`](fn.read.html) function
170/// won't block.
171///
172/// # Arguments
173///
174/// * `timeout` - maximum waiting time for event availability
175///
176/// # Examples
177///
178/// Return immediately:
179///
180/// ```no_run
181/// use std::{time::Duration, io};
182/// use crossterm::{event::poll};
183///
184/// fn is_event_available() -> io::Result<bool> {
185///     // Zero duration says that the `poll` function must return immediately
186///     // with an `Event` availability information
187///     poll(Duration::from_secs(0))
188/// }
189/// ```
190///
191/// Wait up to 100ms:
192///
193/// ```no_run
194/// use std::{time::Duration, io};
195///
196/// use crossterm::event::poll;
197///
198/// fn is_event_available() -> io::Result<bool> {
199///     // Wait for an `Event` availability for 100ms. It returns immediately
200///     // if an `Event` is/becomes available.
201///     poll(Duration::from_millis(100))
202/// }
203/// ```
204pub fn poll(timeout: Duration) -> std::io::Result<bool> {
205    poll_internal(Some(timeout), &EventFilter)
206}
207
208/// Reads a single [`Event`](enum.Event.html).
209///
210/// This function blocks until an [`Event`](enum.Event.html) is available. Combine it with the
211/// [`poll`](fn.poll.html) function to get non-blocking reads.
212///
213/// # Examples
214///
215/// Blocking read:
216///
217/// ```no_run
218/// use crossterm::event::read;
219/// use std::io;
220///
221/// fn print_events() -> io::Result<bool> {
222///     loop {
223///         // Blocks until an `Event` is available
224///         println!("{:?}", read()?);
225///     }
226/// }
227/// ```
228///
229/// Non-blocking read:
230///
231/// ```no_run
232/// use std::time::Duration;
233/// use std::io;
234///
235/// use crossterm::event::{read, poll};
236///
237/// fn print_events() -> io::Result<bool> {
238///     loop {
239///         if poll(Duration::from_millis(100))? {
240///             // It's guaranteed that `read` won't block, because `poll` returned
241///             // `Ok(true)`.
242///             println!("{:?}", read()?);
243///         } else {
244///             // Timeout expired, no `Event` is available
245///         }
246///     }
247/// }
248/// ```
249pub fn read() -> std::io::Result<Event> {
250    match read_internal(&EventFilter)? {
251        InternalEvent::Event(event) => Ok(event),
252        #[cfg(unix)]
253        _ => unreachable!(),
254    }
255}
256
257/// Polls to check if there are any `InternalEvent`s that can be read within the given duration.
258pub(crate) fn poll_internal<F>(timeout: Option<Duration>, filter: &F) -> std::io::Result<bool>
259where
260    F: Filter,
261{
262    let (mut reader, timeout) = if let Some(timeout) = timeout {
263        let poll_timeout = PollTimeout::new(Some(timeout));
264        if let Some(reader) = try_lock_internal_event_reader_for(timeout) {
265            (reader, poll_timeout.leftover())
266        } else {
267            return Ok(false);
268        }
269    } else {
270        (lock_internal_event_reader(), None)
271    };
272    reader.poll(timeout, filter)
273}
274
275/// Reads a single `InternalEvent`.
276pub(crate) fn read_internal<F>(filter: &F) -> std::io::Result<InternalEvent>
277where
278    F: Filter,
279{
280    let mut reader = lock_internal_event_reader();
281    reader.read(filter)
282}
283
284bitflags! {
285    /// Represents special flags that tell compatible terminals to add extra information to keyboard events.
286    ///
287    /// See <https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement> for more information.
288    ///
289    /// Alternate keys and Unicode codepoints are not yet supported by crossterm.
290    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent))]
291    #[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
292    pub struct KeyboardEnhancementFlags: u8 {
293        /// Represent Escape and modified keys using CSI-u sequences, so they can be unambiguously
294        /// read.
295        const DISAMBIGUATE_ESCAPE_CODES = 0b0000_0001;
296        /// Add extra events with [`KeyEvent.kind`] set to [`KeyEventKind::Repeat`] or
297        /// [`KeyEventKind::Release`] when keys are autorepeated or released.
298        const REPORT_EVENT_TYPES = 0b0000_0010;
299        /// Send [alternate keycodes](https://sw.kovidgoyal.net/kitty/keyboard-protocol/#key-codes)
300        /// in addition to the base keycode. The alternate keycode overrides the base keycode in
301        /// resulting `KeyEvent`s.
302        const REPORT_ALTERNATE_KEYS = 0b0000_0100;
303        /// Represent all keyboard events as CSI-u sequences. This is required to get repeat/release
304        /// events for plain-text keys.
305        const REPORT_ALL_KEYS_AS_ESCAPE_CODES = 0b0000_1000;
306        // Send the Unicode codepoint as well as the keycode.
307        //
308        // *Note*: this is not yet supported by crossterm.
309        // const REPORT_ASSOCIATED_TEXT = 0b0001_0000;
310    }
311}
312
313/// A command that enables mouse event capturing.
314///
315/// Mouse events can be captured with [read](./fn.read.html)/[poll](./fn.poll.html).
316#[cfg(feature = "events")]
317#[derive(Debug, Clone, Copy, PartialEq, Eq)]
318pub struct EnableMouseCapture;
319
320#[cfg(feature = "events")]
321impl Command for EnableMouseCapture {
322    fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
323        f.write_str(concat!(
324            // Normal tracking: Send mouse X & Y on button press and release
325            csi!("?1000h"),
326            // Button-event tracking: Report button motion events (dragging)
327            csi!("?1002h"),
328            // Any-event tracking: Report all motion events
329            csi!("?1003h"),
330            // RXVT mouse mode: Allows mouse coordinates of >223
331            csi!("?1015h"),
332            // SGR mouse mode: Allows mouse coordinates of >223, preferred over RXVT mode
333            csi!("?1006h"),
334        ))
335    }
336
337    #[cfg(windows)]
338    fn execute_winapi(&self) -> std::io::Result<()> {
339        sys::windows::enable_mouse_capture()
340    }
341
342    #[cfg(windows)]
343    fn is_ansi_code_supported(&self) -> bool {
344        false
345    }
346}
347
348/// A command that disables mouse event capturing.
349///
350/// Mouse events can be captured with [read](./fn.read.html)/[poll](./fn.poll.html).
351#[derive(Debug, Clone, Copy, PartialEq, Eq)]
352pub struct DisableMouseCapture;
353
354impl Command for DisableMouseCapture {
355    fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
356        f.write_str(concat!(
357            // The inverse commands of EnableMouseCapture, in reverse order.
358            csi!("?1006l"),
359            csi!("?1015l"),
360            csi!("?1003l"),
361            csi!("?1002l"),
362            csi!("?1000l"),
363        ))
364    }
365
366    #[cfg(windows)]
367    fn execute_winapi(&self) -> std::io::Result<()> {
368        sys::windows::disable_mouse_capture()
369    }
370
371    #[cfg(windows)]
372    fn is_ansi_code_supported(&self) -> bool {
373        false
374    }
375}
376
377/// A command that enables focus event emission.
378///
379/// It should be paired with [`DisableFocusChange`] at the end of execution.
380///
381/// Focus events can be captured with [read](./fn.read.html)/[poll](./fn.poll.html).
382#[derive(Debug, Clone, Copy, PartialEq, Eq)]
383pub struct EnableFocusChange;
384
385impl Command for EnableFocusChange {
386    fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
387        f.write_str(csi!("?1004h"))
388    }
389
390    #[cfg(windows)]
391    fn execute_winapi(&self) -> std::io::Result<()> {
392        // Focus events are always enabled on Windows
393        Ok(())
394    }
395}
396
397/// A command that disables focus event emission.
398#[derive(Debug, Clone, Copy, PartialEq, Eq)]
399pub struct DisableFocusChange;
400
401impl Command for DisableFocusChange {
402    fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
403        f.write_str(csi!("?1004l"))
404    }
405
406    #[cfg(windows)]
407    fn execute_winapi(&self) -> std::io::Result<()> {
408        // Focus events can't be disabled on Windows
409        Ok(())
410    }
411}
412
413/// A command that enables [bracketed paste mode](https://en.wikipedia.org/wiki/Bracketed-paste).
414///
415/// It should be paired with [`DisableBracketedPaste`] at the end of execution.
416///
417/// This is not supported in older Windows terminals without
418/// [virtual terminal sequences](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences).
419#[cfg(feature = "bracketed-paste")]
420#[derive(Debug, Clone, Copy, PartialEq, Eq)]
421pub struct EnableBracketedPaste;
422
423#[cfg(feature = "bracketed-paste")]
424impl Command for EnableBracketedPaste {
425    fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
426        f.write_str(csi!("?2004h"))
427    }
428
429    #[cfg(windows)]
430    fn execute_winapi(&self) -> std::io::Result<()> {
431        Err(std::io::Error::new(
432            std::io::ErrorKind::Unsupported,
433            "Bracketed paste not implemented in the legacy Windows API.",
434        ))
435    }
436}
437
438/// A command that disables bracketed paste mode.
439#[cfg(feature = "bracketed-paste")]
440#[derive(Debug, Clone, Copy, PartialEq, Eq)]
441pub struct DisableBracketedPaste;
442
443#[cfg(feature = "bracketed-paste")]
444impl Command for DisableBracketedPaste {
445    fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
446        f.write_str(csi!("?2004l"))
447    }
448
449    #[cfg(windows)]
450    fn execute_winapi(&self) -> std::io::Result<()> {
451        Ok(())
452    }
453}
454
455/// A command that enables the [kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/), which adds extra information to keyboard events and removes ambiguity for modifier keys.
456///
457/// It should be paired with [`PopKeyboardEnhancementFlags`] at the end of execution.
458///
459/// Example usage:
460/// ```no_run
461/// use std::io::{Write, stdout};
462/// use crossterm::execute;
463/// use crossterm::event::{
464///     KeyboardEnhancementFlags,
465///     PushKeyboardEnhancementFlags,
466///     PopKeyboardEnhancementFlags
467/// };
468///
469/// let mut stdout = stdout();
470///
471/// execute!(
472///     stdout,
473///     PushKeyboardEnhancementFlags(
474///         KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
475///     )
476/// );
477///
478/// // ...
479///
480/// execute!(stdout, PopKeyboardEnhancementFlags);
481/// ```
482///
483/// Note that, currently, only the following support this protocol:
484/// * [kitty terminal](https://sw.kovidgoyal.net/kitty/)
485/// * [foot terminal](https://codeberg.org/dnkl/foot/issues/319)
486/// * [WezTerm terminal](https://wezfurlong.org/wezterm/config/lua/config/enable_kitty_keyboard.html)
487/// * [alacritty terminal](https://github.com/alacritty/alacritty/issues/6378)
488/// * [notcurses library](https://github.com/dankamongmen/notcurses/issues/2131)
489/// * [neovim text editor](https://github.com/neovim/neovim/pull/18181)
490/// * [kakoune text editor](https://github.com/mawww/kakoune/issues/4103)
491/// * [dte text editor](https://gitlab.com/craigbarnes/dte/-/issues/138)
492#[derive(Debug, Clone, Copy, PartialEq, Eq)]
493pub struct PushKeyboardEnhancementFlags(pub KeyboardEnhancementFlags);
494
495impl Command for PushKeyboardEnhancementFlags {
496    fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
497        write!(f, "{}{}u", csi!(">"), self.0.bits())
498    }
499
500    #[cfg(windows)]
501    fn execute_winapi(&self) -> std::io::Result<()> {
502        use std::io;
503
504        Err(io::Error::new(
505            io::ErrorKind::Unsupported,
506            "Keyboard progressive enhancement not implemented for the legacy Windows API.",
507        ))
508    }
509
510    #[cfg(windows)]
511    fn is_ansi_code_supported(&self) -> bool {
512        false
513    }
514}
515
516/// A command that disables extra kinds of keyboard events.
517///
518/// Specifically, it pops one level of keyboard enhancement flags.
519///
520/// See [`PushKeyboardEnhancementFlags`] and <https://sw.kovidgoyal.net/kitty/keyboard-protocol/> for more information.
521#[derive(Debug, Clone, Copy, PartialEq, Eq)]
522pub struct PopKeyboardEnhancementFlags;
523
524impl Command for PopKeyboardEnhancementFlags {
525    fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
526        f.write_str(csi!("<1u"))
527    }
528
529    #[cfg(windows)]
530    fn execute_winapi(&self) -> std::io::Result<()> {
531        use std::io;
532
533        Err(io::Error::new(
534            io::ErrorKind::Unsupported,
535            "Keyboard progressive enhancement not implemented for the legacy Windows API.",
536        ))
537    }
538
539    #[cfg(windows)]
540    fn is_ansi_code_supported(&self) -> bool {
541        false
542    }
543}
544
545/// Represents an event.
546#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
547#[cfg_attr(feature = "derive-more", derive(IsVariant))]
548#[cfg_attr(not(feature = "bracketed-paste"), derive(Copy))]
549#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Hash)]
550pub enum Event {
551    /// The terminal gained focus
552    FocusGained,
553    /// The terminal lost focus
554    FocusLost,
555    /// A single key event with additional pressed modifiers.
556    Key(KeyEvent),
557    /// A single mouse event with additional pressed modifiers.
558    Mouse(MouseEvent),
559    /// A string that was pasted into the terminal. Only emitted if bracketed paste has been
560    /// enabled.
561    #[cfg(feature = "bracketed-paste")]
562    Paste(String),
563    /// An resize event with new dimensions after resize (columns, rows).
564    /// **Note** that resize events can occur in batches.
565    Resize(u16, u16),
566}
567
568impl Event {
569    /// Returns `true` if the event is a key press event.
570    ///
571    /// This is useful for waiting for any key press event, regardless of the key that was pressed.
572    ///
573    /// Returns `false` for key release and repeat events (as well as for non-key events).
574    ///
575    /// # Examples
576    ///
577    /// The following code runs a loop that processes events until a key press event is encountered:
578    ///
579    /// ```no_run
580    /// use crossterm::event;
581    ///
582    /// while !event::read()?.is_key_press() {
583    ///     // ...
584    /// }
585    /// # Ok::<(), std::io::Error>(())
586    /// ```
587    #[inline]
588    pub fn is_key_press(&self) -> bool {
589        matches!(
590            self,
591            Event::Key(KeyEvent {
592                kind: KeyEventKind::Press,
593                ..
594            })
595        )
596    }
597
598    /// Returns `true` if the event is a key release event.
599    #[inline]
600    pub fn is_key_release(&self) -> bool {
601        matches!(
602            self,
603            Event::Key(KeyEvent {
604                kind: KeyEventKind::Release,
605                ..
606            })
607        )
608    }
609
610    /// Returns `true` if the event is a key repeat event.
611    #[inline]
612    pub fn is_key_repeat(&self) -> bool {
613        matches!(
614            self,
615            Event::Key(KeyEvent {
616                kind: KeyEventKind::Repeat,
617                ..
618            })
619        )
620    }
621
622    /// Returns the key event if the event is a key event, otherwise `None`.
623    ///
624    /// This is a convenience method that makes apps that only care about key events easier to write.
625    ///
626    /// # Examples
627    ///
628    /// The following code runs a loop that only processes key events:
629    ///
630    /// ```no_run
631    /// use crossterm::event;
632    ///
633    /// while let Some(key_event) = event::read()?.as_key_event() {
634    ///     // ...
635    /// }
636    /// # std::io::Result::Ok(())
637    /// ```
638    #[inline]
639    pub fn as_key_event(&self) -> Option<KeyEvent> {
640        match self {
641            Event::Key(event) => Some(*event),
642            _ => None,
643        }
644    }
645
646    /// Returns an Option containing the KeyEvent if the event is a key press event.
647    ///
648    /// This is a convenience method that makes apps that only care about key press events, and not
649    /// key release or repeat events (or non-key events), easier to write.
650    ///
651    /// Returns `None` for key release and repeat events (as well as for non-key events).
652    ///
653    /// # Examples
654    ///
655    /// The following code runs a loop that only processes key press events:
656    ///
657    /// ```no_run
658    /// use crossterm::event;
659    ///
660    /// while let Ok(event) = event::read() {
661    ///     if let Some(key) = event.as_key_press_event() {
662    ///         // ...
663    ///     }
664    /// }
665    #[inline]
666    pub fn as_key_press_event(&self) -> Option<KeyEvent> {
667        match self {
668            Event::Key(event) if self.is_key_press() => Some(*event),
669            _ => None,
670        }
671    }
672
673    /// Returns an Option containing the `KeyEvent` if the event is a key release event.
674    #[inline]
675    pub fn as_key_release_event(&self) -> Option<KeyEvent> {
676        match self {
677            Event::Key(event) if self.is_key_release() => Some(*event),
678            _ => None,
679        }
680    }
681
682    /// Returns an Option containing the `KeyEvent` if the event is a key repeat event.
683    #[inline]
684    pub fn as_key_repeat_event(&self) -> Option<KeyEvent> {
685        match self {
686            Event::Key(event) if self.is_key_repeat() => Some(*event),
687            _ => None,
688        }
689    }
690
691    /// Returns the mouse event if the event is a mouse event, otherwise `None`.
692    ///
693    /// This is a convenience method that makes code which only cares about mouse events easier to
694    /// write.
695    ///
696    /// # Examples
697    ///
698    /// ```no_run
699    /// use crossterm::event;
700    ///
701    /// while let Some(mouse_event) = event::read()?.as_mouse_event() {
702    ///     // ...
703    /// }
704    /// # std::io::Result::Ok(())
705    /// ```
706    #[inline]
707    pub fn as_mouse_event(&self) -> Option<MouseEvent> {
708        match self {
709            Event::Mouse(event) => Some(*event),
710            _ => None,
711        }
712    }
713
714    /// Returns the pasted string if the event is a paste event, otherwise `None`.
715    ///
716    /// This is a convenience method that makes code which only cares about paste events easier to write.
717    ///
718    /// # Examples
719    ///
720    /// ```no_run
721    /// use crossterm::event;
722    ///
723    /// while let Some(paste) = event::read()?.as_paste_event() {
724    ///     // ...
725    /// }
726    /// # std::io::Result::Ok(())
727    /// ```
728    #[cfg(feature = "bracketed-paste")]
729    #[inline]
730    pub fn as_paste_event(&self) -> Option<&str> {
731        match self {
732            Event::Paste(paste) => Some(paste),
733            _ => None,
734        }
735    }
736
737    /// Returns the size as a tuple if the event is a resize event, otherwise `None`.
738    ///
739    /// This is a convenience method that makes code which only cares about resize events easier to write.
740    ///
741    /// # Examples
742    ///
743    /// ```no_run
744    /// use crossterm::event;
745    ///
746    /// while let Some((columns, rows)) = event::read()?.as_resize_event() {
747    ///     // ...
748    /// }
749    /// # std::io::Result::Ok(())
750    /// ```
751    #[inline]
752    pub fn as_resize_event(&self) -> Option<(u16, u16)> {
753        match self {
754            Event::Resize(columns, rows) => Some((*columns, *rows)),
755            _ => None,
756        }
757    }
758}
759
760/// Represents a mouse event.
761///
762/// # Platform-specific Notes
763///
764/// ## Mouse Buttons
765///
766/// Some platforms/terminals do not report mouse button for the
767/// `MouseEventKind::Up` and `MouseEventKind::Drag` events. `MouseButton::Left`
768/// is returned if we don't know which button was used.
769///
770/// ## Key Modifiers
771///
772/// Some platforms/terminals does not report all key modifiers
773/// combinations for all mouse event types. For example - macOS reports
774/// `Ctrl` + left mouse button click as a right mouse button click.
775#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
776#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
777pub struct MouseEvent {
778    /// The kind of mouse event that was caused.
779    pub kind: MouseEventKind,
780    /// The column that the event occurred on.
781    pub column: u16,
782    /// The row that the event occurred on.
783    pub row: u16,
784    /// The key modifiers active when the event occurred.
785    pub modifiers: KeyModifiers,
786}
787
788/// A mouse event kind.
789///
790/// # Platform-specific Notes
791///
792/// ## Mouse Buttons
793///
794/// Some platforms/terminals do not report mouse button for the
795/// `MouseEventKind::Up` and `MouseEventKind::Drag` events. `MouseButton::Left`
796/// is returned if we don't know which button was used.
797#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
798#[cfg_attr(feature = "derive-more", derive(IsVariant))]
799#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
800pub enum MouseEventKind {
801    /// Pressed mouse button. Contains the button that was pressed.
802    Down(MouseButton),
803    /// Released mouse button. Contains the button that was released.
804    Up(MouseButton),
805    /// Moved the mouse cursor while pressing the contained mouse button.
806    Drag(MouseButton),
807    /// Moved the mouse cursor while not pressing a mouse button.
808    Moved,
809    /// Scrolled mouse wheel downwards (towards the user).
810    ScrollDown,
811    /// Scrolled mouse wheel upwards (away from the user).
812    ScrollUp,
813    /// Scrolled mouse wheel left (mostly on a laptop touchpad).
814    ScrollLeft,
815    /// Scrolled mouse wheel right (mostly on a laptop touchpad).
816    ScrollRight,
817}
818
819/// Represents a mouse button.
820#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
821#[cfg_attr(feature = "derive-more", derive(IsVariant))]
822#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
823pub enum MouseButton {
824    /// Left mouse button.
825    Left,
826    /// Right mouse button.
827    Right,
828    /// Middle mouse button.
829    Middle,
830}
831
832bitflags! {
833    /// Represents key modifiers (shift, control, alt, etc.).
834    ///
835    /// **Note:** `SUPER`, `HYPER`, and `META` can only be read if
836    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
837    /// [`PushKeyboardEnhancementFlags`].
838    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent))]
839    #[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
840    pub struct KeyModifiers: u8 {
841        const SHIFT = 0b0000_0001;
842        const CONTROL = 0b0000_0010;
843        const ALT = 0b0000_0100;
844        const SUPER = 0b0000_1000;
845        const HYPER = 0b0001_0000;
846        const META = 0b0010_0000;
847        const NONE = 0b0000_0000;
848    }
849}
850
851impl Display for KeyModifiers {
852    /// Formats the key modifiers using the given formatter.
853    ///
854    /// The key modifiers are joined by a `+` character.
855    ///
856    /// # Platform-specific Notes
857    ///
858    /// On macOS, the control, alt, and super keys is displayed as "Control", "Option", and
859    /// "Command" respectively. See
860    /// <https://support.apple.com/guide/applestyleguide/welcome/1.0/web>.
861    ///
862    /// On Windows, the super key is displayed as "Windows" and the control key is displayed as
863    /// "Ctrl". See
864    /// <https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/term-collections/keys-keyboard-shortcuts>.
865    ///
866    /// On other platforms, the super key is referred to as "Super" and the control key is
867    /// displayed as "Ctrl".
868    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
869        let mut first = true;
870        for modifier in self.iter() {
871            if !first {
872                f.write_str("+")?;
873            }
874
875            first = false;
876            match modifier {
877                KeyModifiers::SHIFT => f.write_str("Shift")?,
878                #[cfg(unix)]
879                KeyModifiers::CONTROL => f.write_str("Control")?,
880                #[cfg(windows)]
881                KeyModifiers::CONTROL => f.write_str("Ctrl")?,
882                #[cfg(target_os = "macos")]
883                KeyModifiers::ALT => f.write_str("Option")?,
884                #[cfg(not(target_os = "macos"))]
885                KeyModifiers::ALT => f.write_str("Alt")?,
886                #[cfg(target_os = "macos")]
887                KeyModifiers::SUPER => f.write_str("Command")?,
888                #[cfg(target_os = "windows")]
889                KeyModifiers::SUPER => f.write_str("Windows")?,
890                #[cfg(not(any(target_os = "macos", target_os = "windows")))]
891                KeyModifiers::SUPER => f.write_str("Super")?,
892                KeyModifiers::HYPER => f.write_str("Hyper")?,
893                KeyModifiers::META => f.write_str("Meta")?,
894                _ => unreachable!(),
895            }
896        }
897        Ok(())
898    }
899}
900
901/// Represents a keyboard event kind.
902#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
903#[cfg_attr(feature = "derive-more", derive(IsVariant))]
904#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
905pub enum KeyEventKind {
906    Press,
907    Repeat,
908    Release,
909}
910
911bitflags! {
912    /// Represents extra state about the key event.
913    ///
914    /// **Note:** This state can only be read if
915    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
916    /// [`PushKeyboardEnhancementFlags`].
917    #[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
918    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent))]
919    pub struct KeyEventState: u8 {
920        /// The key event origins from the keypad.
921        const KEYPAD = 0b0000_0001;
922        /// Caps Lock was enabled for this key event.
923        ///
924        /// **Note:** this is set for the initial press of Caps Lock itself.
925        const CAPS_LOCK = 0b0000_0010;
926        /// Num Lock was enabled for this key event.
927        ///
928        /// **Note:** this is set for the initial press of Num Lock itself.
929        const NUM_LOCK = 0b0000_0100;
930        const NONE = 0b0000_0000;
931    }
932}
933
934/// Represents a key event.
935#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
936#[derive(Debug, PartialOrd, Clone, Copy)]
937pub struct KeyEvent {
938    /// The key itself.
939    pub code: KeyCode,
940    /// Additional key modifiers.
941    pub modifiers: KeyModifiers,
942    /// Kind of event.
943    ///
944    /// Only set if:
945    /// - Unix: [`KeyboardEnhancementFlags::REPORT_EVENT_TYPES`] has been enabled with [`PushKeyboardEnhancementFlags`].
946    /// - Windows: always
947    pub kind: KeyEventKind,
948    /// Keyboard state.
949    ///
950    /// Only set if [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
951    /// [`PushKeyboardEnhancementFlags`].
952    pub state: KeyEventState,
953}
954
955impl KeyEvent {
956    pub const fn new(code: KeyCode, modifiers: KeyModifiers) -> KeyEvent {
957        KeyEvent {
958            code,
959            modifiers,
960            kind: KeyEventKind::Press,
961            state: KeyEventState::empty(),
962        }
963    }
964
965    pub const fn new_with_kind(
966        code: KeyCode,
967        modifiers: KeyModifiers,
968        kind: KeyEventKind,
969    ) -> KeyEvent {
970        KeyEvent {
971            code,
972            modifiers,
973            kind,
974            state: KeyEventState::empty(),
975        }
976    }
977
978    pub const fn new_with_kind_and_state(
979        code: KeyCode,
980        modifiers: KeyModifiers,
981        kind: KeyEventKind,
982        state: KeyEventState,
983    ) -> KeyEvent {
984        KeyEvent {
985            code,
986            modifiers,
987            kind,
988            state,
989        }
990    }
991
992    // modifies the KeyEvent,
993    // so that KeyModifiers::SHIFT is present iff
994    // an uppercase char is present.
995    fn normalize_case(mut self) -> KeyEvent {
996        let c = match self.code {
997            KeyCode::Char(c) => c,
998            _ => return self,
999        };
1000
1001        if c.is_ascii_uppercase() {
1002            self.modifiers.insert(KeyModifiers::SHIFT);
1003        } else if self.modifiers.contains(KeyModifiers::SHIFT) {
1004            self.code = KeyCode::Char(c.to_ascii_uppercase())
1005        }
1006        self
1007    }
1008
1009    /// Returns whether the key event is a press event.
1010    pub fn is_press(&self) -> bool {
1011        matches!(self.kind, KeyEventKind::Press)
1012    }
1013
1014    /// Returns whether the key event is a release event.
1015    pub fn is_release(&self) -> bool {
1016        matches!(self.kind, KeyEventKind::Release)
1017    }
1018
1019    /// Returns whether the key event is a repeat event.
1020    pub fn is_repeat(&self) -> bool {
1021        matches!(self.kind, KeyEventKind::Repeat)
1022    }
1023}
1024
1025impl From<KeyCode> for KeyEvent {
1026    fn from(code: KeyCode) -> Self {
1027        KeyEvent {
1028            code,
1029            modifiers: KeyModifiers::empty(),
1030            kind: KeyEventKind::Press,
1031            state: KeyEventState::empty(),
1032        }
1033    }
1034}
1035
1036impl PartialEq for KeyEvent {
1037    fn eq(&self, other: &KeyEvent) -> bool {
1038        let KeyEvent {
1039            code: lhs_code,
1040            modifiers: lhs_modifiers,
1041            kind: lhs_kind,
1042            state: lhs_state,
1043        } = self.normalize_case();
1044        let KeyEvent {
1045            code: rhs_code,
1046            modifiers: rhs_modifiers,
1047            kind: rhs_kind,
1048            state: rhs_state,
1049        } = other.normalize_case();
1050        (lhs_code == rhs_code)
1051            && (lhs_modifiers == rhs_modifiers)
1052            && (lhs_kind == rhs_kind)
1053            && (lhs_state == rhs_state)
1054    }
1055}
1056
1057impl Eq for KeyEvent {}
1058
1059impl Hash for KeyEvent {
1060    fn hash<H: Hasher>(&self, hash_state: &mut H) {
1061        let KeyEvent {
1062            code,
1063            modifiers,
1064            kind,
1065            state,
1066        } = self.normalize_case();
1067        code.hash(hash_state);
1068        modifiers.hash(hash_state);
1069        kind.hash(hash_state);
1070        state.hash(hash_state);
1071    }
1072}
1073
1074/// Represents a media key (as part of [`KeyCode::Media`]).
1075#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
1076#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1077pub enum MediaKeyCode {
1078    /// Play media key.
1079    Play,
1080    /// Pause media key.
1081    Pause,
1082    /// Play/Pause media key.
1083    PlayPause,
1084    /// Reverse media key.
1085    Reverse,
1086    /// Stop media key.
1087    Stop,
1088    /// Fast-forward media key.
1089    FastForward,
1090    /// Rewind media key.
1091    Rewind,
1092    /// Next-track media key.
1093    TrackNext,
1094    /// Previous-track media key.
1095    TrackPrevious,
1096    /// Record media key.
1097    Record,
1098    /// Lower-volume media key.
1099    LowerVolume,
1100    /// Raise-volume media key.
1101    RaiseVolume,
1102    /// Mute media key.
1103    MuteVolume,
1104}
1105
1106impl Display for MediaKeyCode {
1107    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1108        match self {
1109            MediaKeyCode::Play => write!(f, "Play"),
1110            MediaKeyCode::Pause => write!(f, "Pause"),
1111            MediaKeyCode::PlayPause => write!(f, "Play/Pause"),
1112            MediaKeyCode::Reverse => write!(f, "Reverse"),
1113            MediaKeyCode::Stop => write!(f, "Stop"),
1114            MediaKeyCode::FastForward => write!(f, "Fast Forward"),
1115            MediaKeyCode::Rewind => write!(f, "Rewind"),
1116            MediaKeyCode::TrackNext => write!(f, "Next Track"),
1117            MediaKeyCode::TrackPrevious => write!(f, "Previous Track"),
1118            MediaKeyCode::Record => write!(f, "Record"),
1119            MediaKeyCode::LowerVolume => write!(f, "Lower Volume"),
1120            MediaKeyCode::RaiseVolume => write!(f, "Raise Volume"),
1121            MediaKeyCode::MuteVolume => write!(f, "Mute Volume"),
1122        }
1123    }
1124}
1125
1126/// Represents a modifier key (as part of [`KeyCode::Modifier`]).
1127#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
1128#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1129pub enum ModifierKeyCode {
1130    /// Left Shift key.
1131    LeftShift,
1132    /// Left Control key. (Control on macOS, Ctrl on other platforms)
1133    LeftControl,
1134    /// Left Alt key. (Option on macOS, Alt on other platforms)
1135    LeftAlt,
1136    /// Left Super key. (Command on macOS, Windows on Windows, Super on other platforms)
1137    LeftSuper,
1138    /// Left Hyper key.
1139    LeftHyper,
1140    /// Left Meta key.
1141    LeftMeta,
1142    /// Right Shift key.
1143    RightShift,
1144    /// Right Control key. (Control on macOS, Ctrl on other platforms)
1145    RightControl,
1146    /// Right Alt key. (Option on macOS, Alt on other platforms)
1147    RightAlt,
1148    /// Right Super key. (Command on macOS, Windows on Windows, Super on other platforms)
1149    RightSuper,
1150    /// Right Hyper key.
1151    RightHyper,
1152    /// Right Meta key.
1153    RightMeta,
1154    /// Iso Level3 Shift key.
1155    IsoLevel3Shift,
1156    /// Iso Level5 Shift key.
1157    IsoLevel5Shift,
1158}
1159
1160impl Display for ModifierKeyCode {
1161    /// Formats the modifier key using the given formatter.
1162    ///
1163    /// # Platform-specific Notes
1164    ///
1165    /// On macOS, the control, alt, and super keys are displayed as "Control", "Option", and
1166    /// "Command" respectively. See
1167    /// <https://support.apple.com/guide/applestyleguide/welcome/1.0/web>.
1168    ///
1169    /// On Windows, the super key is displayed as "Windows" and the control key is displayed as
1170    /// "Ctrl". See
1171    /// <https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/term-collections/keys-keyboard-shortcuts>.
1172    ///
1173    /// On other platforms, the super key is referred to as "Super".
1174    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1175        match self {
1176            ModifierKeyCode::LeftShift => write!(f, "Left Shift"),
1177            ModifierKeyCode::LeftHyper => write!(f, "Left Hyper"),
1178            ModifierKeyCode::LeftMeta => write!(f, "Left Meta"),
1179            ModifierKeyCode::RightShift => write!(f, "Right Shift"),
1180            ModifierKeyCode::RightHyper => write!(f, "Right Hyper"),
1181            ModifierKeyCode::RightMeta => write!(f, "Right Meta"),
1182            ModifierKeyCode::IsoLevel3Shift => write!(f, "Iso Level 3 Shift"),
1183            ModifierKeyCode::IsoLevel5Shift => write!(f, "Iso Level 5 Shift"),
1184
1185            #[cfg(target_os = "macos")]
1186            ModifierKeyCode::LeftControl => write!(f, "Left Control"),
1187            #[cfg(not(target_os = "macos"))]
1188            ModifierKeyCode::LeftControl => write!(f, "Left Ctrl"),
1189
1190            #[cfg(target_os = "macos")]
1191            ModifierKeyCode::LeftAlt => write!(f, "Left Option"),
1192            #[cfg(not(target_os = "macos"))]
1193            ModifierKeyCode::LeftAlt => write!(f, "Left Alt"),
1194
1195            #[cfg(target_os = "macos")]
1196            ModifierKeyCode::LeftSuper => write!(f, "Left Command"),
1197            #[cfg(target_os = "windows")]
1198            ModifierKeyCode::LeftSuper => write!(f, "Left Windows"),
1199            #[cfg(not(any(target_os = "macos", target_os = "windows")))]
1200            ModifierKeyCode::LeftSuper => write!(f, "Left Super"),
1201
1202            #[cfg(target_os = "macos")]
1203            ModifierKeyCode::RightControl => write!(f, "Right Control"),
1204            #[cfg(not(target_os = "macos"))]
1205            ModifierKeyCode::RightControl => write!(f, "Right Ctrl"),
1206
1207            #[cfg(target_os = "macos")]
1208            ModifierKeyCode::RightAlt => write!(f, "Right Option"),
1209            #[cfg(not(target_os = "macos"))]
1210            ModifierKeyCode::RightAlt => write!(f, "Right Alt"),
1211
1212            #[cfg(target_os = "macos")]
1213            ModifierKeyCode::RightSuper => write!(f, "Right Command"),
1214            #[cfg(target_os = "windows")]
1215            ModifierKeyCode::RightSuper => write!(f, "Right Windows"),
1216            #[cfg(not(any(target_os = "macos", target_os = "windows")))]
1217            ModifierKeyCode::RightSuper => write!(f, "Right Super"),
1218        }
1219    }
1220}
1221
1222/// Represents a key.
1223#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
1224#[cfg_attr(feature = "derive-more", derive(IsVariant))]
1225#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1226pub enum KeyCode {
1227    /// Backspace key (Delete on macOS, Backspace on other platforms).
1228    Backspace,
1229    /// Enter key.
1230    Enter,
1231    /// Left arrow key.
1232    Left,
1233    /// Right arrow key.
1234    Right,
1235    /// Up arrow key.
1236    Up,
1237    /// Down arrow key.
1238    Down,
1239    /// Home key.
1240    Home,
1241    /// End key.
1242    End,
1243    /// Page up key.
1244    PageUp,
1245    /// Page down key.
1246    PageDown,
1247    /// Tab key.
1248    Tab,
1249    /// Shift + Tab key.
1250    BackTab,
1251    /// Delete key. (Fn+Delete on macOS, Delete on other platforms)
1252    Delete,
1253    /// Insert key.
1254    Insert,
1255    /// F key.
1256    ///
1257    /// `KeyCode::F(1)` represents F1 key, etc.
1258    #[cfg_attr(feature = "derive-more", is_variant(ignore))]
1259    F(u8),
1260    /// A character.
1261    ///
1262    /// `KeyCode::Char('c')` represents `c` character, etc.
1263    #[cfg_attr(feature = "derive-more", is_variant(ignore))]
1264    Char(char),
1265    /// Null.
1266    Null,
1267    /// Escape key.
1268    Esc,
1269    /// Caps Lock key.
1270    ///
1271    /// **Note:** this key can only be read if
1272    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
1273    /// [`PushKeyboardEnhancementFlags`].
1274    CapsLock,
1275    /// Scroll Lock key.
1276    ///
1277    /// **Note:** this key can only be read if
1278    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
1279    /// [`PushKeyboardEnhancementFlags`].
1280    ScrollLock,
1281    /// Num Lock key.
1282    ///
1283    /// **Note:** this key can only be read if
1284    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
1285    /// [`PushKeyboardEnhancementFlags`].
1286    NumLock,
1287    /// Print Screen key.
1288    ///
1289    /// **Note:** this key can only be read if
1290    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
1291    /// [`PushKeyboardEnhancementFlags`].
1292    PrintScreen,
1293    /// Pause key.
1294    ///
1295    /// **Note:** this key can only be read if
1296    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
1297    /// [`PushKeyboardEnhancementFlags`].
1298    Pause,
1299    /// Menu key.
1300    ///
1301    /// **Note:** this key can only be read if
1302    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
1303    /// [`PushKeyboardEnhancementFlags`].
1304    Menu,
1305    /// The "Begin" key (often mapped to the 5 key when Num Lock is turned on).
1306    ///
1307    /// **Note:** this key can only be read if
1308    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
1309    /// [`PushKeyboardEnhancementFlags`].
1310    KeypadBegin,
1311    /// A media key.
1312    ///
1313    /// **Note:** these keys can only be read if
1314    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
1315    /// [`PushKeyboardEnhancementFlags`].
1316    #[cfg_attr(feature = "derive-more", is_variant(ignore))]
1317    Media(MediaKeyCode),
1318    /// A modifier key.
1319    ///
1320    /// **Note:** these keys can only be read if **both**
1321    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] and
1322    /// [`KeyboardEnhancementFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES`] have been enabled with
1323    /// [`PushKeyboardEnhancementFlags`].
1324    #[cfg_attr(feature = "derive-more", is_variant(ignore))]
1325    Modifier(ModifierKeyCode),
1326}
1327
1328impl KeyCode {
1329    /// Returns `true` if the key code is the given function key.
1330    ///
1331    /// # Examples
1332    ///
1333    /// ```
1334    /// # use crossterm::event::KeyCode;
1335    /// assert!(KeyCode::F(1).is_function_key(1));
1336    /// assert!(!KeyCode::F(1).is_function_key(2));
1337    /// ```
1338    pub fn is_function_key(&self, n: u8) -> bool {
1339        matches!(self, KeyCode::F(m) if *m == n)
1340    }
1341
1342    /// Returns `true` if the key code is the given character.
1343    ///
1344    /// # Examples
1345    ///
1346    /// ```
1347    /// # use crossterm::event::KeyCode;
1348    /// assert!(KeyCode::Char('a').is_char('a'));
1349    /// assert!(!KeyCode::Char('a').is_char('b'));
1350    /// assert!(!KeyCode::F(1).is_char('a'));
1351    /// ```
1352    pub fn is_char(&self, c: char) -> bool {
1353        matches!(self, KeyCode::Char(m) if *m == c)
1354    }
1355
1356    /// Returns the character if the key code is a character key.
1357    ///
1358    /// Returns `None` if the key code is not a character key.
1359    ///
1360    /// # Examples
1361    ///
1362    /// ```
1363    /// # use crossterm::event::KeyCode;
1364    /// assert_eq!(KeyCode::Char('a').as_char(), Some('a'));
1365    /// assert_eq!(KeyCode::F(1).as_char(), None);
1366    /// ```
1367    pub fn as_char(&self) -> Option<char> {
1368        match self {
1369            KeyCode::Char(c) => Some(*c),
1370            _ => None,
1371        }
1372    }
1373
1374    /// Returns `true` if the key code is the given media key.
1375    ///
1376    /// **Note:** this method requires
1377    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] to be enabled with
1378    /// [`PushKeyboardEnhancementFlags`].
1379    ///
1380    /// # Examples
1381    ///
1382    /// ```
1383    /// # use crossterm::event::{KeyCode, MediaKeyCode};
1384    /// assert!(KeyCode::Media(MediaKeyCode::Play).is_media_key(MediaKeyCode::Play));
1385    /// assert!(!KeyCode::Media(MediaKeyCode::Play).is_media_key(MediaKeyCode::Pause));
1386    /// ```
1387    pub fn is_media_key(&self, media: MediaKeyCode) -> bool {
1388        matches!(self, KeyCode::Media(m) if *m == media)
1389    }
1390
1391    /// Returns `true` if the key code is the given modifier key.
1392    ///
1393    /// **Note:** this method requires both
1394    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] and
1395    /// [`KeyboardEnhancementFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES`] to be enabled with
1396    /// [`PushKeyboardEnhancementFlags`].
1397    ///
1398    /// # Examples
1399    ///
1400    /// ```
1401    /// # use crossterm::event::{KeyCode, ModifierKeyCode};
1402    /// assert!(KeyCode::Modifier(ModifierKeyCode::LeftShift).is_modifier(ModifierKeyCode::LeftShift));
1403    /// assert!(!KeyCode::Modifier(ModifierKeyCode::LeftShift).is_modifier(ModifierKeyCode::RightShift));
1404    /// ```
1405    pub fn is_modifier(&self, modifier: ModifierKeyCode) -> bool {
1406        matches!(self, KeyCode::Modifier(m) if *m == modifier)
1407    }
1408}
1409
1410impl Display for KeyCode {
1411    /// Formats the `KeyCode` using the given formatter.
1412    ///
1413    /// # Platform-specific Notes
1414    ///
1415    /// On macOS, the Backspace key is displayed as "Delete", the Delete key is displayed as "Fwd
1416    /// Del", and the Enter key is displayed as "Return". See
1417    /// <https://support.apple.com/guide/applestyleguide/welcome/1.0/web>.
1418    ///
1419    /// On other platforms, the Backspace key is displayed as "Backspace", the Delete key is
1420    /// displayed as "Del", and the Enter key is displayed as "Enter".
1421    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1422        match self {
1423            // On macOS, the Backspace key is called "Delete" and the Delete key is called "Fwd Del".
1424            #[cfg(target_os = "macos")]
1425            KeyCode::Backspace => write!(f, "Delete"),
1426            #[cfg(target_os = "macos")]
1427            KeyCode::Delete => write!(f, "Fwd Del"),
1428
1429            #[cfg(not(target_os = "macos"))]
1430            KeyCode::Backspace => write!(f, "Backspace"),
1431            #[cfg(not(target_os = "macos"))]
1432            KeyCode::Delete => write!(f, "Del"),
1433
1434            #[cfg(target_os = "macos")]
1435            KeyCode::Enter => write!(f, "Return"),
1436            #[cfg(not(target_os = "macos"))]
1437            KeyCode::Enter => write!(f, "Enter"),
1438            KeyCode::Left => write!(f, "Left"),
1439            KeyCode::Right => write!(f, "Right"),
1440            KeyCode::Up => write!(f, "Up"),
1441            KeyCode::Down => write!(f, "Down"),
1442            KeyCode::Home => write!(f, "Home"),
1443            KeyCode::End => write!(f, "End"),
1444            KeyCode::PageUp => write!(f, "Page Up"),
1445            KeyCode::PageDown => write!(f, "Page Down"),
1446            KeyCode::Tab => write!(f, "Tab"),
1447            KeyCode::BackTab => write!(f, "Back Tab"),
1448            KeyCode::Insert => write!(f, "Insert"),
1449            KeyCode::F(n) => write!(f, "F{}", n),
1450            KeyCode::Char(c) => match c {
1451                // special case for non-visible characters
1452                ' ' => write!(f, "Space"),
1453                c => write!(f, "{}", c),
1454            },
1455            KeyCode::Null => write!(f, "Null"),
1456            KeyCode::Esc => write!(f, "Esc"),
1457            KeyCode::CapsLock => write!(f, "Caps Lock"),
1458            KeyCode::ScrollLock => write!(f, "Scroll Lock"),
1459            KeyCode::NumLock => write!(f, "Num Lock"),
1460            KeyCode::PrintScreen => write!(f, "Print Screen"),
1461            KeyCode::Pause => write!(f, "Pause"),
1462            KeyCode::Menu => write!(f, "Menu"),
1463            KeyCode::KeypadBegin => write!(f, "Begin"),
1464            KeyCode::Media(media) => write!(f, "{}", media),
1465            KeyCode::Modifier(modifier) => write!(f, "{}", modifier),
1466        }
1467    }
1468}
1469
1470/// An internal event.
1471///
1472/// Encapsulates publicly available `Event` with additional internal
1473/// events that shouldn't be publicly available to the crate users.
1474#[derive(Debug, PartialOrd, PartialEq, Hash, Clone, Eq)]
1475pub(crate) enum InternalEvent {
1476    /// An event.
1477    Event(Event),
1478    /// A cursor position (`col`, `row`).
1479    #[cfg(unix)]
1480    CursorPosition(u16, u16),
1481    /// The progressive keyboard enhancement flags enabled by the terminal.
1482    #[cfg(unix)]
1483    KeyboardEnhancementFlags(KeyboardEnhancementFlags),
1484    /// Attributes and architectural class of the terminal.
1485    #[cfg(unix)]
1486    PrimaryDeviceAttributes,
1487}
1488
1489#[cfg(test)]
1490mod tests {
1491    use std::collections::hash_map::DefaultHasher;
1492    use std::hash::{Hash, Hasher};
1493
1494    use super::*;
1495    use KeyCode::*;
1496    use MediaKeyCode::*;
1497    use ModifierKeyCode::*;
1498
1499    #[test]
1500    fn test_equality() {
1501        let lowercase_d_with_shift = KeyEvent::new(KeyCode::Char('d'), KeyModifiers::SHIFT);
1502        let uppercase_d_with_shift = KeyEvent::new(KeyCode::Char('D'), KeyModifiers::SHIFT);
1503        let uppercase_d = KeyEvent::new(KeyCode::Char('D'), KeyModifiers::NONE);
1504        assert_eq!(lowercase_d_with_shift, uppercase_d_with_shift);
1505        assert_eq!(uppercase_d, uppercase_d_with_shift);
1506    }
1507
1508    #[test]
1509    fn test_hash() {
1510        let lowercase_d_with_shift_hash = {
1511            let mut hasher = DefaultHasher::new();
1512            KeyEvent::new(KeyCode::Char('d'), KeyModifiers::SHIFT).hash(&mut hasher);
1513            hasher.finish()
1514        };
1515        let uppercase_d_with_shift_hash = {
1516            let mut hasher = DefaultHasher::new();
1517            KeyEvent::new(KeyCode::Char('D'), KeyModifiers::SHIFT).hash(&mut hasher);
1518            hasher.finish()
1519        };
1520        let uppercase_d_hash = {
1521            let mut hasher = DefaultHasher::new();
1522            KeyEvent::new(KeyCode::Char('D'), KeyModifiers::NONE).hash(&mut hasher);
1523            hasher.finish()
1524        };
1525        assert_eq!(lowercase_d_with_shift_hash, uppercase_d_with_shift_hash);
1526        assert_eq!(uppercase_d_hash, uppercase_d_with_shift_hash);
1527    }
1528
1529    #[test]
1530    fn keycode_display() {
1531        #[cfg(target_os = "macos")]
1532        {
1533            assert_eq!(format!("{}", Backspace), "Delete");
1534            assert_eq!(format!("{}", Delete), "Fwd Del");
1535            assert_eq!(format!("{}", Enter), "Return");
1536        }
1537        #[cfg(not(target_os = "macos"))]
1538        {
1539            assert_eq!(format!("{}", Backspace), "Backspace");
1540            assert_eq!(format!("{}", Delete), "Del");
1541            assert_eq!(format!("{}", Enter), "Enter");
1542        }
1543        assert_eq!(format!("{}", Left), "Left");
1544        assert_eq!(format!("{}", Right), "Right");
1545        assert_eq!(format!("{}", Up), "Up");
1546        assert_eq!(format!("{}", Down), "Down");
1547        assert_eq!(format!("{}", Home), "Home");
1548        assert_eq!(format!("{}", End), "End");
1549        assert_eq!(format!("{}", PageUp), "Page Up");
1550        assert_eq!(format!("{}", PageDown), "Page Down");
1551        assert_eq!(format!("{}", Tab), "Tab");
1552        assert_eq!(format!("{}", BackTab), "Back Tab");
1553        assert_eq!(format!("{}", Insert), "Insert");
1554        assert_eq!(format!("{}", F(1)), "F1");
1555        assert_eq!(format!("{}", Char('a')), "a");
1556        assert_eq!(format!("{}", Null), "Null");
1557        assert_eq!(format!("{}", Esc), "Esc");
1558        assert_eq!(format!("{}", CapsLock), "Caps Lock");
1559        assert_eq!(format!("{}", ScrollLock), "Scroll Lock");
1560        assert_eq!(format!("{}", NumLock), "Num Lock");
1561        assert_eq!(format!("{}", PrintScreen), "Print Screen");
1562        assert_eq!(format!("{}", KeyCode::Pause), "Pause");
1563        assert_eq!(format!("{}", Menu), "Menu");
1564        assert_eq!(format!("{}", KeypadBegin), "Begin");
1565    }
1566
1567    #[test]
1568    fn media_keycode_display() {
1569        assert_eq!(format!("{}", Media(Play)), "Play");
1570        assert_eq!(format!("{}", Media(MediaKeyCode::Pause)), "Pause");
1571        assert_eq!(format!("{}", Media(PlayPause)), "Play/Pause");
1572        assert_eq!(format!("{}", Media(Reverse)), "Reverse");
1573        assert_eq!(format!("{}", Media(Stop)), "Stop");
1574        assert_eq!(format!("{}", Media(FastForward)), "Fast Forward");
1575        assert_eq!(format!("{}", Media(Rewind)), "Rewind");
1576        assert_eq!(format!("{}", Media(TrackNext)), "Next Track");
1577        assert_eq!(format!("{}", Media(TrackPrevious)), "Previous Track");
1578        assert_eq!(format!("{}", Media(Record)), "Record");
1579        assert_eq!(format!("{}", Media(LowerVolume)), "Lower Volume");
1580        assert_eq!(format!("{}", Media(RaiseVolume)), "Raise Volume");
1581        assert_eq!(format!("{}", Media(MuteVolume)), "Mute Volume");
1582    }
1583
1584    #[test]
1585    fn modifier_keycode_display() {
1586        assert_eq!(format!("{}", Modifier(LeftShift)), "Left Shift");
1587        assert_eq!(format!("{}", Modifier(LeftHyper)), "Left Hyper");
1588        assert_eq!(format!("{}", Modifier(LeftMeta)), "Left Meta");
1589        assert_eq!(format!("{}", Modifier(RightShift)), "Right Shift");
1590        assert_eq!(format!("{}", Modifier(RightHyper)), "Right Hyper");
1591        assert_eq!(format!("{}", Modifier(RightMeta)), "Right Meta");
1592        assert_eq!(format!("{}", Modifier(IsoLevel3Shift)), "Iso Level 3 Shift");
1593        assert_eq!(format!("{}", Modifier(IsoLevel5Shift)), "Iso Level 5 Shift");
1594    }
1595
1596    #[cfg(target_os = "macos")]
1597    #[test]
1598    fn modifier_keycode_display_macos() {
1599        assert_eq!(format!("{}", Modifier(LeftControl)), "Left Control");
1600        assert_eq!(format!("{}", Modifier(LeftAlt)), "Left Option");
1601        assert_eq!(format!("{}", Modifier(LeftSuper)), "Left Command");
1602        assert_eq!(format!("{}", Modifier(RightControl)), "Right Control");
1603        assert_eq!(format!("{}", Modifier(RightAlt)), "Right Option");
1604        assert_eq!(format!("{}", Modifier(RightSuper)), "Right Command");
1605    }
1606
1607    #[cfg(target_os = "windows")]
1608    #[test]
1609    fn modifier_keycode_display_windows() {
1610        assert_eq!(format!("{}", Modifier(LeftControl)), "Left Ctrl");
1611        assert_eq!(format!("{}", Modifier(LeftAlt)), "Left Alt");
1612        assert_eq!(format!("{}", Modifier(LeftSuper)), "Left Windows");
1613        assert_eq!(format!("{}", Modifier(RightControl)), "Right Ctrl");
1614        assert_eq!(format!("{}", Modifier(RightAlt)), "Right Alt");
1615        assert_eq!(format!("{}", Modifier(RightSuper)), "Right Windows");
1616    }
1617
1618    #[cfg(not(any(target_os = "macos", target_os = "windows")))]
1619    #[test]
1620    fn modifier_keycode_display_other() {
1621        assert_eq!(format!("{}", Modifier(LeftControl)), "Left Ctrl");
1622        assert_eq!(format!("{}", Modifier(LeftAlt)), "Left Alt");
1623        assert_eq!(format!("{}", Modifier(LeftSuper)), "Left Super");
1624        assert_eq!(format!("{}", Modifier(RightControl)), "Right Ctrl");
1625        assert_eq!(format!("{}", Modifier(RightAlt)), "Right Alt");
1626        assert_eq!(format!("{}", Modifier(RightSuper)), "Right Super");
1627    }
1628
1629    #[test]
1630    fn key_modifiers_display() {
1631        let modifiers = KeyModifiers::SHIFT | KeyModifiers::CONTROL | KeyModifiers::ALT;
1632
1633        #[cfg(target_os = "macos")]
1634        assert_eq!(modifiers.to_string(), "Shift+Control+Option");
1635
1636        #[cfg(target_os = "windows")]
1637        assert_eq!(modifiers.to_string(), "Shift+Ctrl+Alt");
1638
1639        #[cfg(not(any(target_os = "macos", target_os = "windows")))]
1640        assert_eq!(modifiers.to_string(), "Shift+Control+Alt");
1641    }
1642
1643    const ESC_PRESSED: KeyEvent =
1644        KeyEvent::new_with_kind(KeyCode::Esc, KeyModifiers::empty(), KeyEventKind::Press);
1645    const ESC_RELEASED: KeyEvent =
1646        KeyEvent::new_with_kind(KeyCode::Esc, KeyModifiers::empty(), KeyEventKind::Release);
1647    const ESC_REPEAT: KeyEvent =
1648        KeyEvent::new_with_kind(KeyCode::Esc, KeyModifiers::empty(), KeyEventKind::Repeat);
1649    const MOUSE_CLICK: MouseEvent = MouseEvent {
1650        kind: MouseEventKind::Down(MouseButton::Left),
1651        column: 1,
1652        row: 1,
1653        modifiers: KeyModifiers::empty(),
1654    };
1655
1656    #[cfg(feature = "derive-more")]
1657    #[test]
1658    fn event_is() {
1659        let event = Event::FocusGained;
1660        assert!(event.is_focus_gained());
1661        assert!(event.is_focus_gained());
1662        assert!(!event.is_key());
1663
1664        let event = Event::FocusLost;
1665        assert!(event.is_focus_lost());
1666        assert!(!event.is_focus_gained());
1667        assert!(!event.is_key());
1668
1669        let event = Event::Resize(1, 1);
1670        assert!(event.is_resize());
1671        assert!(!event.is_key());
1672
1673        let event = Event::Key(ESC_PRESSED);
1674        assert!(event.is_key());
1675        assert!(event.is_key_press());
1676        assert!(!event.is_key_release());
1677        assert!(!event.is_key_repeat());
1678        assert!(!event.is_focus_gained());
1679
1680        let event = Event::Key(ESC_RELEASED);
1681        assert!(event.is_key());
1682        assert!(!event.is_key_press());
1683        assert!(event.is_key_release());
1684        assert!(!event.is_key_repeat());
1685        assert!(!event.is_focus_gained());
1686
1687        let event = Event::Key(ESC_REPEAT);
1688        assert!(event.is_key());
1689        assert!(!event.is_key_press());
1690        assert!(!event.is_key_release());
1691        assert!(event.is_key_repeat());
1692        assert!(!event.is_focus_gained());
1693
1694        let event = Event::Mouse(MOUSE_CLICK);
1695        assert!(event.is_mouse());
1696        assert!(!event.is_key());
1697
1698        #[cfg(feature = "bracketed-paste")]
1699        {
1700            let event = Event::Paste("".to_string());
1701            assert!(event.is_paste());
1702            assert!(!event.is_key());
1703        }
1704    }
1705
1706    #[test]
1707    fn event_as() {
1708        let event = Event::FocusGained;
1709        assert_eq!(event.as_key_event(), None);
1710
1711        let event = Event::Key(ESC_PRESSED);
1712        assert_eq!(event.as_key_event(), Some(ESC_PRESSED));
1713        assert_eq!(event.as_key_press_event(), Some(ESC_PRESSED));
1714        assert_eq!(event.as_key_release_event(), None);
1715        assert_eq!(event.as_key_repeat_event(), None);
1716        assert_eq!(event.as_resize_event(), None);
1717
1718        let event = Event::Key(ESC_RELEASED);
1719        assert_eq!(event.as_key_event(), Some(ESC_RELEASED));
1720        assert_eq!(event.as_key_release_event(), Some(ESC_RELEASED));
1721        assert_eq!(event.as_key_press_event(), None);
1722        assert_eq!(event.as_key_repeat_event(), None);
1723        assert_eq!(event.as_resize_event(), None);
1724
1725        let event = Event::Key(ESC_REPEAT);
1726        assert_eq!(event.as_key_event(), Some(ESC_REPEAT));
1727        assert_eq!(event.as_key_repeat_event(), Some(ESC_REPEAT));
1728        assert_eq!(event.as_key_press_event(), None);
1729        assert_eq!(event.as_key_release_event(), None);
1730        assert_eq!(event.as_resize_event(), None);
1731
1732        let event = Event::Resize(1, 1);
1733        assert_eq!(event.as_resize_event(), Some((1, 1)));
1734        assert_eq!(event.as_key_event(), None);
1735
1736        let event = Event::Mouse(MOUSE_CLICK);
1737        assert_eq!(event.as_mouse_event(), Some(MOUSE_CLICK));
1738        assert_eq!(event.as_key_event(), None);
1739
1740        #[cfg(feature = "bracketed-paste")]
1741        {
1742            let event = Event::Paste("".to_string());
1743            assert_eq!(event.as_paste_event(), Some(""));
1744            assert_eq!(event.as_key_event(), None);
1745        }
1746    }
1747}