Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 27 additions & 2 deletions crates/base/src/input/base/blink_cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ impl BlinkCursor {
self.paused || self.visible
}

/// Pause the blinking, and delay 500ms to resume the blinking.
/// Show the cursor immediately and restart the idle delay before blinking resumes.
pub(crate) fn pause(&mut self, cx: &mut Context<Self>) {
self.paused = true;
self.visible = true;
cx.notify();

// delay 500ms to start the blinking
// Every pause replaces the pending timer, keeping repeated input visible.
let epoch = self.next_epoch();
self._task = cx.spawn(async move |this, cx| {
cx.background_executor().timer(PAUSE_DELAY).await;
Expand All @@ -93,3 +93,28 @@ impl BlinkCursor {
});
}
}

#[cfg(test)]
mod tests {
use super::*;
use gpui::{AppContext as _, TestAppContext};

#[gpui::test]
fn repeated_pauses_keep_cursor_visible_until_idle(cx: &mut TestAppContext) {
let cursor = cx.new(|_| BlinkCursor::new());
assert!(!cursor.read_with(cx, |cursor, _| cursor.visible()));
for _ in 0..5 {
cursor.update(cx, |cursor, cx| cursor.pause(cx));
cx.run_until_parked();
cx.executor().advance_clock(Duration::from_millis(200));
cx.run_until_parked();
assert!(cursor.read_with(cx, |cursor, _| cursor.visible()));
}
cx.executor().advance_clock(Duration::from_millis(100));
cx.run_until_parked();
assert!(!cursor.read_with(cx, |cursor, _| cursor.visible()));
cx.executor().advance_clock(INTERVAL);
cx.run_until_parked();
assert!(cursor.read_with(cx, |cursor, _| cursor.visible()));
}
}
20 changes: 14 additions & 6 deletions crates/base/src/input/base/change.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ use std::fmt::Debug;

use crate::input::Selection;

/// One text replacement, in the coordinates of the document as it stood
/// immediately before the replacement was applied.
#[derive(Debug, PartialEq, Clone)]
pub(super) struct Change {
pub(crate) old_range: Selection,
pub(crate) old_text: String,
pub(crate) new_range: Selection,
pub(crate) new_text: String,
pub(crate) selection_before: Selection,
pub(crate) selection_after: Selection,
}

impl Change {
Expand All @@ -18,16 +18,24 @@ impl Change {
old_text: &str,
new_range: impl Into<Selection>,
new_text: &str,
selection_before: Selection,
selection_after: Selection,
) -> Self {
Self {
old_range: old_range.into(),
old_text: old_text.to_string(),
new_range: new_range.into(),
new_text: new_text.to_string(),
selection_before,
selection_after,
}
}

/// The same change as it would read after `delta` bytes were inserted
/// (positive) or removed (negative) ahead of it.
pub(super) fn shifted(&self, delta: isize) -> Self {
let shift = |offset: usize| (offset as isize + delta).max(0) as usize;
Self {
old_range: (shift(self.old_range.start)..shift(self.old_range.end)).into(),
old_text: self.old_text.clone(),
new_range: (shift(self.new_range.start)..shift(self.new_range.end)).into(),
new_text: self.new_text.clone(),
}
}
}
Loading
Loading