Working on text wrap
This commit is contained in:
parent
4295c93435
commit
510914c083
159
src/lib.rs
159
src/lib.rs
|
@ -10,6 +10,123 @@ use termion::screen::IntoAlternateScreen;
|
||||||
use termion::terminal_size;
|
use termion::terminal_size;
|
||||||
use termion::{clear, color, cursor, style};
|
use termion::{clear, color, cursor, style};
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eprintln!("{} {}", real_start, real_end);
|
||||||
|
&s[real_start..real_end]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use termion::color;
|
||||||
|
|
||||||
|
use crate::str_len;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_str_len_1() {
|
||||||
|
let string = format!(
|
||||||
|
"{}Hello{} {}World{}",
|
||||||
|
color::Red.fg_str(),
|
||||||
|
color::Reset.fg_str(),
|
||||||
|
color::Green.fg_str(),
|
||||||
|
color::Reset.fg_str(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(str_len(&string), 11);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A tile with a command running inside it.
|
/// A tile with a command running inside it.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Tile {
|
pub struct Tile {
|
||||||
|
@ -203,9 +320,16 @@ impl<W: Write> Multiview<W> {
|
||||||
.stdout
|
.stdout
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.to_string())
|
.map(|x| x.to_string())
|
||||||
.enumerate()
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let max_title_len = term_size.0 - 4 - "Command: ".len() as u16;
|
||||||
|
|
||||||
|
let command_str = if str_len(&command_str) > max_title_len {
|
||||||
|
format!("{}...", sub_str(&command_str, 0, max_title_len - 3))
|
||||||
|
} else {
|
||||||
|
command_str
|
||||||
|
};
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
self.stdout,
|
self.stdout,
|
||||||
"{}{} {}Command: {}{}",
|
"{}{} {}Command: {}{}",
|
||||||
|
@ -216,13 +340,32 @@ impl<W: Write> Multiview<W> {
|
||||||
style::Reset,
|
style::Reset,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
for (line_index, line) in lines {
|
let mut line_index = 0;
|
||||||
write!(
|
for line in lines {
|
||||||
self.stdout,
|
let mut len = str_len(&line) as i32;
|
||||||
"{}{}",
|
let mut current_char_index = 0;
|
||||||
cursor::Goto(x1 + 2, y1 + 3 + line_index as u16),
|
|
||||||
line
|
if len == 0 {
|
||||||
)?;
|
line_index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while len > 0 {
|
||||||
|
write!(
|
||||||
|
self.stdout,
|
||||||
|
"{}{}",
|
||||||
|
cursor::Goto(x1 + 2, y1 + 3 + line_index as u16),
|
||||||
|
sub_str(
|
||||||
|
&line,
|
||||||
|
current_char_index,
|
||||||
|
current_char_index + term_size.0 - 4
|
||||||
|
),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
line_index += 1;
|
||||||
|
len -= (term_size.0 - 4) as i32;
|
||||||
|
current_char_index += term_size.0 - 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in New Issue