summaryrefslogtreecommitdiff
path: root/platforms/tortuise-script-compiled/src/buffer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'platforms/tortuise-script-compiled/src/buffer.rs')
-rw-r--r--platforms/tortuise-script-compiled/src/buffer.rs296
1 files changed, 296 insertions, 0 deletions
diff --git a/platforms/tortuise-script-compiled/src/buffer.rs b/platforms/tortuise-script-compiled/src/buffer.rs
new file mode 100644
index 0000000..c60ee40
--- /dev/null
+++ b/platforms/tortuise-script-compiled/src/buffer.rs
@@ -0,0 +1,296 @@
+use std::time::Duration;
+
+use crossterm::style::ContentStyle;
+use serde::{Deserialize, Serialize};
+use tortuise::script::Operation;
+
+use crate::ScriptContext;
+
+#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Serialize, Deserialize)]
+pub struct Cell {
+ pub character: char,
+ pub foreground_color: Color,
+ pub background_color: Color,
+ pub underline_color: Color,
+ pub attributes: Attributes,
+ pub x: u16,
+ pub y: u16,
+ pub z: u8,
+}
+
+#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Serialize, Deserialize)]
+pub struct WindowSize {
+ pub rows: u16,
+ pub columns: u16,
+}
+
+#[derive(
+ Copy, Clone, Debug, Default, PartialEq, Eq, Ord, PartialOrd, Hash, Serialize, Deserialize,
+)]
+pub enum Color {
+ /// Resets the terminal color.
+ #[default]
+ Reset,
+
+ /// Black color.
+ Black,
+
+ /// Dark grey color.
+ DarkGrey,
+
+ /// Light red color.
+ Red,
+
+ /// Dark red color.
+ DarkRed,
+
+ /// Light green color.
+ Green,
+
+ /// Dark green color.
+ DarkGreen,
+
+ /// Light yellow color.
+ Yellow,
+
+ /// Dark yellow color.
+ DarkYellow,
+
+ /// Light blue color.
+ Blue,
+
+ /// Dark blue color.
+ DarkBlue,
+
+ /// Light magenta color.
+ Magenta,
+
+ /// Dark magenta color.
+ DarkMagenta,
+
+ /// Light cyan color.
+ Cyan,
+
+ /// Dark cyan color.
+ DarkCyan,
+
+ /// White color.
+ White,
+
+ /// Grey color.
+ Grey,
+
+ /// An RGB color. See [RGB color model](https://en.wikipedia.org/wiki/RGB_color_model) for more info.
+ ///
+ /// Most UNIX terminals and Windows 10 supported only.
+ /// See [Platform-specific notes](enum.Color.html#platform-specific-notes) for more info.
+ Rgb { r: u8, g: u8, b: u8 },
+
+ /// An ANSI color. See [256 colors - cheat sheet](https://jonasjacek.github.io/colors/) for more info.
+ ///
+ /// Most UNIX terminals and Windows 10 supported only.
+ /// See [Platform-specific notes](enum.Color.html#platform-specific-notes) for more info.
+ AnsiValue(u8),
+}
+
+#[derive(
+ Copy, Clone, Debug, Default, PartialEq, Eq, Ord, PartialOrd, Hash, Serialize, Deserialize,
+)]
+pub struct Attributes(u32);
+
+pub enum Attribute {
+ /// Increases the text intensity.
+ Bold = 1,
+ /// Decreases the text intensity.
+ Dim = 2,
+ /// Emphasises the text.
+ Italic = 4,
+ /// Underlines the text.
+ Underlined = 8,
+
+ // Other types of underlining
+ /// Double underlines the text.
+ DoubleUnderlined = 16,
+ /// Undercurls the text.
+ Undercurled = 32,
+ /// Underdots the text.
+ Underdotted = 64,
+ /// Underdashes the text.
+ Underdashed = 128,
+
+ /// Makes the text blinking (< 150 per minute).
+ SlowBlink = 256,
+ /// Makes the text blinking (>= 150 per minute).
+ RapidBlink = 512,
+ /// Swaps foreground and background colors.
+ Reverse = 1024,
+ /// Hides the text (also known as Conceal).
+ Hidden = 2048,
+ /// Crosses the text.
+ CrossedOut = 4096,
+ /// Sets the [Fraktur](https://en.wikipedia.org/wiki/Fraktur) typeface.
+ ///
+ /// Mostly used for [mathematical alphanumeric symbols](https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols).
+ Fraktur = 8192,
+ /// Makes the text framed.
+ Framed = 16384,
+ /// Makes the text encircled.
+ Encircled = 32768,
+ /// Draws a line at the top of the text.
+ OverLined = 65536,
+}
+
+impl Attributes {
+ pub fn none() -> Self {
+ Self(0)
+ }
+
+ pub fn with(self, attribute: Attribute) -> Self {
+ Self(self.0 | attribute as u32)
+ }
+
+ pub fn without(self, attribute: Attribute) -> Self {
+ Self(self.0 & !(attribute as u32))
+ }
+
+ pub fn set(&mut self, attribute: Attribute) {
+ self.0 |= attribute as u32;
+ }
+
+ pub fn unset(&mut self, attribute: Attribute) {
+ self.0 &= !(attribute as u32)
+ }
+
+ pub fn has(self, attribute: Attribute) -> bool {
+ self.0 & (attribute as u32) != 0
+ }
+
+ pub fn extend(&mut self, attributes: Attributes) {
+ self.0 |= attributes.0
+ }
+
+ pub fn is_empty(self) -> bool {
+ self.0 == 0
+ }
+}
+
+impl From<Color> for crossterm::style::Color {
+ fn from(value: Color) -> Self {
+ match value {
+ Color::Reset => crossterm::style::Color::Reset,
+ Color::Black => crossterm::style::Color::Black,
+ Color::DarkGrey => crossterm::style::Color::DarkGrey,
+ Color::Red => crossterm::style::Color::Red,
+ Color::DarkRed => crossterm::style::Color::DarkRed,
+ Color::Green => crossterm::style::Color::Green,
+ Color::DarkGreen => crossterm::style::Color::DarkGreen,
+ Color::Yellow => crossterm::style::Color::Yellow,
+ Color::DarkYellow => crossterm::style::Color::DarkYellow,
+ Color::Blue => crossterm::style::Color::Blue,
+ Color::DarkBlue => crossterm::style::Color::DarkBlue,
+ Color::Magenta => crossterm::style::Color::Magenta,
+ Color::DarkMagenta => crossterm::style::Color::DarkMagenta,
+ Color::Cyan => crossterm::style::Color::Cyan,
+ Color::DarkCyan => crossterm::style::Color::DarkCyan,
+ Color::White => crossterm::style::Color::White,
+ Color::Grey => crossterm::style::Color::Grey,
+ Color::Rgb { r, g, b } => crossterm::style::Color::Rgb { r, g, b },
+ Color::AnsiValue(v) => crossterm::style::Color::AnsiValue(v),
+ }
+ }
+}
+
+impl From<Attributes> for crossterm::style::Attributes {
+ fn from(value: Attributes) -> Self {
+ let mut new = crossterm::style::Attributes::none();
+
+ if value.has(Attribute::Bold) {
+ new.set(crossterm::style::Attribute::Bold);
+ }
+ if value.has(Attribute::Dim) {
+ new.set(crossterm::style::Attribute::Dim);
+ }
+ if value.has(Attribute::Italic) {
+ new.set(crossterm::style::Attribute::Italic);
+ }
+ if value.has(Attribute::Underlined) {
+ new.set(crossterm::style::Attribute::Underlined);
+ }
+ if value.has(Attribute::DoubleUnderlined) {
+ new.set(crossterm::style::Attribute::DoubleUnderlined);
+ }
+ if value.has(Attribute::Undercurled) {
+ new.set(crossterm::style::Attribute::Undercurled);
+ }
+ if value.has(Attribute::Underdotted) {
+ new.set(crossterm::style::Attribute::Underdotted);
+ }
+ if value.has(Attribute::Underdashed) {
+ new.set(crossterm::style::Attribute::Underdashed);
+ }
+ if value.has(Attribute::SlowBlink) {
+ new.set(crossterm::style::Attribute::SlowBlink);
+ }
+ if value.has(Attribute::RapidBlink) {
+ new.set(crossterm::style::Attribute::RapidBlink);
+ }
+ if value.has(Attribute::Reverse) {
+ new.set(crossterm::style::Attribute::Reverse);
+ }
+ if value.has(Attribute::Hidden) {
+ new.set(crossterm::style::Attribute::Hidden);
+ }
+ if value.has(Attribute::CrossedOut) {
+ new.set(crossterm::style::Attribute::CrossedOut);
+ }
+ if value.has(Attribute::Fraktur) {
+ new.set(crossterm::style::Attribute::Fraktur);
+ }
+ if value.has(Attribute::Framed) {
+ new.set(crossterm::style::Attribute::Framed);
+ }
+ if value.has(Attribute::Encircled) {
+ new.set(crossterm::style::Attribute::Encircled);
+ }
+ if value.has(Attribute::OverLined) {
+ new.set(crossterm::style::Attribute::OverLined);
+ }
+
+ new
+ }
+}
+
+impl ScriptContext<'_> {
+ pub fn add_cell(&mut self, cell: Cell) {
+ puffin::profile_function!();
+ self.0
+ .operation_queue
+ .push(Operation::AddCell(tortuise::buffer::Cell {
+ character: cell.character,
+ style: ContentStyle {
+ foreground_color: Some(cell.foreground_color.into()),
+ background_color: Some(cell.background_color.into()),
+ underline_color: Some(cell.underline_color.into()),
+ attributes: cell.attributes.into(),
+ },
+ x: cell.x,
+ y: cell.y,
+ z: cell.z,
+ }));
+ }
+
+ pub fn window_size(&self) -> WindowSize {
+ puffin::profile_function!();
+ let size = &self.0.buffer.window_size;
+ WindowSize {
+ rows: size.rows,
+ columns: size.columns,
+ }
+ }
+
+ pub fn set_framerate_limit(&mut self, limit: Option<u32>) {
+ puffin::profile_function!();
+ let limit = limit.map(|limit| Duration::from_nanos(1_000_000_000 / limit as u64));
+ self.0.operation_queue.push(Operation::SetFrameLimit(limit));
+ }
+}