aboutsummaryrefslogtreecommitdiffstats
path: root/src/ratatui/backend
diff options
context:
space:
mode:
authorVladislav Stepanov <8uk.8ak@gmail.com>2023-04-14 23:18:58 +0400
committerGitHub <noreply@github.com>2023-04-14 20:18:58 +0100
commitc05d2850420a2c163b8f62c33a6cef7c0ae1ad8d (patch)
tree2c44a44eda7e76fa74e78ac1fd02f55c1ed4d804 /src/ratatui/backend
parentSwitch to uuidv7 (#864) (diff)
downloadatuin-c05d2850420a2c163b8f62c33a6cef7c0ae1ad8d.zip
Workspace reorder (#868)
* Try different workspace structure Move main crate (atuin) to be on the same level with other crates in this workspace * extract common dependencies to the workspace definition * fix base64 v0.21 deprecation warning * questionable: update deps & fix chrono deprecations possible panic sites are unchanged, they're just more visible now * Revert "questionable: update deps & fix chrono deprecations" This reverts commit 993e60f8dea81a1625a04285a617959ad09a0866.
Diffstat (limited to 'src/ratatui/backend')
-rw-r--r--src/ratatui/backend/crossterm.rs241
-rw-r--r--src/ratatui/backend/mod.rs58
-rw-r--r--src/ratatui/backend/termion.rs275
3 files changed, 0 insertions, 574 deletions
diff --git a/src/ratatui/backend/crossterm.rs b/src/ratatui/backend/crossterm.rs
deleted file mode 100644
index 3dceb6ad..00000000
--- a/src/ratatui/backend/crossterm.rs
+++ /dev/null
@@ -1,241 +0,0 @@
-use crate::ratatui::{
- backend::{Backend, ClearType},
- buffer::Cell,
- layout::Rect,
- style::{Color, Modifier},
-};
-use crossterm::{
- cursor::{Hide, MoveTo, Show},
- execute, queue,
- style::{
- Attribute as CAttribute, Color as CColor, Print, SetAttribute, SetBackgroundColor,
- SetForegroundColor,
- },
- terminal::{self, Clear},
-};
-use std::io::{self, Write};
-
-pub struct CrosstermBackend<W: Write> {
- buffer: W,
-}
-
-impl<W> CrosstermBackend<W>
-where
- W: Write,
-{
- pub fn new(buffer: W) -> CrosstermBackend<W> {
- CrosstermBackend { buffer }
- }
-}
-
-impl<W> Write for CrosstermBackend<W>
-where
- W: Write,
-{
- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- self.buffer.write(buf)
- }
-
- fn flush(&mut self) -> io::Result<()> {
- self.buffer.flush()
- }
-}
-
-impl<W> Backend for CrosstermBackend<W>
-where
- W: Write,
-{
- fn draw<'a, I>(&mut self, content: I) -> io::Result<()>
- where
- I: Iterator<Item = (u16, u16, &'a Cell)>,
- {
- let mut fg = Color::Reset;
- let mut bg = Color::Reset;
- let mut modifier = Modifier::empty();
- let mut last_pos: Option<(u16, u16)> = None;
- for (x, y, cell) in content {
- // Move the cursor if the previous location was not (x - 1, y)
- if !matches!(last_pos, Some(p) if x == p.0 + 1 && y == p.1) {
- map_error(queue!(self.buffer, MoveTo(x, y)))?;
- }
- last_pos = Some((x, y));
- if cell.modifier != modifier {
- let diff = ModifierDiff {
- from: modifier,
- to: cell.modifier,
- };
- diff.queue(&mut self.buffer)?;
- modifier = cell.modifier;
- }
- if cell.fg != fg {
- let color = CColor::from(cell.fg);
- map_error(queue!(self.buffer, SetForegroundColor(color)))?;
- fg = cell.fg;
- }
- if cell.bg != bg {
- let color = CColor::from(cell.bg);
- map_error(queue!(self.buffer, SetBackgroundColor(color)))?;
- bg = cell.bg;
- }
-
- map_error(queue!(self.buffer, Print(&cell.symbol)))?;
- }
-
- map_error(queue!(
- self.buffer,
- SetForegroundColor(CColor::Reset),
- SetBackgroundColor(CColor::Reset),
- SetAttribute(CAttribute::Reset)
- ))
- }
-
- fn hide_cursor(&mut self) -> io::Result<()> {
- map_error(execute!(self.buffer, Hide))
- }
-
- fn show_cursor(&mut self) -> io::Result<()> {
- map_error(execute!(self.buffer, Show))
- }
-
- fn get_cursor(&mut self) -> io::Result<(u16, u16)> {
- crossterm::cursor::position()
- .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))
- }
-
- fn set_cursor(&mut self, x: u16, y: u16) -> io::Result<()> {
- map_error(execute!(self.buffer, MoveTo(x, y)))
- }
-
- fn clear(&mut self) -> io::Result<()> {
- self.clear_region(ClearType::All)
- }
-
- fn clear_region(&mut self, clear_type: ClearType) -> io::Result<()> {
- map_error(execute!(
- self.buffer,
- Clear(match clear_type {
- ClearType::All => crossterm::terminal::ClearType::All,
- ClearType::AfterCursor => crossterm::terminal::ClearType::FromCursorDown,
- ClearType::BeforeCursor => crossterm::terminal::ClearType::FromCursorUp,
- ClearType::CurrentLine => crossterm::terminal::ClearType::CurrentLine,
- ClearType::UntilNewLine => crossterm::terminal::ClearType::UntilNewLine,
- })
- ))
- }
-
- fn append_lines(&mut self, n: u16) -> io::Result<()> {
- for _ in 0..n {
- map_error(queue!(self.buffer, Print("\n")))?;
- }
- self.buffer.flush()
- }
-
- fn size(&self) -> io::Result<Rect> {
- let (width, height) =
- terminal::size().map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?;
-
- Ok(Rect::new(0, 0, width, height))
- }
-
- fn flush(&mut self) -> io::Result<()> {
- self.buffer.flush()
- }
-}
-
-fn map_error(error: crossterm::Result<()>) -> io::Result<()> {
- error.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))
-}
-
-impl From<Color> for CColor {
- fn from(color: Color) -> Self {
- match color {
- Color::Reset => CColor::Reset,
- Color::Black => CColor::Black,
- Color::Red => CColor::DarkRed,
- Color::Green => CColor::DarkGreen,
- Color::Yellow => CColor::DarkYellow,
- Color::Blue => CColor::DarkBlue,
- Color::Magenta => CColor::DarkMagenta,
- Color::Cyan => CColor::DarkCyan,
- Color::Gray => CColor::Grey,
- Color::DarkGray => CColor::DarkGrey,
- Color::LightRed => CColor::Red,
- Color::LightGreen => CColor::Green,
- Color::LightBlue => CColor::Blue,
- Color::LightYellow => CColor::Yellow,
- Color::LightMagenta => CColor::Magenta,
- Color::LightCyan => CColor::Cyan,
- Color::White => CColor::White,
- Color::Indexed(i) => CColor::AnsiValue(i),
- Color::Rgb(r, g, b) => CColor::Rgb { r, g, b },
- }
- }
-}
-
-#[derive(Debug)]
-struct ModifierDiff {
- pub from: Modifier,
- pub to: Modifier,
-}
-
-impl ModifierDiff {
- fn queue<W>(&self, mut w: W) -> io::Result<()>
- where
- W: io::Write,
- {
- //use crossterm::Attribute;
- let removed = self.from - self.to;
- if removed.contains(Modifier::REVERSED) {
- map_error(queue!(w, SetAttribute(CAttribute::NoReverse)))?;
- }
- if removed.contains(Modifier::BOLD) {
- map_error(queue!(w, SetAttribute(CAttribute::NormalIntensity)))?;
- if self.to.contains(Modifier::DIM) {
- map_error(queue!(w, SetAttribute(CAttribute::Dim)))?;
- }
- }
- if removed.contains(Modifier::ITALIC) {
- map_error(queue!(w, SetAttribute(CAttribute::NoItalic)))?;
- }
- if removed.contains(Modifier::UNDERLINED) {
- map_error(queue!(w, SetAttribute(CAttribute::NoUnderline)))?;
- }
- if removed.contains(Modifier::DIM) {
- map_error(queue!(w, SetAttribute(CAttribute::NormalIntensity)))?;
- }
- if removed.contains(Modifier::CROSSED_OUT) {
- map_error(queue!(w, SetAttribute(CAttribute::NotCrossedOut)))?;
- }
- if removed.contains(Modifier::SLOW_BLINK) || removed.contains(Modifier::RAPID_BLINK) {
- map_error(queue!(w, SetAttribute(CAttribute::NoBlink)))?;
- }
-
- let added = self.to - self.from;
- if added.contains(Modifier::REVERSED) {
- map_error(queue!(w, SetAttribute(CAttribute::Reverse)))?;
- }
- if added.contains(Modifier::BOLD) {
- map_error(queue!(w, SetAttribute(CAttribute::Bold)))?;
- }
- if added.contains(Modifier::ITALIC) {
- map_error(queue!(w, SetAttribute(CAttribute::Italic)))?;
- }
- if added.contains(Modifier::UNDERLINED) {
- map_error(queue!(w, SetAttribute(CAttribute::Underlined)))?;
- }
- if added.contains(Modifier::DIM) {
- map_error(queue!(w, SetAttribute(CAttribute::Dim)))?;
- }
- if added.contains(Modifier::CROSSED_OUT) {
- map_error(queue!(w, SetAttribute(CAttribute::CrossedOut)))?;
- }
- if added.contains(Modifier::SLOW_BLINK) {
- map_error(queue!(w, SetAttribute(CAttribute::SlowBlink)))?;
- }
- if added.contains(Modifier::RAPID_BLINK) {
- map_error(queue!(w, SetAttribute(CAttribute::RapidBlink)))?;
- }
-
- Ok(())
- }
-}
diff --git a/src/ratatui/backend/mod.rs b/src/ratatui/backend/mod.rs
deleted file mode 100644
index a360db18..00000000
--- a/src/ratatui/backend/mod.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-use std::io;
-
-use crate::ratatui::buffer::Cell;
-use crate::ratatui::layout::Rect;
-
-#[cfg(feature = "termion")]
-mod termion;
-#[cfg(feature = "termion")]
-pub use self::termion::TermionBackend;
-
-mod crossterm;
-pub use self::crossterm::CrosstermBackend;
-
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub enum ClearType {
- All,
- AfterCursor,
- BeforeCursor,
- CurrentLine,
- UntilNewLine,
-}
-
-pub trait Backend {
- fn draw<'a, I>(&mut self, content: I) -> Result<(), io::Error>
- where
- I: Iterator<Item = (u16, u16, &'a Cell)>;
-
- /// Insert `n` line breaks to the terminal screen
- fn append_lines(&mut self, n: u16) -> io::Result<()> {
- // to get around the unused warning
- let _n = n;
- Ok(())
- }
-
- fn hide_cursor(&mut self) -> Result<(), io::Error>;
- fn show_cursor(&mut self) -> Result<(), io::Error>;
- fn get_cursor(&mut self) -> Result<(u16, u16), io::Error>;
- fn set_cursor(&mut self, x: u16, y: u16) -> Result<(), io::Error>;
-
- /// Clears the whole terminal screen
- fn clear(&mut self) -> Result<(), io::Error>;
-
- /// Clears a specific region of the terminal specified by the [`ClearType`] parameter
- fn clear_region(&mut self, clear_type: ClearType) -> Result<(), io::Error> {
- match clear_type {
- ClearType::All => self.clear(),
- ClearType::AfterCursor
- | ClearType::BeforeCursor
- | ClearType::CurrentLine
- | ClearType::UntilNewLine => Err(io::Error::new(
- io::ErrorKind::Other,
- format!("clear_type [{clear_type:?}] not supported with this backend"),
- )),
- }
- }
- fn size(&self) -> Result<Rect, io::Error>;
- fn flush(&mut self) -> Result<(), io::Error>;
-}
diff --git a/src/ratatui/backend/termion.rs b/src/ratatui/backend/termion.rs
deleted file mode 100644
index 76def792..00000000
--- a/src/ratatui/backend/termion.rs
+++ /dev/null
@@ -1,275 +0,0 @@
-use crate::{
- backend::{Backend, ClearType},
- buffer::Cell,
- layout::Rect,
- style::{Color, Modifier},
-};
-use std::{
- fmt,
- io::{self, Write},
-};
-
-pub struct TermionBackend<W>
-where
- W: Write,
-{
- stdout: W,
-}
-
-impl<W> TermionBackend<W>
-where
- W: Write,
-{
- pub fn new(stdout: W) -> TermionBackend<W> {
- TermionBackend { stdout }
- }
-}
-
-impl<W> Write for TermionBackend<W>
-where
- W: Write,
-{
- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- self.stdout.write(buf)
- }
-
- fn flush(&mut self) -> io::Result<()> {
- self.stdout.flush()
- }
-}
-
-impl<W> Backend for TermionBackend<W>
-where
- W: Write,
-{
- fn clear(&mut self) -> io::Result<()> {
- self.clear_region(ClearType::All)
- }
-
- fn clear_region(&mut self, clear_type: ClearType) -> io::Result<()> {
- match clear_type {
- ClearType::All => write!(self.stdout, "{}", termion::clear::All)?,
- ClearType::AfterCursor => write!(self.stdout, "{}", termion::clear::AfterCursor)?,
- ClearType::BeforeCursor => write!(self.stdout, "{}", termion::clear::BeforeCursor)?,
- ClearType::CurrentLine => write!(self.stdout, "{}", termion::clear::CurrentLine)?,
- ClearType::UntilNewLine => write!(self.stdout, "{}", termion::clear::UntilNewline)?,
- };
- self.stdout.flush()
- }
-
- fn append_lines(&mut self, n: u16) -> io::Result<()> {
- for _ in 0..n {
- writeln!(self.stdout)?;
- }
- self.stdout.flush()
- }
-
- /// Hides cursor
- fn hide_cursor(&mut self) -> io::Result<()> {
- write!(self.stdout, "{}", termion::cursor::Hide)?;
- self.stdout.flush()
- }
-
- /// Shows cursor
- fn show_cursor(&mut self) -> io::Result<()> {
- write!(self.stdout, "{}", termion::cursor::Show)?;
- self.stdout.flush()
- }
-
- /// Gets cursor position (0-based index)
- fn get_cursor(&mut self) -> io::Result<(u16, u16)> {
- termion::cursor::DetectCursorPos::cursor_pos(&mut self.stdout).map(|(x, y)| (x - 1, y - 1))
- }
-
- /// Sets cursor position (0-based index)
- fn set_cursor(&mut self, x: u16, y: u16) -> io::Result<()> {
- write!(self.stdout, "{}", termion::cursor::Goto(x + 1, y + 1))?;
- self.stdout.flush()
- }
-
- fn draw<'a, I>(&mut self, content: I) -> io::Result<()>
- where
- I: Iterator<Item = (u16, u16, &'a Cell)>,
- {
- use std::fmt::Write;
-
- let mut string = String::with_capacity(content.size_hint().0 * 3);
- let mut fg = Color::Reset;
- let mut bg = Color::Reset;
- let mut modifier = Modifier::empty();
- let mut last_pos: Option<(u16, u16)> = None;
- for (x, y, cell) in content {
- // Move the cursor if the previous location was not (x - 1, y)
- if !matches!(last_pos, Some(p) if x == p.0 + 1 && y == p.1) {
- write!(string, "{}", termion::cursor::Goto(x + 1, y + 1)).unwrap();
- }
- last_pos = Some((x, y));
- if cell.modifier != modifier {
- write!(
- string,
- "{}",
- ModifierDiff {
- from: modifier,
- to: cell.modifier
- }
- )
- .unwrap();
- modifier = cell.modifier;
- }
- if cell.fg != fg {
- write!(string, "{}", Fg(cell.fg)).unwrap();
- fg = cell.fg;
- }
- if cell.bg != bg {
- write!(string, "{}", Bg(cell.bg)).unwrap();
- bg = cell.bg;
- }
- string.push_str(&cell.symbol);
- }
- write!(
- self.stdout,
- "{}{}{}{}",
- string,
- Fg(Color::Reset),
- Bg(Color::Reset),
- termion::style::Reset,
- )
- }
-
- /// Return the size of the terminal
- fn size(&self) -> io::Result<Rect> {
- let terminal = termion::terminal_size()?;
- Ok(Rect::new(0, 0, terminal.0, terminal.1))
- }
-
- fn flush(&mut self) -> io::Result<()> {
- self.stdout.flush()
- }
-}
-
-struct Fg(Color);
-
-struct Bg(Color);
-
-struct ModifierDiff {
- from: Modifier,
- to: Modifier,
-}
-
-impl fmt::Display for Fg {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- use termion::color::Color as TermionColor;
- match self.0 {
- Color::Reset => termion::color::Reset.write_fg(f),
- Color::Black => termion::color::Black.write_fg(f),
- Color::Red => termion::color::Red.write_fg(f),
- Color::Green => termion::color::Green.write_fg(f),
- Color::Yellow => termion::color::Yellow.write_fg(f),
- Color::Blue => termion::color::Blue.write_fg(f),
- Color::Magenta => termion::color::Magenta.write_fg(f),
- Color::Cyan => termion::color::Cyan.write_fg(f),
- Color::Gray => termion::color::White.write_fg(f),
- Color::DarkGray => termion::color::LightBlack.write_fg(f),
- Color::LightRed => termion::color::LightRed.write_fg(f),
- Color::LightGreen => termion::color::LightGreen.write_fg(f),
- Color::LightBlue => termion::color::LightBlue.write_fg(f),
- Color::LightYellow => termion::color::LightYellow.write_fg(f),
- Color::LightMagenta => termion::color::LightMagenta.write_fg(f),
- Color::LightCyan => termion::color::LightCyan.write_fg(f),
- Color::White => termion::color::LightWhite.write_fg(f),
- Color::Indexed(i) => termion::color::AnsiValue(i).write_fg(f),
- Color::Rgb(r, g, b) => termion::color::Rgb(r, g, b).write_fg(f),
- }
- }
-}
-impl fmt::Display for Bg {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- use termion::color::Color as TermionColor;
- match self.0 {
- Color::Reset => termion::color::Reset.write_bg(f),
- Color::Black => termion::color::Black.write_bg(f),
- Color::Red => termion::color::Red.write_bg(f),
- Color::Green => termion::color::Green.write_bg(f),
- Color::Yellow => termion::color::Yellow.write_bg(f),
- Color::Blue => termion::color::Blue.write_bg(f),
- Color::Magenta => termion::color::Magenta.write_bg(f),
- Color::Cyan => termion::color::Cyan.write_bg(f),
- Color::Gray => termion::color::White.write_bg(f),
- Color::DarkGray => termion::color::LightBlack.write_bg(f),
- Color::LightRed => termion::color::LightRed.write_bg(f),
- Color::LightGreen => termion::color::LightGreen.write_bg(f),
- Color::LightBlue => termion::color::LightBlue.write_bg(f),
- Color::LightYellow => termion::color::LightYellow.write_bg(f),
- Color::LightMagenta => termion::color::LightMagenta.write_bg(f),
- Color::LightCyan => termion::color::LightCyan.write_bg(f),
- Color::White => termion::color::LightWhite.write_bg(f),
- Color::Indexed(i) => termion::color::AnsiValue(i).write_bg(f),
- Color::Rgb(r, g, b) => termion::color::Rgb(r, g, b).write_bg(f),
- }
- }
-}
-
-impl fmt::Display for ModifierDiff {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let remove = self.from - self.to;
- if remove.contains(Modifier::REVERSED) {
- write!(f, "{}", termion::style::NoInvert)?;
- }
- if remove.contains(Modifier::BOLD) {
- // XXX: the termion NoBold flag actually enables double-underline on ECMA-48 compliant
- // terminals, and NoFaint additionally disables bold... so we use this trick to get
- // the right semantics.
- write!(f, "{}", termion::style::NoFaint)?;
-
- if self.to.contains(Modifier::DIM) {
- write!(f, "{}", termion::style::Faint)?;
- }
- }
- if remove.contains(Modifier::ITALIC) {
- write!(f, "{}", termion::style::NoItalic)?;
- }
- if remove.contains(Modifier::UNDERLINED) {
- write!(f, "{}", termion::style::NoUnderline)?;
- }
- if remove.contains(Modifier::DIM) {
- write!(f, "{}", termion::style::NoFaint)?;
-
- // XXX: the NoFaint flag additionally disables bold as well, so we need to re-enable it
- // here if we want it.
- if self.to.contains(Modifier::BOLD) {
- write!(f, "{}", termion::style::Bold)?;
- }
- }
- if remove.contains(Modifier::CROSSED_OUT) {
- write!(f, "{}", termion::style::NoCrossedOut)?;
- }
- if remove.contains(Modifier::SLOW_BLINK) || remove.contains(Modifier::RAPID_BLINK) {
- write!(f, "{}", termion::style::NoBlink)?;
- }
-
- let add = self.to - self.from;
- if add.contains(Modifier::REVERSED) {
- write!(f, "{}", termion::style::Invert)?;
- }
- if add.contains(Modifier::BOLD) {
- write!(f, "{}", termion::style::Bold)?;
- }
- if add.contains(Modifier::ITALIC) {
- write!(f, "{}", termion::style::Italic)?;
- }
- if add.contains(Modifier::UNDERLINED) {
- write!(f, "{}", termion::style::Underline)?;
- }
- if add.contains(Modifier::DIM) {
- write!(f, "{}", termion::style::Faint)?;
- }
- if add.contains(Modifier::CROSSED_OUT) {
- write!(f, "{}", termion::style::CrossedOut)?;
- }
- if add.contains(Modifier::SLOW_BLINK) || add.contains(Modifier::RAPID_BLINK) {
- write!(f, "{}", termion::style::Blink)?;
- }
-
- Ok(())
- }
-}