mirror of
https://github.com/youwen5/iamb.git
synced 2025-06-20 05:39:52 -07:00
Support sending and displaying formatted messages (#10)
This commit is contained in:
parent
8966644f6e
commit
4f2261e66f
11 changed files with 1770 additions and 233 deletions
157
src/message/printer.rs
Normal file
157
src/message/printer.rs
Normal file
|
@ -0,0 +1,157 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use modalkit::tui::layout::Alignment;
|
||||
use modalkit::tui::style::Style;
|
||||
use modalkit::tui::text::{Span, Spans, Text};
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
use crate::util::{space_span, take_width};
|
||||
|
||||
pub struct TextPrinter<'a> {
|
||||
text: Text<'a>,
|
||||
width: usize,
|
||||
base_style: Style,
|
||||
hide_reply: bool,
|
||||
|
||||
alignment: Alignment,
|
||||
curr_spans: Vec<Span<'a>>,
|
||||
curr_width: usize,
|
||||
}
|
||||
|
||||
impl<'a> TextPrinter<'a> {
|
||||
pub fn new(width: usize, base_style: Style, hide_reply: bool) -> Self {
|
||||
TextPrinter {
|
||||
text: Text::default(),
|
||||
width,
|
||||
base_style,
|
||||
hide_reply,
|
||||
|
||||
alignment: Alignment::Left,
|
||||
curr_spans: vec![],
|
||||
curr_width: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn align(mut self, alignment: Alignment) -> Self {
|
||||
self.alignment = alignment;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn hide_reply(&self) -> bool {
|
||||
self.hide_reply
|
||||
}
|
||||
|
||||
pub fn width(&self) -> usize {
|
||||
self.width
|
||||
}
|
||||
|
||||
pub fn sub(&self, indent: usize) -> Self {
|
||||
TextPrinter {
|
||||
text: Text::default(),
|
||||
width: self.width.saturating_sub(indent),
|
||||
base_style: self.base_style,
|
||||
hide_reply: self.hide_reply,
|
||||
|
||||
alignment: self.alignment,
|
||||
curr_spans: vec![],
|
||||
curr_width: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn remaining(&self) -> usize {
|
||||
self.width - self.curr_width
|
||||
}
|
||||
|
||||
pub fn commit(&mut self) {
|
||||
if self.curr_width > 0 {
|
||||
self.push_break();
|
||||
}
|
||||
}
|
||||
|
||||
fn push(&mut self) {
|
||||
self.curr_width = 0;
|
||||
self.text.lines.push(Spans(std::mem::take(&mut self.curr_spans)));
|
||||
}
|
||||
|
||||
pub fn push_break(&mut self) {
|
||||
if self.curr_width == 0 && self.text.lines.is_empty() {
|
||||
// Disallow leading breaks.
|
||||
return;
|
||||
}
|
||||
|
||||
let remaining = self.remaining();
|
||||
|
||||
if remaining > 0 {
|
||||
match self.alignment {
|
||||
Alignment::Left => {
|
||||
let tspan = space_span(remaining, self.base_style);
|
||||
self.curr_spans.push(tspan);
|
||||
},
|
||||
Alignment::Center => {
|
||||
let trailing = remaining / 2;
|
||||
let leading = remaining - trailing;
|
||||
|
||||
let tspan = space_span(trailing, self.base_style);
|
||||
let lspan = space_span(leading, self.base_style);
|
||||
|
||||
self.curr_spans.push(tspan);
|
||||
self.curr_spans.insert(0, lspan);
|
||||
},
|
||||
Alignment::Right => {
|
||||
let lspan = space_span(remaining, self.base_style);
|
||||
self.curr_spans.insert(0, lspan);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
self.push();
|
||||
}
|
||||
|
||||
pub fn push_str<T>(&mut self, s: T, style: Style)
|
||||
where
|
||||
T: Into<Cow<'a, str>>,
|
||||
{
|
||||
let style = self.base_style.patch(style);
|
||||
let mut cow = s.into();
|
||||
|
||||
loop {
|
||||
let sw = UnicodeWidthStr::width(cow.as_ref());
|
||||
|
||||
if self.curr_width + sw <= self.width {
|
||||
// The text fits within the current line.
|
||||
self.curr_spans.push(Span::styled(cow, style));
|
||||
self.curr_width += sw;
|
||||
break;
|
||||
}
|
||||
|
||||
// Take a leading portion of the text that fits in the line.
|
||||
let ((s0, w), s1) = take_width(cow, self.remaining());
|
||||
cow = s1;
|
||||
|
||||
self.curr_spans.push(Span::styled(s0, style));
|
||||
self.curr_width += w;
|
||||
|
||||
self.commit();
|
||||
}
|
||||
|
||||
if self.curr_width == self.width {
|
||||
// If the last bit fills the full line, start a new one.
|
||||
self.push();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_line(&mut self, spans: Spans<'a>) {
|
||||
self.commit();
|
||||
self.text.lines.push(spans);
|
||||
}
|
||||
|
||||
pub fn push_text(&mut self, text: Text<'a>) {
|
||||
self.commit();
|
||||
self.text.lines.extend(text.lines);
|
||||
}
|
||||
|
||||
pub fn finish(mut self) -> Text<'a> {
|
||||
self.commit();
|
||||
self.text
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue