mod dirty_rows;
mod shell;
mod transcript;
pub use dirty_rows::DirtyRows;
pub use shell::{
Command, CommandId, PromptId, PromptOutcome, ShellEvent, ShellTracker, VisiblePrompt,
};
pub use transcript::Transcript;
use crate::{Anchor, Line, Operation, Position, Terminal};
use std::ops::Range;
pub struct Observation<'a> {
terminal: &'a mut Terminal,
}
impl<'a> Observation<'a> {
pub(crate) fn new(terminal: &'a mut Terminal) -> Self {
Self { terminal }
}
pub fn terminal(&self) -> &Terminal {
self.terminal
}
pub fn anchor_at_cursor(&mut self) -> Anchor {
self.terminal.anchor_at_cursor()
}
pub fn anchor_at(&mut self, position: Position) -> Option<Anchor> {
self.terminal.anchor_at(position)
}
pub fn resolve(&self, anchor: &Anchor) -> Option<Position> {
self.terminal.resolve(anchor)
}
}
pub trait Observer {
type Output;
fn begin(&mut self, _context: &mut Observation<'_>) {}
fn before(&mut self, _context: &mut Observation<'_>, _operation: &Operation) {}
fn resized(&mut self, _cols: usize, _rows: usize) {}
fn dirty(&mut self, _rows: Range<usize>) {}
fn after(&mut self, _context: &mut Observation<'_>, _operation: &Operation) {}
fn evicted(&mut self, _context: &mut Observation<'_>, _line: &Line) {}
fn end(&mut self, context: &mut Observation<'_>) -> Self::Output;
}
impl<O: Observer + ?Sized> crate::engine::Effects for O {
fn dirty(&mut self, rows: Range<usize>) {
Observer::dirty(self, rows);
}
fn resized(&mut self, cols: usize, rows: usize) {
Observer::resized(self, cols, rows);
}
}
impl Observer for () {
type Output = ();
fn end(&mut self, _: &mut Observation<'_>) {}
}
impl<O: Observer + ?Sized> Observer for &mut O {
type Output = O::Output;
fn begin(&mut self, context: &mut Observation<'_>) {
(**self).begin(context);
}
fn before(&mut self, context: &mut Observation<'_>, operation: &Operation) {
(**self).before(context, operation);
}
fn resized(&mut self, cols: usize, rows: usize) {
(**self).resized(cols, rows);
}
fn dirty(&mut self, rows: Range<usize>) {
(**self).dirty(rows);
}
fn after(&mut self, context: &mut Observation<'_>, operation: &Operation) {
(**self).after(context, operation);
}
fn evicted(&mut self, context: &mut Observation<'_>, line: &Line) {
(**self).evicted(context, line);
}
fn end(&mut self, context: &mut Observation<'_>) -> Self::Output {
(**self).end(context)
}
}
impl<A: Observer, B: Observer> Observer for (A, B) {
type Output = (A::Output, B::Output);
fn begin(&mut self, context: &mut Observation<'_>) {
self.0.begin(context);
self.1.begin(context);
}
fn before(&mut self, context: &mut Observation<'_>, operation: &Operation) {
self.0.before(context, operation);
self.1.before(context, operation);
}
fn resized(&mut self, cols: usize, rows: usize) {
self.0.resized(cols, rows);
self.1.resized(cols, rows);
}
fn dirty(&mut self, rows: Range<usize>) {
self.0.dirty(rows.clone());
self.1.dirty(rows);
}
fn after(&mut self, context: &mut Observation<'_>, operation: &Operation) {
self.0.after(context, operation);
self.1.after(context, operation);
}
fn evicted(&mut self, context: &mut Observation<'_>, line: &Line) {
self.0.evicted(context, line);
self.1.evicted(context, line);
}
fn end(&mut self, context: &mut Observation<'_>) -> Self::Output {
(self.0.end(context), self.1.end(context))
}
}