cli: Fix multiline `patch show` description output
This commit is contained in:
parent
6c1e2d0ddd
commit
577a232a68
|
|
@ -7,9 +7,8 @@ use radicle::cob::patch;
|
||||||
use radicle::git;
|
use radicle::git;
|
||||||
use radicle::storage::git::Repository;
|
use radicle::storage::git::Repository;
|
||||||
use radicle_term::{
|
use radicle_term::{
|
||||||
label,
|
|
||||||
table::{Table, TableOptions},
|
table::{Table, TableOptions},
|
||||||
Element, Paint, VStack,
|
textarea, Element, Paint, VStack,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::terminal as term;
|
use crate::terminal as term;
|
||||||
|
|
@ -71,7 +70,10 @@ pub fn run(
|
||||||
.border(Some(term::colors::FAINT))
|
.border(Some(term::colors::FAINT))
|
||||||
.child(attrs)
|
.child(attrs)
|
||||||
.children(if !description.is_empty() {
|
.children(if !description.is_empty() {
|
||||||
vec![term::Label::blank(), label(term::format::dim(description))]
|
vec![
|
||||||
|
term::Label::blank().boxed(),
|
||||||
|
textarea(term::format::dim(description)).boxed(),
|
||||||
|
]
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,20 @@ pub trait Element: fmt::Debug {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Element for Box<dyn Element + 'a> {
|
||||||
|
fn size(&self) -> Size {
|
||||||
|
self.deref().size()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(&self) -> Vec<Line> {
|
||||||
|
self.deref().render()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print(&self) {
|
||||||
|
self.deref().print()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Element> Element for &T {
|
impl<T: Element> Element for &T {
|
||||||
fn size(&self) -> Size {
|
fn size(&self) -> Size {
|
||||||
self.deref().size()
|
self.deref().size()
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,11 @@ impl Label {
|
||||||
pub fn space() -> Self {
|
pub fn space() -> Self {
|
||||||
Self(Paint::new(" ".to_owned()))
|
Self(Paint::new(" ".to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Box the label.
|
||||||
|
pub fn boxed(self) -> Box<dyn Element> {
|
||||||
|
Box::new(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Element for Label {
|
impl Element for Label {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ pub mod io;
|
||||||
pub mod label;
|
pub mod label;
|
||||||
pub mod spinner;
|
pub mod spinner;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
|
pub mod textarea;
|
||||||
pub mod vstack;
|
pub mod vstack;
|
||||||
|
|
||||||
pub use ansi::Color;
|
pub use ansi::Color;
|
||||||
|
|
@ -22,6 +23,7 @@ pub use io::*;
|
||||||
pub use label::{label, Label};
|
pub use label::{label, Label};
|
||||||
pub use spinner::{spinner, Spinner};
|
pub use spinner::{spinner, Spinner};
|
||||||
pub use table::Table;
|
pub use table::Table;
|
||||||
|
pub use textarea::{textarea, TextArea};
|
||||||
pub use vstack::{VStack, VStackOptions};
|
pub use vstack::{VStack, VStackOptions};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
|
use crate::{Element, Line, Paint, Size};
|
||||||
|
|
||||||
|
/// Text area.
|
||||||
|
///
|
||||||
|
/// A block of text that can contain multiple lines.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TextArea(Paint<String>);
|
||||||
|
|
||||||
|
impl TextArea {
|
||||||
|
/// Create a new text area.
|
||||||
|
pub fn new(content: impl Into<Paint<String>>) -> Self {
|
||||||
|
Self(content.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the lines of text in this text area.
|
||||||
|
pub fn lines(&self) -> impl Iterator<Item = &str> {
|
||||||
|
self.0.content().lines()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Box the text area.
|
||||||
|
pub fn boxed(self) -> Box<dyn Element> {
|
||||||
|
Box::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Element for TextArea {
|
||||||
|
fn size(&self) -> Size {
|
||||||
|
let cols = self.lines().map(|l| l.width()).max().unwrap_or(0);
|
||||||
|
let rows = self.lines().count();
|
||||||
|
|
||||||
|
Size::new(cols, rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(&self) -> Vec<Line> {
|
||||||
|
self.lines()
|
||||||
|
.map(|l| Line::new(Paint::new(l).with_style(self.0.style)))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new text area.
|
||||||
|
pub fn textarea(content: impl Into<Paint<String>>) -> TextArea {
|
||||||
|
TextArea::new(content)
|
||||||
|
}
|
||||||
|
|
@ -42,7 +42,10 @@ impl<'a> VStack<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add multiple elements to the stack.
|
/// Add multiple elements to the stack.
|
||||||
pub fn children<E: Element + 'a>(self, children: impl IntoIterator<Item = E>) -> Self {
|
pub fn children<I>(self, children: I) -> Self
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = Box<dyn Element>>,
|
||||||
|
{
|
||||||
let mut vstack = self;
|
let mut vstack = self;
|
||||||
|
|
||||||
for child in children.into_iter() {
|
for child in children.into_iter() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue