返回 CodeWhale
verification.rs
根目录 / vendor / codewhale-ratatui / src / components / verification.rs
1 //! The Engine's verification tick, distinct from its working swell.
2 //!
3 //! The frame table and cadence come from `Hmbown/CodeWhale`
4 //! `a79ce5c4d5ed1a5f7032185710c27343a900351c`,
5 //! `crates/tui/src/tui/spinner.rs::verification_tick_frame`. Earned delay,
6 //! ASCII rotation, elapsed words and quiet-mode marks share this kit's
7 //! [`Spinner`]. The caller supplies elapsed time and owns all scheduling.
8
9 use std::time::Duration;
10
11 use crate::{MotionMode, Paint, Spinner, Theme, spin};
12 use ratatui::{
13 buffer::Buffer,
14 layout::Rect,
15 text::{Line, Span},
16 };
17
18 /// A checking phase uses a round tick while working uses a swell.
19 ///
20 /// Construct it only for verification the host has actually observed. The
21 /// verb is caller-owned, and the elapsed time is measured rather than a
22 /// progress estimate. Reduced and still motion show a static mark and word.
23 #[derive(Clone, Debug, PartialEq, Eq)]
24 pub struct VerificationSpinner {
25 pub verb: String,
26 pub elapsed: Duration,
27 pub motion: MotionMode,
28 }
29
30 impl VerificationSpinner {
31 /// The Engine's eight adjacent verification frames.
32 pub const FRAMES: [&'static str; 8] = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧"];
33
34 #[must_use]
35 pub fn new(verb: impl Into<String>, elapsed: Duration, motion: MotionMode) -> Self {
36 Self {
37 verb: verb.into(),
38 elapsed,
39 motion,
40 }
41 }
42
43 /// Sample a verification frame without reading a clock.
44 #[must_use]
45 pub fn frame(elapsed: Duration, motion: MotionMode, ascii: bool) -> &'static str {
46 if !motion.animates() || ascii || elapsed < spin::EARN_DELAY {
47 return spin::frame(elapsed, motion, ascii);
48 }
49 let step = (elapsed - spin::EARN_DELAY).as_millis() / spin::FRAME_INTERVAL.as_millis();
50 Self::FRAMES[(step % Self::FRAMES.len() as u128) as usize]
51 }
52
53 /// The shared five-step cadence; quiet motion asks for no redraws.
54 #[must_use]
55 pub fn next_frame_in(elapsed: Duration, motion: MotionMode) -> Option<Duration> {
56 spin::next_frame_in(elapsed, motion)
57 }
58
59 /// A tick, the caller's sanitized verb and the shared measured-time words.
60 #[must_use]
61 pub fn spans(&self, theme: &Theme) -> Vec<Span<'static>> {
62 let mut spans = Spinner::new(&self.verb, self.elapsed, self.motion).spans(theme);
63 spans[0].content = Self::frame(self.elapsed, self.motion, theme.ascii()).into();
64 spans
65 }
66 }
67
68 impl Paint for VerificationSpinner {
69 fn paint(&self, area: Rect, buf: &mut Buffer, theme: &Theme) {
70 let area = area.intersection(buf.area);
71 if !area.is_empty() {
72 // Buffer::set_line also handles a right edge of u16::MAX, where
73 // the widget Line renderer can overflow while clipping a span.
74 super::workbench::row(area, buf, &Line::from(self.spans(theme)));
75 }
76 }
77 }
78
78 lines RUST