diff --git a/src/lib.rs b/src/lib.rs index b21c5d7..2ae1c73 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,133 +10,10 @@ use termion::terminal_size; use termion::{clear, cursor}; pub mod tile; +pub mod utils; use tile::{Tile, TileBuilder}; -/// Draws a box from (x1, y1) to (x2, y2). -pub fn rect((x1, y1): (u16, u16), (x2, y2): (u16, u16)) -> String { - let mut buffer = vec![]; - - buffer.push(format!("{}┌", cursor::Goto(x1, y1))); - - for _ in (x1 + 1)..x2 { - buffer.push(format!("─")); - } - - buffer.push(format!("┐")); - - for y in (y1 + 1)..y2 { - buffer.push(format!("{}│", cursor::Goto(x1, y))); - buffer.push(format!("{}│", cursor::Goto(x2, y))); - } - - buffer.push(format!("{}└", cursor::Goto(x1, y2))); - - for _ in (x1 + 1)..x2 { - buffer.push(format!("─")); - } - - buffer.push(format!("┘")); - - buffer.join("") -} - -/// Returns the length of a string containing colors and styles. -pub fn str_len(s: &str) -> u16 { - let mut count = 0; - let mut counting = true; - let mut iter = s.chars().peekable(); - - loop { - let current = match iter.next() { - Some(c) => c, - None => break, - }; - - let next = iter.peek(); - - if current == '\x1b' && next == Some(&'[') { - counting = false; - } - - if counting { - count += 1; - } - - if current == 'm' { - counting = true; - } - } - - count -} - -/// Returns a substring of a string containing colors and styles. -pub fn sub_str<'a>(s: &'a str, start: u16, end: u16) -> &'a str { - let mut counting = true; - let mut iter = s.chars().peekable(); - - // Find the start - let mut real_start = 0; - let mut logical_start = 0; - loop { - if logical_start == start { - break; - } - - let current = match iter.next() { - Some(c) => c, - None => break, - }; - - let next = iter.peek(); - - if current == '\x1b' && next == Some(&'[') { - counting = false; - } - - real_start += 1; - if counting { - logical_start += 1; - } - - if current == 'm' { - counting = true; - } - } - - // Find the end - let mut real_end = real_start; - let mut logical_end = logical_start; - loop { - if logical_end == end { - break; - } - - let current = match iter.next() { - Some(c) => c, - None => break, - }; - - let next = iter.peek(); - - if current == '\x1b' && next == Some(&'[') { - counting = false; - } - - if counting { - logical_end += 1; - } - real_end += 1; - - if current == 'm' { - counting = true; - } - } - - &s[real_start..real_end] -} - /// Multiple applications running in a single terminal. struct Multiview { /// The stdout on which the multiview will be rendererd. diff --git a/src/tile.rs b/src/tile.rs index 69139db..9225402 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -10,7 +10,7 @@ use pty_process::blocking::Pty; use termion::{color, cursor, style}; -use crate::{rect, Msg}; +use crate::{utils, Msg}; /// A helper to build tiles. pub struct TileBuilder { @@ -325,7 +325,7 @@ impl Tile { let mut buffer = vec![]; - let max_title_len = self.inner_size.1 - "Command: ".len() as u16; + let max_title_len = self.inner_size.0 - "Command: ".len() as u16; let command_str = if command_str.len() > max_title_len as usize { format!( @@ -350,14 +350,18 @@ impl Tile { buffer.push(format!("{}", color::Green.fg_str())); } - buffer.push(rect((x, y), (x + w - 1, y + h - 1))); + buffer.push(utils::rect((x, y), (x + w - 1, y + h - 1))); buffer.push(format!("{}├", cursor::Goto(x, y + 2))); for _ in (x + 1)..(x + w) { buffer.push(format!("─")); } - buffer.push(format!("{}┤", cursor::Goto(x + w - 1, y + 2))); + buffer.push(format!( + "{}┤{}", + cursor::Goto(x + w - 1, y + 2), + style::Reset, + )); buffer.join("") } @@ -387,7 +391,7 @@ impl Tile { let old_current_char_index = current_char_index; current_char_index = 0; - if line_index >= scroll && line_index < h + scroll { + if line_index >= scroll && line_index <= h + scroll { if old_current_char_index < w { let mut spaces = String::new(); for _ in old_current_char_index..w { @@ -408,11 +412,11 @@ impl Tile { current_char_index += 1; } - if current_char_index == w { + if current_char_index == w + 1 { line_index += 1; current_char_index = 1; - if line_index >= scroll && line_index < h + scroll { + if line_index >= scroll && line_index <= h + scroll { buffer.push(format!( "{}", cursor::Goto(x, y + line_index as u16 - scroll) @@ -420,7 +424,7 @@ impl Tile { } } - if line_index >= scroll && line_index < h + scroll { + if line_index >= scroll && line_index <= h + scroll { buffer.push(format!("{}", c)); } } @@ -431,14 +435,6 @@ impl Tile { } } - if current_char_index == 0 { - let mut spaces = format!("{}", cursor::Goto(x, y + h)); - for _ in 0..w { - spaces.push(' '); - } - buffer.push(spaces); - } - buffer.push(format!("{}", style::Reset)); buffer.join("") } diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..5815a77 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,127 @@ +//! Some helper functions. + +use termion::cursor; + +/// Draws a box from (x1, y1) to (x2, y2). +pub fn rect((x1, y1): (u16, u16), (x2, y2): (u16, u16)) -> String { + let mut buffer = vec![]; + + buffer.push(format!("{}┌", cursor::Goto(x1, y1))); + + for _ in (x1 + 1)..x2 { + buffer.push(format!("─")); + } + + buffer.push(format!("┐")); + + for y in (y1 + 1)..y2 { + buffer.push(format!("{}│", cursor::Goto(x1, y))); + buffer.push(format!("{}│", cursor::Goto(x2, y))); + } + + buffer.push(format!("{}└", cursor::Goto(x1, y2))); + + for _ in (x1 + 1)..x2 { + buffer.push(format!("─")); + } + + buffer.push(format!("┘")); + + buffer.join("") +} + +/// Returns the length of a string containing colors and styles. +pub fn str_len(s: &str) -> u16 { + let mut count = 0; + let mut counting = true; + let mut iter = s.chars().peekable(); + + loop { + let current = match iter.next() { + Some(c) => c, + None => break, + }; + + let next = iter.peek(); + + if current == '\x1b' && next == Some(&'[') { + counting = false; + } + + if counting { + count += 1; + } + + if current == 'm' { + counting = true; + } + } + + count +} + +/// Returns a substring of a string containing colors and styles. +pub fn sub_str<'a>(s: &'a str, start: u16, end: u16) -> &'a str { + let mut counting = true; + let mut iter = s.chars().peekable(); + + // Find the start + let mut real_start = 0; + let mut logical_start = 0; + loop { + if logical_start == start { + break; + } + + let current = match iter.next() { + Some(c) => c, + None => break, + }; + + let next = iter.peek(); + + if current == '\x1b' && next == Some(&'[') { + counting = false; + } + + real_start += 1; + if counting { + logical_start += 1; + } + + if current == 'm' { + counting = true; + } + } + + // Find the end + let mut real_end = real_start; + let mut logical_end = logical_start; + loop { + if logical_end == end { + break; + } + + let current = match iter.next() { + Some(c) => c, + None => break, + }; + + let next = iter.peek(); + + if current == '\x1b' && next == Some(&'[') { + counting = false; + } + + if counting { + logical_end += 1; + } + real_end += 1; + + if current == 'm' { + counting = true; + } + } + + &s[real_start..real_end] +}