Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
radicle-term: Remove custom pager
Lorenz Leutgeb committed 10 months ago
commit ec47566cb0af0fab62e00a65fd1f5aff7a867e79
parent 570bfc3bbd7692f7aa4fa28fae0ccd5c348b5532
3 files changed +1 -188
modified crates/radicle-cli/src/commands/diff.rs
@@ -145,7 +145,7 @@ pub fn run(options: Options, _ctx: impl term::Context) -> anyhow::Result<()> {
    let mut hi = Highlighter::default();
    let pretty = diff.pretty(&mut hi, &(), &repo);

-
    term::pager::page(pretty)?;
+
    crate::pager::run(pretty)?;

    Ok(())
}
modified crates/radicle-term/src/lib.rs
@@ -8,7 +8,6 @@ pub mod format;
pub mod hstack;
pub mod io;
pub mod label;
-
pub mod pager;
pub mod spinner;
pub mod table;
pub mod textarea;
deleted crates/radicle-term/src/pager.rs
@@ -1,186 +0,0 @@
-
use std::io::{IsTerminal, Write};
-
use std::{io, thread};
-

-
use crate::element::Size;
-
use crate::{Constraint, Element, Line, Paint};
-

-
use crossbeam_channel as chan;
-
use radicle_signals as signals;
-
use termion::event::{Event, Key, MouseButton, MouseEvent};
-
use termion::{input::TermRead, raw::IntoRawMode, screen::IntoAlternateScreen};
-

-
/// How many lines to scroll when the mouse wheel is used.
-
const MOUSE_SCROLL_LINES: usize = 3;
-

-
/// Pager error.
-
#[derive(Debug, thiserror::Error)]
-
pub enum Error {
-
    #[error(transparent)]
-
    Io(#[from] io::Error),
-
    #[error(transparent)]
-
    Channel(#[from] chan::RecvError),
-
}
-

-
/// A pager for the given element. Re-renders the element when the terminal is resized so that
-
/// it doesn't wrap. If the output device is not a TTY, just prints the element via
-
/// [`Element::print`].
-
///
-
/// # Signal Handling
-
///
-
/// This will install handlers for the pager until finished by the user, with there
-
/// being only one element handling signals at a time. If the pager cannot install
-
/// handlers, then it will return with an error.
-
pub fn page<E: Element + Send + 'static>(element: E) -> Result<(), Error> {
-
    let (events_tx, events_rx) = chan::unbounded();
-
    let (signals_tx, signals_rx) = chan::unbounded();
-

-
    signals::install(signals_tx)?;
-

-
    thread::spawn(move || {
-
        for e in io::stdin().events() {
-
            events_tx.send(e).ok();
-
        }
-
    });
-
    let result = thread::spawn(move || main(element, signals_rx, events_rx))
-
        .join()
-
        .unwrap();
-

-
    signals::uninstall()?;
-

-
    result
-
}
-

-
fn main<E: Element>(
-
    element: E,
-
    signals_rx: chan::Receiver<signals::Signal>,
-
    events_rx: chan::Receiver<Result<Event, io::Error>>,
-
) -> Result<(), Error> {
-
    let stdout = io::stdout();
-
    if !stdout.is_terminal() {
-
        element.print();
-
        return Ok(());
-
    }
-
    let raw = stdout.into_raw_mode()?;
-
    let mut stdout = termion::input::MouseTerminal::from(raw).into_alternate_screen()?;
-
    let (mut width, mut height) = termion::terminal_size()?;
-
    let mut lines = element.render(Constraint::max(Size::new(width as usize, height as usize)));
-
    let mut line = 0;
-

-
    render(&mut stdout, lines.as_slice(), line, (width, height))?;
-

-
    loop {
-
        chan::select! {
-
            recv(signals_rx) -> signal => {
-
                match signal? {
-
                    signals::Signal::WindowChanged => {
-
                        let (w, h) = termion::terminal_size()?;
-

-
                        lines = element.render(Constraint::max(Size::new(w as usize, h as usize)));
-
                        width = w;
-
                        height = h;
-
                    }
-
                    signals::Signal::Interrupt | signals::Signal::Terminate => {
-
                        break;
-
                    }
-
                    _ => continue,
-
                }
-
            }
-
            recv(events_rx) -> event => {
-
                let event = event??;
-
                let page = height as usize - 1; // Don't count the status bar.
-
                let end = if page > lines.len() { 0 } else { lines.len() - page };
-
                let prev = line;
-

-
                match event {
-
                    Event::Key(key) => match key {
-
                        Key::Up | Key::Char('k') => {
-
                            line = line.saturating_sub(1);
-
                        }
-
                        Key::Home => {
-
                            line = 0;
-
                        }
-
                        Key::End | Key::Char('G') => {
-
                            line = end;
-
                        }
-
                        Key::PageUp | Key::Char('b') => {
-
                            line = line.saturating_sub(page);
-
                        }
-
                        Key::PageDown | Key::Char(' ') => {
-
                            line = (line + page).min(end);
-
                        }
-
                        Key::Down | Key::Char('j') => {
-
                            if line < end {
-
                                line += 1;
-
                            }
-
                        }
-
                        Key::Char('q') => break,
-

-
                        _ => continue,
-
                    }
-
                    Event::Mouse(MouseEvent::Press(MouseButton::WheelDown, _, _)) => {
-
                        if line < end {
-
                            line += MOUSE_SCROLL_LINES;
-
                        }
-
                    }
-
                    Event::Mouse(MouseEvent::Press(MouseButton::WheelUp, _, _)) => {
-
                        line = line.saturating_sub(MOUSE_SCROLL_LINES);
-
                    }
-
                    _ => continue,
-
                }
-
                // Don't re-render if there's no change in line.
-
                if line == prev {
-
                    continue;
-
                }
-
            }
-
        }
-
        render(&mut stdout, &lines, line, (width, height))?;
-
    }
-
    Ok(())
-
}
-

-
fn render<W: Write>(
-
    out: &mut W,
-
    lines: &[Line],
-
    start_line: usize,
-
    (width, height): (u16, u16),
-
) -> io::Result<()> {
-
    write!(
-
        out,
-
        "{}{}",
-
        termion::clear::All,
-
        termion::cursor::Goto(1, 1)
-
    )?;
-

-
    let content_length = lines.len();
-
    let window_size = height as usize - 1;
-
    let end_line = if start_line + window_size > content_length {
-
        content_length
-
    } else {
-
        start_line + window_size
-
    };
-
    // Render content.
-
    for (ix, line) in lines[start_line..end_line].iter().enumerate() {
-
        write!(out, "{}{}", termion::cursor::Goto(1, ix as u16 + 1), line)?;
-
    }
-
    // Render progress meter.
-
    write!(
-
        out,
-
        "{}{}",
-
        termion::cursor::Goto(width - 3, height),
-
        Paint::new(format!(
-
            "{:.0}%",
-
            end_line as f64 / lines.len() as f64 * 100.
-
        ))
-
        .dim()
-
    )?;
-
    // Render cursor input area.
-
    write!(
-
        out,
-
        "{}{}",
-
        termion::cursor::Goto(1, height),
-
        Paint::new(":").dim()
-
    )?;
-
    out.flush()?;
-

-
    Ok(())
-
}