Giter Club home page Giter Club logo

tui-rs's People

Contributors

abusch avatar cjbassi avatar clementtsang avatar deepu105 avatar defiori avatar dflemstr avatar eminence avatar fdehau avatar imsnif avatar jeffa5 avatar jonboylecoding avatar josephfknight avatar karolinepauls avatar kemyt avatar lithdew avatar man0lis avatar meteor-lsw avatar nebkor avatar orf avatar orhun avatar scvalex avatar sectore avatar stevensonmt avatar svenstaro avatar tarkah avatar thelostlambda avatar timonpost avatar vchekan avatar wose avatar z2oh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tui-rs's Issues

Missing last character when wrapping text

I noticed in the demo application the footer section does not show the last character of the line before being wrapped. I tried adding a margin, but didn't fix it.

How do we control the cursor display?

I don't see anything in the docs about how to control the cursor. I'd be happy to submit documentation PR, except I have no clue how to control the cursor.

Is mouse event supported?

I've noticed that there is no example that uses mouse to interact with the widgets? Is this possible on this library?

Allow Lists to wrap

I would like to present stuff in a list but I'd also like stuff in it to be able to wrap long strings.

Intersted in crossterm implementation?

Hi, I am the writer of Crossterm cross-platform terminal manipulation library. In a short time, I will launch a new version of my crate which has than support for user input. It will then have all the features that termion has but then crossplatform.

Interested? is there a place where I could contact you like discord or so?

Regarding cursor state when text input

AFAIK, currently there's no way to modify cursor state.. So if I want a text input, like a line editing, I'd like the user to see the cursor, so they know where they are editing. But I don't see anything like editing cursor position when editing. There are only "show" and "hide" cursor. So, how can this be achieved?

Type hell

Maybe I'm just too new to rust; but it sure is damn hard with the beta of the library to break a drawing step into a separate function. Compiler puke everywhere trying to figure out the damn types. Like to pass a terminal to a function it has to be t: &mut Terminal<TermionBackend<RawTerminal<io::Stdout>>>. And I can't figure out what the return value should be on a t.draw(some closure)?; call...

Question: Best way to draw a Buffer directly?

I'm making a TUI game, and I'm having trouble figuring out the best way to place a single character into a Rect. I see the Buffer methods and doing it that low-level is just fine, the question is how do I then render the Buffer? Do I have to make a custom widget for that?

TUI does not render properly

I tried running the demo, however, the resulting render seems off. Most notably the bar charts. I've tried using terminal and iterm. Any idea what the issue is?

I'm using Rust 1.26.0

screen shot 2018-05-24 at 17 14 13

TUI never enters raw mode.

I'm using MacOS and on any terminal I've tried, none of the examples enter raw mode. I can still scroll around freely, my screen never locks, etc. Is this a bug??

Rustbox backend example also does not enter raw mode.

can a list be rendered bottom first?

I see the style modifier Invert but when I have a list area that can have say 10 items in it but I only have 4 items they still appear at the top and not at the bottom of the area? I'm trying to make two lists that give the data points on say a bell curve and the lists converge on the center point. If that doesn't make sense let me know and I'll try to draw something.

Text Input Widget

Just found your library and it looks awesome!

I'm aware that you wrote "the library does not provide any input handling nor any event system", but is there any example of a text input widget?

I'm trying to write a very simple chat application, so I'd just need a text input at the bottom and a scrolling text view at the top.

SelectableList with no item selected

Two things:

  1. It seems like a SelectableList will always show its highlight_symbol next to one of its items even if none of the items are selected, whereas the highlight_style is only applied when an item is actually selected.

  2. I (a total Rust newbie) can't work out a good way to conditionally select an item in a SelectableList... I think if SelectableList.select took an Option<usize>, everything would all just work, but since it takes just a usize, I have to only call .select if some condition is true, which means I have to do something ugly like this:

    let mut w = tui::widgets::SelectableList::default();
    let w = w.block(Block::default().borders(Borders::ALL))
        .items(&["one", "two", "three"])
        .highlight_style(tui::style::Style::default().fg(tui::style::Color::Cyan));
    if let Some(n) = app.selected {
        w.select(n)
    } else {
        w
    }.render(t, &chunks[0]);

    Is there (or could there be added) a better way to deal with conditional selection?

Rust newb trying to use library

Hi I'm learning rust and I was wondering if you could help me with an issue I ran into when using this library. (great library btw)

Example code:

extern crate tui;

use tui::widgets::Block;
use tui::widgets::Chart;

const TITLE: &str = " CPU Usage ";

pub struct CPU {
    pub chart: Chart<'static, String, String>,
}

impl CPU {
    pub fn new() -> CPU {
        let chart = Chart::default();
        chart.block(Block::default().title(TITLE));
        CPU {
            chart,
        }
    }
}

I'm getting an issue due to the chart.block(Block::default().title(TITLE)); line. The error says

error[E0597]: `chart` does not live long enough
  --> src/widgets/cpu.rs:15:9
   |
15 |         chart.block(Block::default().title(TITLE));
   |         ^^^^^ borrowed value does not live long enough
...
19 |     }
   |     - borrowed value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...

but aren't I moving the chart value into the CPU struct which is being returned? I'm confused why the borrowed value doesn't live longer. Sorry to bother you with a newb question, but I would appreciate any help. Thanks!

Enable use of Termion's AlternateScreen

Hi there,

I was wondering if I could use Termion's AlternateScreen with tui-rs and I found myself adding the following to your code:

pub type AlternateScreenBackend =
    TermionBackend<termion::screen::AlternateScreen<termion::raw::RawTerminal<io::Stdout>>>;

impl AlternateScreenBackend {
    pub fn new() -> Result<AlternateScreenBackend, io::Error> {
        let raw = io::stdout().into_raw_mode()?;
        let screen = termion::screen::AlternateScreen::from(raw);
        Ok(TermionBackend { stdout: screen })
    }
}

It worked just as I expected! But then, I faced another problem: I couldn't use print! or even write to stdout, I needed to write to backend.stdout, but that would require some changes in the lib's API, since it's a private attribute.

Exposing it doesn't seem like a good solution for me. We could implement std::io::Write for Terminal and just call self.backend.stdout.write internally.

What do you think about that? Is the change pertinent? Do you have another solution? I'm still in the "fighting the borrow-checker" phase, but I would love to help with that or any other feature.

Also, thanks for the great lib! :)

Scrollbars

How about Scrollbars for Tables and similiar widgets or a related solution?

How to scroll Paragraph when appending to the end?

I have a long multi-line string that I continuously append onto and I'd like Paragraph to append to the end. I'd then like Paragraph to scroll down so that no lines get hidden from the newly appended text. However, I can't know how much to scroll because Paragraph doesn't yield any information about its layouted text.

Paragraph with `.wrap(false)` can panic when fed long lines

Minimal repro with 0.3.0-beta.3 (not a new one - I initially observed it with 0.2.3) and with termion 1.5.1: https://gitlab.com/karolinepauls/tui-repro/blob/master/src/main.rs

First the line gets drawn over the border, then when it reaches the screen boundary, it panics. I would expect .wrap(false) to truncate the excess rather than print it.

Panic (cleaned up, the lines end up printed garbled over the TUI, with broken newlines due to the raw terminal mode):

thread 'main' panicked at 'Trying to access position outside the buffer: x=239, y=3, area=Rect { x: 0, y: 0, width: 239, height: 70 }', /home/k/.cargo/registry/src/github.com-1ecc6299db9ec823/tui-0.3.0-beta.3/src/buffer.rs:182:9
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
1: std::sys_common::backtrace::print at libstd/sys_common/backtrace.rs:71 at libstd/sys_common/backtrace.rs:59
2: std::panicking::default_hook::{{closure}} at libstd/panicking.rs:211
3: std::panicking::default_hook at libstd/panicking.rs:227
4: std::panicking::rust_panic_with_hook at libstd/panicking.rs:475
5: std::panicking::continue_panic_fmt at libstd/panicking.rs:390
6: std::panicking::begin_panic_fmt at libstd/panicking.rs:345
7: tui::buffer::Buffer::index_of at /home/k/.cargo/registry/src/github.com-1ecc6299db9ec823/tui-0.3.0-beta.3/src/buffer.rs:182
8: tui::buffer::Buffer::get_mut at /home/k/.cargo/registry/src/github.com-1ecc6299db9ec823/tui-0.3.0-beta.3/src/buffer.rs:149
9: <tui::widgets::paragraph::Paragraph<'a, 't, T> as tui::widgets::Widget>::draw
at /home/k/.cargo/registry/src/github.com-1ecc6299db9ec823/tui-0.3.0-beta.3/src/widgets/paragraph.rs:197
10: <tui::terminal::Frame<'a, B>>::render at /home/k/.cargo/registry/src/github.com-1ecc6299db9ec823/tui-0.3.0-beta.3/src/terminal.rs:40
11: tui::widgets::Widget::render at /home/k/.cargo/registry/src/github.com-1ecc6299db9ec823/tui-0.3.0-beta.3/src/widgets/mod.rs: 82
12: tui_repro::main::{{closure}} at src/main.rs:31
13: <tui::terminal::Terminal<B>>::draw at /home/k/.cargo/registry/src/github.com-1ecc6299db9ec823/tui-0.3.0-beta.3/src/terminal.rs:126
14: tui_repro::main at src/main.rs:25
15: std::rt::lang_start::{{closure}} at /checkout/src/libstd/rt.rs:74
16: std::panicking::try::do_call at libstd/rt.rs:59 at libstd/panicking.rs:310
17: __rust_maybe_catch_panic at libpanic_unwind/lib.rs:105
18: std::rt::lang_start_internal at libstd/panicking.rs:289 at libstd/panic.rs:392 at libstd/rt.rs:58
19: std::rt::lang_start at /checkout/src/libstd/rt.rs:74
20: main
21: __libc_start_main
22: _start

Large resoluton issues (u16 integer overflow and rendering artefacts)

I started playing around resizing the terminal and looking what happens. For now I've only fixed a couple of panics with higher resolutions: karolinepauls@bd33c04

However, I could still see some rendering artefacts and I'm investigating some right now. Artefacts appear when the number of characters exceeds 2^16 (resolution over 256x256). 2^16 characters is quite a lot but e.g. tmux continues working fine.

$ git grep ' as u16' shows the lib generally assumes u16.

I haven't fixed the gauge demo is panicking so far because here the root of the problem is using integer percentages instead of floating points:

let width = (gauge_area.width * self.percent) / 100;

Limiting fractional sizes to 0-100 also likely makes scaling choppy.

One way would be to (A) hardcode max resolution to be X:Y where X * Y < 2^16. Another (B) - promote u16 dimensions to u32 (and limit the resolution to 2^32 in case someone's that crazy).

(C) Regarding percentages, I would rather see them as [0, 1] floating points, which would make slicing more precise (3 panes with a ratio of 0.33333333333... will leave a smaller gap than 3 panes with percentage being 33).

I'm looking for some input on that.

Branch confusion

Today I was trying to use tui and so I went to try and walk through the examples. To my surprise I couldn't get them to work because MouseBackend didn't seem to be a thing. After some investigation I figured this was due to the fact that master was tracking development, and I had to go to the last release tag (0.1.3) to find the compatible examples.

It might be more reasonable to create a devel branch, and only merge changes to master when the update is released. This way anyone coming to the GitHub repository immediately finds the correct source and examples.

Latest version is not published to crates.io

It seems like the latest version of tui is not published to crates.io, making it awkward to depend on for published crates. (Perhaps the same is true for the termion crate?).

Would you consider publishing a new version? Thanks!

Auto resizing causes a race condition

The auto-resizing implemented in #94 unfortunately makes it impossible to ensure that you're using the right size in your layout calculation.

Previously you'd use something like:

let new_size = terminal.size()?;
if size != new_size {
    size = new_size;
    terminal.resize(size)?;
}

terminal.draw(|mut f| { /* ... */ });

which ensures that the size variable later used to calculate the layout is the same size that is used for the buffer inside the terminal instance.

But now you have to do:

let size = terminal.size();
/* RACE WINDOW HERE */
terminal.draw(|mut f| { /* ... */ });
})

You have to ask for the size of the terminal first, and then, inside the draw() method, the size might change because of the automatic resizing. If the terminal is actually resized in between these two actions, the sizes get out of sync, and there's no way for the programmer to avoid the resulting artifacts or crash.

One way to handle this would be to adjust the callback in draw() to accept the current terminal size as a second parameter like this:

terminal.draw(|mut f, size| { /* ... */ });

That would ensure that the size matches the buffer size. If that sounds good to you, I could prepare a PR for that.

Colors doesn't work very well

If we use termion::color at a Text inside of a widget, we will get a strange behaviour. For example:

format!(
    " 0x00: {color_green}green{reset} foo {color_blue}blue{reset}",
    color_green = COLOR_GREEN!(),
    color_blue = COLOR_BLUE!(),
    reset = color::Fg(color::Reset),
)

We expected a result like 0x00: green foo blue, but we get it:

image

A workaround that I use (and works sometimes) is using cursor::Left, for example:

format!(
    " 0x00: {color_green}green{reset} {goto}foo {color_blue}{goto_blue}blue{reset}",
    color_green = COLOR_GREEN!(),
    color_blue = COLOR_BLUE!(),
    goto = cursor::Left(14),
    goto_blue = cursor::Left(19),
    reset = color::Fg(color::Reset),
)

it will print:

image

But, this workaround isn't work in all situations, for example, if this text change.

Full example code:

extern crate termion;
extern crate tui;
use std::io::{stdout, stdin};
use tui::Terminal;
use tui::backend::TermionBackend;
use tui::layout::{Layout, Constraint, Direction};
use termion::clear;
use termion::event::Key;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
use tui::backend::Backend;
use tui::widgets::{Widget, Block, Borders, Text, List};
use tui::layout::Rect;
use tui::Frame;
use termion::{color, cursor};

macro_rules! COLOR_GREEN { () => { color::Fg(color::Green) } }
macro_rules! COLOR_BLUE { () => { color::Fg(color::LightBlue) } }

fn format_line(i: usize, text: &str) -> String {
    format!(
        " {:#04X}: {color_green}green{reset} {} {color_blue}blue{reset}",
        i, text,
        color_green = COLOR_GREEN!(),
        color_blue = COLOR_BLUE!(),
        reset = color::Fg(color::Reset),
    )
}

fn draw_list<B>(f: &mut Frame<B>, area: Rect)
where
    B: Backend,
{
    let raw_text = ["foo", "bar"];
    let formatted_text = raw_text
        .iter()
        .enumerate()
        .map(|(i, text)|
            Text::raw(
                format_line(i, text)
            )
        );

    List::new(formatted_text)
      .block(Block::default().borders(Borders::ALL).title(" Table "))
      .render(f, area);
}

fn main() -> Result<(), Box<std::error::Error>> {
    let stdout_raw_mode = stdout().into_raw_mode()?;
    let backend = TermionBackend::new(stdout_raw_mode);
    let mut terminal = Terminal::new(backend)?;

    let size = terminal.size()?;

    println!("{}", clear::All);

    'main: loop {
        terminal.draw(|mut f| {
            let chunks = Layout::default()
                .direction(Direction::Horizontal)
                .constraints([Constraint::Percentage(100)].as_ref())
                .split(size);

            draw_list(&mut f, chunks[0]);
        })?;

        for c in stdin().keys() {
            match c? {
                Key::Char('q') => break 'main Ok(()),
                _ => {}
            }
        }
    }
}

inconsistent Builder pattern

Some types in this library (e.g. Style, Block) use mut self in builder methods while others (e.g. SelectableList) go with &'a mut self. The latter style considered harmful, and I hate it a lot. This is what i had to make up to make things work for optional selection in a list view:

pub trait OptionalSelection<'a> {
    fn select_optional(&'a mut self, index: Option<usize>) -> &'a mut Self;
}

impl<'a> OptionalSelection<'a> for SelectableList<'a> {
    fn select_optional(&'a mut self, index: Option<usize>) -> &'a mut SelectableList<'a> {
        match index {
            Some(index) => self.select(index),
            None => self,
        }
    }
}

Of course it's more about the lack of such method in the library (which only has select(&'a mut self, usize)) than about the builder pattern and lifetimed references. But with a method that takes ownership and returns ownership, it's damn simple to store intermediate value somewhere and perform some conditional calls later. Try that with -> &'a mut Self, I dare you!

Should I open a pull request about it? Could it be a breaking change? Is it acceptable?

Ctrl-C

catching sigint is a bit strange UX. (good old quit vim jokes anyone?)
that might be an unintentional side effect of terminal raw mode,
so i it would be ok to add a keyhandler for ctrl+c i guess, but Event::Input lacks a modifier.

potential performance issue in List

So I'm following your examples and I notice in your main loop you create a new Group with new List's for each iteration. Looking at the code behind this at https://github.com/fdehau/tui-rs/blob/master/src/widgets/list.rs#L14 shows that List has a Vec inside of it. While all the items are references you'll still be allocating a Vec for the entire thing. Looking at how its then used is to iterate over the items so you could probably come up with a custom iterator type that could take in. Looking further at the List example, you collect() to a Vec and then pass the slice in since List.items() takes a slice. It then turns around an collect()'s to a Vec again so you're taking the allocation performance hit twice.

Another idea would be to take the style independently of the data, both as IntoIterator Then you could use Iterator.zip() to combine the two. You could alternatively create a type like

pub enum Item<'s> {
    Data(::std::fmt::Display), // allows any type that can be displayed to be used as input (so `String` and `&str` still work)
    StyledData(::std::fmt::Display, &'s ::tui::style::Style),
}

Then List.items() could have a signature like:

pub fn items<L: IntoIterator<Item=Item>(&'a mut self, items: L) -> &mut List<'a>

and you could just store the iterator inside of List instead collecting to a Vec. Then when draw() ran it would just work with that iterator.

Interoperability: Terminal Should Implement Debug

Currently terminal::Terminal does not implement Debug, which prohibit us from deriving Debug trait for the struct that contains terminal::Terminal.

#[derive(Debug) // Compile error: std::fmt::Debug is not implemented for Terminal
pub struct Render {
    terminal: Terminal
}

This hurts interoperability as stated by the offical API guidelines.

Feature request: Linechart

I think it would be nice if we had an option for the chart widget to draw lines between each marker. I saw you were able to have a linechart in examples/demo.rs but only when feeding in continuous data. Maybe add an option to the chart widget or create a new linechart struct to enable drawing a line between consecutive points. I could probably hack a pr together but I wasn't sure what the best way to implement it would be.

SelectableList does not pass style to underlying List

I'm trying to render a SelectableList with white background and black text, but the list does not get those colors.

Instead only the text of the list items have the correct color, but the rest of the list has default background color.

I think this is because the SelectableList creates a List and renders it, but it fails to pass on the style to it. The style is only attached to the items; and when List renders it calls Widget::background with the default style before rendering the items.

Add Europe Map

The world map is really cool, any chance you could extend this so I can select Europe instead of the whole world? blessed-contrib currently has a USA map, but no map for Europe.

Thank you!

Lock terminal scrolling

Is there a function which prevents one from scrolling outside the application? As it is still possible to use the terminal scrollbar to scroll up.
Or is this rather a question for the termion issues?

draw vs. render

Group layout is confusing. It has method render like an ordinary widget, but it lacks a counterpart method draw.

I tried to separate drawing logic from main App's single method and split it up into widgets, and call render on them. For widgets i have to implement the draw method โ€” the only one required by the trait. But no way! I can't, not without the reference to a terminal, which is needed for Group::render.

impl Widget for MainViewController {
    fn draw(&self, area: &Rect, buf: &mut Buffer) {
        Group::default()
            .direction(Direction::Vertical)
            .sizes(&[Size::Min(0), Size::Fixed(3)])
            .render( ??? );
    }
}

I can see Group::render accessing terminal's layout cache, but it doesn't make me feel any better. Any ideas?

I don't know how to use tui::widgets::Table effectively

The Table type is giving me some type-related difficulty when I try to use it in a practical application.

What I want to do is display a formatted (read: truncated and aligned) float as one of the columns in a table, e.g.

HEADER1  HEADER2      THING
-------  -------      -----
name     other-thing   1.99
name2    description  25.80

Sounds simple, right? Not so fast. Granted, I am relatively new to Rust, so I may be missing something.

Row::Data(x) expects x to be an Iterator<D>, where type D is Display. This means that every element must be the same type (no surprise) and that that type must implement Display (also no surprise). Okay, so that means I need to provide all of my row values as some sort of string type. Maybe like this?

let data_vec = vec![
        "name".to_string(),
        "other-thing".to_string(),
        format!("{:5.2}", 1.99)
    ];
let data_row = Row::Data(data_vec.into_iter());

Looks good so far. Now let's try to use it in a UI.

let size = term.size()?;
Group::default()
    .sizes(&[Size::Percent(100)])
    .render(term, &size, |t, c| {
        Table::new(
            vec!["HEADER1", "HEADER2", "THING"].into_iter(),
            vec![data_row].into_iter()
        ).block(Block::default())
            .render(t, &c[0]);
    });

Hold on, what?

error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
  --> src/main.rs:92:22
   |
85 |     let data_row = Row::Data(data_vec.into_iter());
   |         -------- captured outer variable
...
92 |                 vec![data_row].into_iter()
   |                      ^^^^^^^^ cannot move out of captured outer variable in an `FnMut` closure

I think that this is something ownership-related. Maybe we should use references. Let's change the first block to look like this:

let formatted_flt = format!("{:5.2}", 1.99);
let data_vec = vec![
        "name",
        "other-thing",
        &formatted_flt
    ];
let data_row = Row::Data(data_vec.into_iter());

Nope.

error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
  --> src/main.rs:94:22
   |
87 |     let data_row = Row::Data(data_vec.into_iter());
   |         -------- captured outer variable
...
94 |                 vec![data_row].into_iter()
   |                      ^^^^^^^^ cannot move out of captured outer variable in an `FnMut` closure

In the demos, this is avoided by using string literals as the ultimate source for the tabular data:

tui-rs/examples/table.rs

Lines 25 to 32 in ef2054a

items: vec![
vec!["Row12", "Row12", "Row13"],
vec!["Row21", "Row22", "Row23"],
vec!["Row31", "Row32", "Row33"],
vec!["Row41", "Row42", "Row43"],
vec!["Row51", "Row52", "Row53"],
vec!["Row61", "Row62", "Row63"],
],

Likewise in the docs:

/// vec![
/// Row::StyledData(["Row11", "Row12", "Row13"].into_iter(), &row_style),
/// Row::StyledData(["Row21", "Row22", "Row23"].into_iter(), &row_style),
/// Row::StyledData(["Row31", "Row32", "Row33"].into_iter(), &row_style),
/// Row::Data(["Row41", "Row42", "Row43"].into_iter())
/// ].into_iter()

I really hope that the problem here is my understanding of the Rust type system. If not, then this is not a useful implementation of a user-facing table (ususally, tables are used to display information that is created or discovered at runtime).

my M(non-)WE with a .txt extension for Github's file uploader

Wrong operator in Buffer::pos_of?

I might be misunderstanding this whole thing, but it looks like the wrong comparison operator is used in Buffer::pos_of.

tui-rs/src/buffer.rs

Lines 170 to 176 in c561734

pub fn pos_of(&self, i: usize) -> (u16, u16) {
debug_assert!(
i >= self.content.len(),
"Trying to get the coords of a cell outside the buffer: i={} len={}",
i,
self.content.len()
);

The index must be bigger than the buffer size instead of within the buffer size.

Given a buffer of 20*20 cells (length 400), I would expect 0 to be (0, 0), 20 to be (0, 1), and so on. Instead I must pass an index like 400 or 555.

Add Box shape

I think there should be a Box shape just like there is a Line shape.

Feedback on v0.3.0-beta.0

I tried to migrate one of my projects to the newly released v0.3.0-beta.0. For the most part things look good. The one thing that I had a problem with are the changes to Paragraph, which now takes of a Vec<Text>, and the fact that Text only takes borrowed strings. It made it really hard to do things like:

let mut text = vec![];
if some_condition {
    text.push(&format!("..."));
} else {
    text.push(&format!("..."));
}
Paragraph::new(text.iter())...

due to lifetime issues (strings returned by format!() don't live long enough). I think maybe Text should store a Cow<str> internally, so it could accept both borrowed and owned strings.

What do you think?

I might give it a shot on a branch an see how it goes...

Widget: TreeView

Im very interested to see a TreeView as another widget. Is it planned or in consideration?

Why can't we use a Vec<Text> or something for lists?

I'm getting all sorts of compiler puke when trying to use the List and SelectableList widgets. It's looking like the library requires me to use a fixed array to give to List or SelectableList. Why can't I use a vec? This makes it a PITA when dealing with dynamic UI lists.

provide wrapped Terminal type in render() closures

So when implementing a full app it looks like the best practice is to implement different draw() functions that encompass each group of widgets. You end up calling each draw() inside the render() closure, e.g.

draw_first_tab(t, app, &chunks[1]);

I ended up implementing my example app by implementing my first group and having the top level app loop call its draw(). Then I put that group within another group and made a new draw() calling the original like linked above. But the program immediately stopped working and didn't show anything. I was really confused for a but but then realized that my inner draw() still had a t.draw() call which caused the issue. There was no error or panic, the application just sat there with an empty screen. Looking at Terminal there are a few things that look like they shouldn't be called at this inner level so maybe it'd be better to provide a wrapped type or a trait that just doesn't implement all these additional methods so people can't get tripped up by them.

Line breaks not rendered properly in List and SelectableList

When using a List or SelectableList, if an item contain newlines, text after the newline will get overwritten by the next items.

For example:

SelectableList::default()
    .items(&["Hey\nYou",":O:O:O"])
    .render(&mut f, size);

Renders as:

Hey
:O:O:O

When it should be rendered as:

Hey
You
:O:O:O

Missing widgets from blessed-contrib

Hi @fdehau
Are you planning to add missing widgets from blessed-contrib like stacked-gauge donut etc.
It would also be nice to have some more shapes like triangles to draw on canvas widget.

Question/Feature Request: Why does `Text::raw` get rid of `\t` tabs?

I'm not getting the expected behavior of Text::raw used in a widget::Paragraph. It's not honoring \t in the text, however, it is honoring \n. Am I doing something wrong? Is there a reason this isn't working?

let x = format!("No indent\n");
let y = format!("\tThis should indent.");
let text = Text [Text::raw(&x), Text::raw(&y)];
Paragraph::new(text.iter())...

I expect the second line to be indented by a tab, but it's flush left with the first line start.

Feature request: Dynamic dispatch chain

from my point of view, the dynamic rendering is complemented well with a dynamically build dispatch chain. This approach I have used in tui-logger-widget and IMHO works quite well. Just I would prefer, that this is an integrated part in tui-rs instead of the widget.

Have you thought about using similar dynamically built dispatch chain ?

Improve scrolling behavior of selectable lists

The current scrolling behavior of selectable lists somewhat confusing. Currently, when you're at the bottom of the window and you select the previous entry, instead of just moving the selection up, the list scrolls up and the selected row is still at the bottom. I'd much rather have the list only scroll when I already hit the top or bottom of the currently visible rows.

Additionally, I'd love to have support for a scroll offset. That is, a set amount of rows that is kept above or below the selected row, i.e. the list starts scrolling X rows before you hit the top/bottom. One reason is that this allows you to see whether there are still more rows to come even without a scrollbar.

Random layout bug

Hi,

I've integrated a simple example from the doc which does nothing but display 2 blocks, and this example randomly displays overlapping boxes. Here's the code excerpt:

fn draw(t: &mut Terminal<RawBackend>) -> std::result::Result<(), std::io::Error> {                                                                             
    let size = t.size()?;
                                                                               
    Group::default()                                                           
        .direction(Direction::Vertical)                                        
        .margin(1)
        .sizes(&[Size::Fixed(10), Size::Max(20), Size::Min(10)])               
        .render(t, &size, |t, chunks| {                                        
            Block::default()
                .title("Block")                                                
                .borders(Borders::ALL)
                .render(t, &chunks[0]);
            Block::default()                                                   
                .title("Block 2")
                .borders(Borders::ALL)
                .render(t, &chunks[2]);                                        
        });

    t.draw()                                                                   
}

And here are the results - randomly one or the other (note that I always press ^L before running the example):
capture d ecran de 2018-02-22 13-45-49
capture d ecran de 2018-02-22 13-45-58

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.