Skip to content

Commit

Permalink
Import plenty of utilities from prodash into tui-react
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Mar 29, 2020
1 parent 1f1c0ce commit 584cc98
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 7 deletions.
12 changes: 7 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion tui-react/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tui-react"
version = "0.2.1"
version = "0.2.2"
authors = ["Sebastian Thiel <sthiel@thoughtworks.com>"]
edition = "2018"
repository = "https://github.com/Byron/dua-cli"
Expand All @@ -11,3 +11,5 @@ license = "MIT"
[dependencies]
tui = "0.8.0"
log = "0.4.6"
unicode-segmentation = "1.6.0"
unicode-width = "0.1.7"
129 changes: 128 additions & 1 deletion tui-react/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ pub use list::*;
pub use terminal::*;

use std::iter::repeat;
use tui::{self, buffer::Buffer, layout::Rect, style::Color};
use tui::{self, buffer::Buffer, layout::Rect, style::Color, style::Style};
use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr;

pub fn fill_background_to_right(mut s: String, entire_width: u16) -> String {
match (s.len(), entire_width as usize) {
Expand All @@ -27,3 +29,128 @@ pub fn fill_background(area: Rect, buf: &mut Buffer, color: Color) {
}
}
}

pub fn draw_text_with_ellipsis_nowrap<'a>(
bound: Rect,
buf: &mut Buffer,
text: impl AsRef<str>,
style: impl Into<Option<Style>>,
) -> u16 {
let s = style.into();
let t = text.as_ref();
let mut graphemes = t.graphemes(true);
let mut total_width = 0;
{
let mut ellipsis_candidate_x = None;
let mut x_offset = 0;
for (g, mut x) in graphemes.by_ref().zip(bound.left()..bound.right()) {
let width = g.width();
total_width += width;

x += x_offset;
let cell = buf.get_mut(x, bound.y);
if x + 1 == bound.right() {
ellipsis_candidate_x = Some(x);
}
cell.symbol = g.into();
if let Some(s) = s {
cell.style = s;
}

x_offset += width.saturating_sub(1) as u16;
if x + x_offset >= bound.right() {
break;
}
let x = x as usize;
for x in x + 1..x + width {
let i = buf.index_of(x as u16, bound.y);
buf.content[i].reset();
}
}
if let (Some(_), Some(x)) = (graphemes.next(), ellipsis_candidate_x) {
buf.get_mut(x, bound.y).symbol = "…".into();
}
}
total_width as u16
}

pub fn draw_text_nowrap_fn(
bound: Rect,
buf: &mut Buffer,
t: impl AsRef<str>,
mut s: impl FnMut(&str, u16, u16) -> Style,
) {
if bound.width == 0 {
return;
}
for (g, x) in t.as_ref().graphemes(true).zip(bound.left()..bound.right()) {
let cell = buf.get_mut(x, bound.y);
cell.symbol = g.into();
cell.style = s(&cell.symbol, x, bound.y);
}
}

pub mod util {
use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr;

pub fn sanitize_offset(offset: u16, num_items: usize, num_displayable_lines: u16) -> u16 {
offset.min((num_items.saturating_sub(num_displayable_lines as usize)) as u16)
}

#[derive(Default)]
pub struct GraphemeCountWriter(pub usize);

impl std::io::Write for GraphemeCountWriter {
fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
self.0 += String::from_utf8_lossy(buf).graphemes(true).count();
Ok(buf.len())
}

fn flush(&mut self) -> Result<(), std::io::Error> {
Ok(())
}
}

pub fn block_width(s: &str) -> u16 {
s.graphemes(true).map(|g| g.width()).sum::<usize>() as u16
}

pub mod rect {
use tui::layout::Rect;

/// A safe version of Rect::intersection that doesn't suffer from underflows
pub fn intersect(lhs: Rect, rhs: Rect) -> Rect {
let x1 = lhs.x.max(rhs.x);
let y1 = lhs.y.max(rhs.y);
let x2 = lhs.right().min(rhs.right());
let y2 = lhs.bottom().min(rhs.bottom());
Rect {
x: x1,
y: y1,
width: x2.saturating_sub(x1),
height: y2.saturating_sub(y1),
}
}

pub fn offset_x(r: Rect, offset: u16) -> Rect {
Rect {
x: r.x + offset,
width: r.width.saturating_sub(offset),
..r
}
}

pub fn snap_to_right(bound: Rect, new_width: u16) -> Rect {
offset_x(bound, bound.width.saturating_sub(new_width))
}

pub fn line_bound(bound: Rect, line: usize) -> Rect {
Rect {
y: bound.y + line as u16,
height: 1,
..bound
}
}
}
}

0 comments on commit 584cc98

Please sign in to comment.