diff options
author | Dettorer <Dettorer@users.noreply.github.com> | 2020-11-24 00:11:03 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-23 23:11:03 +0000 |
commit | 2fd2db4afa232ebd15dbfff88160224badeaa669 (patch) | |
tree | ef0cdf3311df017da5fff4d29ce898d690980a3e /alacritty_terminal/src/term | |
parent | 07cfe8bbba0851ff4989f6aaf082d72130cd0f5b (diff) | |
download | alacritty-2fd2db4afa232ebd15dbfff88160224badeaa669.tar.gz alacritty-2fd2db4afa232ebd15dbfff88160224badeaa669.zip |
Add blinking cursor support
This adds support for blinking the terminal cursor. This can be
controlled either using the configuration file, or using escape
sequences.
The supported control sequences for changing the blinking state are
`CSI Ps SP q` and private mode 12.
Diffstat (limited to 'alacritty_terminal/src/term')
-rw-r--r-- | alacritty_terminal/src/term/mod.rs | 73 |
1 files changed, 56 insertions, 17 deletions
diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index 926b89d7..accb4dc1 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize}; use unicode_width::UnicodeWidthChar; use crate::ansi::{ - self, Attr, CharsetIndex, Color, CursorStyle, Handler, NamedColor, StandardCharset, + self, Attr, CharsetIndex, Color, CursorShape, CursorStyle, Handler, NamedColor, StandardCharset, }; use crate::config::{BellAnimation, BellConfig, Config}; use crate::event::{Event, EventListener}; @@ -61,7 +61,7 @@ struct RenderableCursor { /// A key for caching cursor glyphs. #[derive(Debug, Eq, PartialEq, Copy, Clone, Hash, Deserialize)] pub struct CursorKey { - pub style: CursorStyle, + pub shape: CursorShape, pub is_wide: bool, } @@ -202,7 +202,7 @@ impl<'a, C> RenderableCellsIter<'a, C> { let cell = self.inner.next()?; let mut cell = RenderableCell::new(self, cell); - if self.cursor.key.style == CursorStyle::Block { + if self.cursor.key.shape == CursorShape::Block { cell.fg = match self.cursor.cursor_color { // Apply cursor color, or invert the cursor if it has a fixed background // close to the cell's background. @@ -249,7 +249,7 @@ impl<'a, C> RenderableCellsIter<'a, C> { }; // Do not invert block cursor at selection boundaries. - if self.cursor.key.style == CursorStyle::Block + if self.cursor.key.shape == CursorShape::Block && self.cursor.point == point && (selection.start == point || selection.end == point @@ -855,8 +855,8 @@ impl<T> Term<T> { original_colors: colors, semantic_escape_chars: config.selection.semantic_escape_chars().to_owned(), cursor_style: None, - default_cursor_style: config.cursor.style, - vi_mode_cursor_style: config.cursor.vi_mode_style, + default_cursor_style: config.cursor.style(), + vi_mode_cursor_style: config.cursor.vi_mode_style(), event_proxy, is_focused: true, title: None, @@ -885,8 +885,8 @@ impl<T> Term<T> { if let Some(0) = config.scrolling.faux_multiplier() { self.mode.remove(TermMode::ALTERNATE_SCROLL); } - self.default_cursor_style = config.cursor.style; - self.vi_mode_cursor_style = config.cursor.vi_mode_style; + self.default_cursor_style = config.cursor.style(); + self.vi_mode_cursor_style = config.cursor.vi_mode_style(); let title_event = match &self.title { Some(title) => Event::Title(title.clone()), @@ -1207,7 +1207,10 @@ impl<T> Term<T> { /// Toggle the vi mode. #[inline] - pub fn toggle_vi_mode(&mut self) { + pub fn toggle_vi_mode(&mut self) + where + T: EventListener, + { self.mode ^= TermMode::VI; let vi_mode = self.mode.contains(TermMode::VI); @@ -1226,6 +1229,9 @@ impl<T> Term<T> { self.cancel_search(); } + // Update UI about cursor blinking state changes. + self.event_proxy.send_event(Event::CursorBlinkingChange(self.cursor_style().blinking)); + self.dirty = true; } @@ -1332,6 +1338,20 @@ impl<T> Term<T> { &self.semantic_escape_chars } + /// Active terminal cursor style. + /// + /// While vi mode is active, this will automatically return the vi mode cursor style. + #[inline] + pub fn cursor_style(&self) -> CursorStyle { + let cursor_style = self.cursor_style.unwrap_or(self.default_cursor_style); + + if self.mode.contains(TermMode::VI) { + self.vi_mode_cursor_style.unwrap_or(cursor_style) + } else { + cursor_style + } + } + /// Insert a linebreak at the current cursor position. #[inline] fn wrapline(&mut self) @@ -1395,18 +1415,18 @@ impl<T> Term<T> { // Cursor shape. let hidden = !self.mode.contains(TermMode::SHOW_CURSOR) || point.line >= self.screen_lines(); - let cursor_style = if hidden && !vi_mode { + let cursor_shape = if hidden && !vi_mode { point.line = Line(0); - CursorStyle::Hidden + CursorShape::Hidden } else if !self.is_focused && config.cursor.unfocused_hollow() { - CursorStyle::HollowBlock + CursorShape::HollowBlock } else { let cursor_style = self.cursor_style.unwrap_or(self.default_cursor_style); if vi_mode { - self.vi_mode_cursor_style.unwrap_or(cursor_style) + self.vi_mode_cursor_style.unwrap_or(cursor_style).shape } else { - cursor_style + cursor_style.shape } }; @@ -1432,7 +1452,7 @@ impl<T> Term<T> { RenderableCursor { text_color, cursor_color, - key: CursorKey { style: cursor_style, is_wide }, + key: CursorKey { shape: cursor_shape, is_wide }, point, rendered: false, } @@ -2098,6 +2118,9 @@ impl<T: EventListener> Handler for Term<T> { // Preserve vi mode across resets. self.mode &= TermMode::VI; self.mode.insert(TermMode::default()); + + let blinking = self.cursor_style().blinking; + self.event_proxy.send_event(Event::CursorBlinkingChange(blinking)); } #[inline] @@ -2199,7 +2222,9 @@ impl<T: EventListener> Handler for Term<T> { ansi::Mode::DECCOLM => self.deccolm(), ansi::Mode::Insert => self.mode.insert(TermMode::INSERT), ansi::Mode::BlinkingCursor => { - trace!("... unimplemented mode"); + let style = self.cursor_style.get_or_insert(self.default_cursor_style); + style.blinking = true; + self.event_proxy.send_event(Event::CursorBlinkingChange(true)); }, } } @@ -2239,7 +2264,9 @@ impl<T: EventListener> Handler for Term<T> { ansi::Mode::DECCOLM => self.deccolm(), ansi::Mode::Insert => self.mode.remove(TermMode::INSERT), ansi::Mode::BlinkingCursor => { - trace!("... unimplemented mode"); + let style = self.cursor_style.get_or_insert(self.default_cursor_style); + style.blinking = false; + self.event_proxy.send_event(Event::CursorBlinkingChange(false)); }, } } @@ -2296,6 +2323,18 @@ impl<T: EventListener> Handler for Term<T> { fn set_cursor_style(&mut self, style: Option<CursorStyle>) { trace!("Setting cursor style {:?}", style); self.cursor_style = style; + + // Notify UI about blinking changes. + let blinking = style.unwrap_or(self.default_cursor_style).blinking; + self.event_proxy.send_event(Event::CursorBlinkingChange(blinking)); + } + + #[inline] + fn set_cursor_shape(&mut self, shape: CursorShape) { + trace!("Setting cursor shape {:?}", shape); + + let style = self.cursor_style.get_or_insert(self.default_cursor_style); + style.shape = shape; } #[inline] |