ratatui-org / ratatui Goto Github PK
View Code? Open in Web Editor NEWRust library that's all about cooking up terminal user interfaces (TUIs) ๐จโ๐ณ๐
Home Page: https://ratatui.rs
License: MIT License
Rust library that's all about cooking up terminal user interfaces (TUIs) ๐จโ๐ณ๐
Home Page: https://ratatui.rs
License: MIT License
I was trying to migrate my project from tui to this fork and i had everything working but for some reason my project started complaining that crates are not resolved so i've added them but that make ratatui to trow errors about multiple implementation of Line/Text
. To reiterate it was working just few hours before and i don't think i did anything werid.
Honestly have no idea haw to reproduce this issue.
No conflicts in definiton of List/Text
Grapheme
, the term given to the subdivisions of a Span
by the original tui-rs
developer, is not the right word to describe what it actually contains. A grapheme is essentially the smallest component of a written language that has a certain phonetic sound. For instance, d
is a grapheme, but so is sh
. The term stops working when considering multi-symbol graphemes.
It should probably be renamed to Char
, or something similar, because although Unicode doesn't have chars exactly, it is at least clearer than Grapheme
. Symbol
may also work and is more accurate, but one of the fields is already called Symbol
and I'm not a huge fan of fields that have the same name as their enclosing struct. I'm open to other suggestions.
Sometimes one may want to adjust the outer block fluidly according to the inner components size, in which case inner_block.outer()
is useful.
Not sure if there's already a workaround.
Similar to Block::inner
, implement a Block::outer
function.
For example, a popup for user inputs.
The user input block is an inner block of the popup block. And users may want automatically adjust the outer block size according to the input length.
I'm not a user of helix or tui. But I found this helix issue and thought I'd mention it here:
helix-editor/helix#6012
Helix uses a fork of a subset of tui. Notably the core of Buffer is basically the same (AFAIK).
I'm pretty sure that this bug is shared by everything using the tui-style Buffer.
AFAIK, the reason is that unicode-width doesn't (or can't?) report the column width for emojis. See readme and issues:
https://github.com/unicode-rs/unicode-width
I won't have anything to contribute here, or any personal interest, really.
Perhaps you should get into contact with the helix team for this, as this effects both.
TL;DR; Is it correct that:
If I have a paragraph with a block around it then there are 4 combinations of setting styles for the text and box
para block
------- -------
default default
explicit default
default explicit
explicit explicit
by default I mean Style::default
by explicit i mean say Style::default().bg(Color::Red).fg(Color::Yellow)
I used
Style::default().bg(Color::Red).fg(Color::Yellow)
for the block in my tests (setting block.border_style)Style::default().bg(Color::Blue).fg(Color::Green)
for the paragraphIn a modified version of the paragraph sample app. (source below)
My expectation was a follows (for each combo listed above)
What I get is
I also ran the same code with block.style instead of block.border_style. Nothing in the docs explains the difference between them. So I wanted to see what happened
This seems to be suggesting that block.style is intended to set the overall style of the para/block combo (para inherits from block), whereas block.border_style only sets the stye of the block. Fine.
But note that in the second case of both screen shots the para style has overriden the default of the block. This is a surprise
Also note the odd fact that although the para is explicity set to blue on green in the last case (of the last screen shot) the style set in the block style 'wins' in the 'blank' space
are these 2 intended behaviors?
I also tried with styled text rather that styling the paragraph (para always set to Style::default
)
(There are only 2 combos now since the para style is always set to default but the text is set to white on blue)
Note the big difference for the second one. The style of the text is not propagated to the containing block.
and for completeness sake , style text with the block style set via block.border_style
here is the modified code of the paragraph sample
let size = f.size();
// Words made "loooong" to demonstrate line breaking.
let s = "Veeeeeeeeeeeeeeeery loooooooooooooooooong striiiiiiiiiiiiiiiiiiiiiiiiiing. ";
let mut long_line = s.repeat(usize::from(size.width) / s.len() + 4);
long_line.push('\n');
// let block = Block::default().style(Style::default()); //.bg(Color::White).fg(Color::Black));
// f.render_widget(block, size);
let chunks = Layout::default()
.direction(Direction::Vertical)
.margin(5)
.constraints(
[
Constraint::Percentage(25),
Constraint::Percentage(25),
Constraint::Percentage(25),
Constraint::Percentage(25),
]
.as_ref(),
)
.split(size);
let text = vec![Spans::from("This is a line ")];
let create_block = |title, dflt| {
Block::default()
.borders(Borders::ALL)
.title(Span::styled(
title,
Style::default().add_modifier(Modifier::BOLD),
))
.border_style(if dflt {
Style::default()
} else {
Style::default().bg(Color::Red).fg(Color::Yellow)
})
};
let paragraph = Paragraph::new(text.clone())
.style(Style::default())
.block(create_block("dflt dflt", true))
.alignment(Alignment::Left);
f.render_widget(paragraph, chunks[0]);
let paragraph = Paragraph::new(text.clone())
.style(Style::default().bg(Color::Blue).fg(Color::Green))
.block(create_block("para = Gr/Bl bl = dflt", true))
.alignment(Alignment::Left);
f.render_widget(paragraph, chunks[1]);
let paragraph = Paragraph::new(text.clone())
.style(Style::default())
.block(create_block("para = dflt, block = Y/red", false))
.alignment(Alignment::Left);
f.render_widget(paragraph, chunks[2]);
let paragraph = Paragraph::new(text.clone())
.style(Style::default().bg(Color::Blue).fg(Color::Green))
.block(create_block("Para = b/g block = y/red ", false))
.alignment(Alignment::Left);
f.render_widget(paragraph, chunks[3]);
}
Add a description of the systems where you are observing the issue. For example:
Why do I care about ths. Because I am writing a widget that greys out a paragraphs text temporarily. If I do that when the surrounding block is set to Style::default
then it gets greyed out too. And there is no way for me to inspect the block to look at its style (there is no get_style method)
The way that this crate handles text is flawed, in my opinion. There are two major pain points and one minor pain point that I have encountered when dealing with Text
, Spans
, and Span
.
Text
is an ambiguous term to describe "a collection of lines." Spans
is a bad name because it creates confusion between Spans
and Span
s. This is especially an issue in code comments, where markdown's inline code blocks are not supported.Spans
should not have an unnamed field. Spans.0
makes code unreadable in a way that is entirely unnecessary; the reason I suspect this has not been changed is because it is a breaking change. But I believe it to be a warranted one. It is my opinion that no crate should have publicly-exposed unnamed fields.Span
into a Spans
and placing it in a Text
is rather annoying. I call this a minor pain point because, although it makes manipulating text (especially existing text) rather unwieldy, it may have a good reason for being implemented the way it is. Feedback on this would be appreciated.Spans
needs to be renamed to Line
.Spans
/Line
needs a named field. If the previous suggestion is adopted, I would recommend Line.spans
.Text
to something else - though I'm not really aware of any specific name for a collection of lines.0.21.0
.I'm not sure what alternatives to this feature would be - feel free to let me know any ideas you have.
A long line in ListItem does not break into multipe lines
Add a possibilty to wrap ListItem text, same thing as Paragraph
Not that I know about
Currently only horizontal alignment is supported for Paragraph
s, which makes vertically positioning paragraphs very awkward.
Add some sort of vertical_align
method that takes in a VAlignment
type as an argument, and offset paragraph rendering vertically accordingly. The VAlignment
type should at the very least look like this:
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive] // if we want to add more alignment types in the future
pub enum VAlignment {
Top,
Center,
Bottom,
}
Users can manually currently allocate an appropriate amount of space for the paragraph with Layout
, but this is not very flexible as the user has to know the height beforehand. Using some sort of Flex API would also solve the problem, though it appears that that API is still very early in development. Finally we could avoid creating a new alignment type, but the horizontal variant names could potentially confuse the user.
We often see action check failures due to conventional commits, cargo clippy lints, and rust format.
There's a bunch of ways to have pre-commit git hooks that check rust format, clippy, and conventional commits. Evaluate the options and choose the appropriate one to implement. I'm not sure which one is the best / most used / idiomatic.
None
Installation of any required tooling should be low impact. Bonus points for borrowing the config of some reasonably stable project.
As far as I am aware, there is no built-in way to align a list to the center of the terminal window. The only way that I know of is to add spaces before a string within a ListItem
to be able to pad it towards the right side.
Given that there's an alignment method for Paragraph
, perhaps making this available across other widgets would be nice.
Method would be accessible to the List
widget:
Entire list:
let list = List::new(items)
.style(Style::default().fg(Color::White))
.highlight_style(Style::default().add_modifier(Modifier::ITALIC))
.alignment(Alignment::Center);
None that I know about.
The demo does not render correctly (after 1 frame it starts spamming the terminal with the layout code).
I'm using alacritty 0.12.1 (5fdfd47f), and running fish 3.6.1 inside tmux 3.3a on Arch Linux.
The demo fails like this with all backends, but some examples work e.g. list (albeit with some theming issues) :
Config details:
~/.config/alacritty/alacritty.yml
:
window:
decorations: none
scrolling:
history: 0
font:
normal:
family: "Noto Sans Mono"
size: 13.0
colors:
primary:
background: '0x151515'
foreground: '0xd0d0d0'
cursor:
text: '0x151515'
cursor: '0xd0d0d0'
normal:
black: '0x151515'
red: '0xac4142'
green: '0x90a959'
yellow: '0xf4bf75'
blue: '0x6a9fb5'
magenta: '0xaa759f'
cyan: '0x75b5aa'
white: '0xd0d0d0'
bright:
black: '0x505050'
red: '0xd28445'
green: '0x202020'
yellow: '0x303030'
blue: '0xb0b0b0'
magenta: '0xe0e0e0'
cyan: '0x8f5536'
white: '0xf5f5f5'
draw_bold_text_with_bright_colors: false
hints:
enabled:
- regex: "(ipfs:|ipns:|magnet:|mailto:|gemini:|gopher:|https:|http:
..|news:|file:|git:|ssh:|ftp:)\
[^\u0000-\u001F\u007F-\u009F<>\"\\s{-}\\^โจโฉ`]+"
command: chromium
post_processing: true
mouse:
enabled: true
mods: None
binding:
key: U
mods: Control|Shift
key_bindings:
- { key: V, mods: Alt, action: Paste }
- { key: C, mods: Alt, action: Copy }
- { key: V, mods: Control|Shift, action: ReceiveChar }
- { key: C, mods: Control|Shift, action: ReceiveChar }
~/.tmux.conf
:
# set scroll history to 100,000 lines
set-option -g history-limit 100000
# modern colors
set -g default-terminal "tmux-256color"
set -ga terminal-overrides ",alacritty:Tc"
# unbind the prefix and bind it to Ctrl-a like screen
# unbind C-b
# set -g prefix C-a
# bind C-a send-prefix
bind '"' split-window -c "#{pane_current_path}"
bind % split-window -h -c "#{pane_current_path}"
bind c new-window -c "#{pane_current_path}"
# copy to X clipboard
bind -T copy-mode-vi v send -X begin-selection
bind -T copy-mode-vi y send-keys -X copy-pipe 'xclip -in -selection clipboard &> /dev/null'
bind -T copy-mode-vi Enter send-keys -X cancel
# shortcut for moving tmux buffer to clipboard
# useful if you've selected with the mouse
bind-key -nr C-y run "tmux show-buffer | xclip -in -selection clipboard &> /dev/null"
# Avoid ESC delay
set -s escape-time 0
# Fix titlebar
set -g set-titles on
set -g set-titles-string "#T"
# VIM mode
set -g mode-keys vi
# Mouse friendly
set -g mouse on
# Move between panes with vi keys
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
set -g status-right ''
set -g status-right-length 0
source-file ~/.config/base16/tmux/base16-classic-dark.conf
~/.config/base16/tmux/base16-classic-dark.conf
:
set-option -g status-style "fg=#B0B0B0,bg=#202020"
set-window-option -g window-status-style "fg=#B0B0B0,bg=default"
set-window-option -g window-status-current-style "fg=#F4BF75,bg=default"
set-option -g pane-border-style "fg=#202020"
set-option -g pane-active-border-style "fg=#303030"
set-option -g message-style "fg=#D0D0D0,bg=#202020"
set-option -g display-panes-active-colour "#90A959"
set-option -g display-panes-colour "#F4BF75"
set-window-option -g clock-mode-colour "#90A959"
set-window-option -g mode-style "fg=#B0B0B0,bg=#303030"
set-window-option -g window-status-bell-style "fg=#202020,bg=#AC4142"
Above run with:
cargo run --example demo --release -- --tick-rate 200
from master with:
cargo 1.71.0-nightly (ac8401032 2023-05-02)
rustc 1.71.0-nightly (74c482104 2023-05-04)
The demo should render correctly.
The strange thing is that it works okay on my laptop with a similar setup (but more recent config), I haven't had time to compare them directly yet though.
In my projects I sometimes need a conversion like this:
"black" => TuiColor::Black,
"red" => TuiColor::Red,
"green" => TuiColor::Green,
Implement FromStr
for ratatui::style::Color
.
An example can be found here.
In the example, I used rgb
crate for converting HEX values to Color
as well. Since it introduces a new dependency, I'm not sure if we should do that as well.
None.
I also did something like this in the past: https://github.com/orhun/kmon/blob/66f27006fed614c048469b2511b600d07c8912d6/src/style.rs#L110-L152
We can possibly do a similar thing and split the applications into categories.
None.
None.
Clippy will be disabled in #51.
This issue is to re-enable clippy with linting fixes.
intersection panic at ratatui-0.21.0/src/layout.rs:464:43
version:
ratatui = "=0.21.0"
source code:
fn main() {
let test_backend = ratatui::backend::TestBackend::new(58596, 58596);
let _rect1 = if let Ok(x) = ratatui::backend::Backend::size(&(test_backend)) {
x
} else {
use std::process;
process::exit(0);
};
let _rect2 = ratatui::layout::Rect::new(58596, 58596, 58368, 0);
let _local16 = ratatui::layout::Rect::intersection(_rect1, _rect2);
}
thread 'main' panicked at 'attempt to add with overflow', /home/yxz/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/ratatui-0.21.0/src/layout.rs:464:43
The layout chunk size are static by default.
Having a new constraints that allow a chunk to grow and or shrink based on its content. The new constraints should allow to define the min and max size for the chunk. Additionally, it would be great to have an indicator that the size of the chunk content is larger than the size of the chunk itself and hence enable the scrolling automatically.
An alternative is to update the chunk constraints for each step of the loop.
Considering the quantity of apps using ratatui that are referenced in our readme, maybe we could move them to a table in a separate markdown file ?
This would make the main README leaner, while at the same time enabling us to maybe give the option for adding more details since it would now be a dedicated file.
There are a few widgets that need scrolling behavior. It would be wasteful to implement this on each widget rather than doing it properly once. There is existing scroll behavior in Table, Paragraph and List. There are a few issues / PRs related to scrolling currently in the queue
Paragraph
:
Paragraph::default().scroll((1,2))
)Table
:
{ selected, offset }
List
{ selected, offset }
Elsewhere:
tui_rs_tree_widget::Tree
tui-logger
tui-textarea
tui-input
I'm sure there are other things to look at. Please add them if you know of them.
Brainstorming ideas
TODO: refine these as must-have, should-have, could-have, won't have (MoSCoW)
render
method just fix the invalid scroll?list_state.scroll_down()
)ScrollState
type with all the scrolling behavior and include this in ListState, TableState etc.list_state.scroll_state.scroll_down()
And for scrollbar:
I am writing a project that makes use of tui::widgets::ListItem
to display commit-nodes of a git Repository. Currently, I am making use of tui::widgets::Text
to display this git graph:
tui::widgets::Text
displays a new line when \n
is found on the string. It is working fine. Relevant code is here and here
However, now I'd like to add color to the left side panel. I tried to use tui::widgets::Spans
to build the ListItem
. Here is the new code and here you have the screen shot
As you can see, if a line feed char is inside a Span
, ListItem
won't write the next chars into a new line. But if a line feed char is inside a Text
, ListItem
will write the next chars into a new line.
My first thought was to make the Span
widget react to a line feed char. But I think this is not the right solution, because a Span
is meant to span one line, not to introduce new lines.
I saw the original tui
code, and found out there is a Text#styled you can use and it -partially works for me-. Because yes, you can stylize a Text input and have line feeds inside and you will see a colored text and the line feeds in the ListItem
. However, I want to colorize a -segment- of a string, not the entire string. And currently, there is no feature to build a ListItem
from a Vec<Text>
. I think it would be easier to build a trait to implement ListItem
from a Paragraph
rather than build it from a Vec<Text>
I am working on git_explorer as a side project to better understand rust, and I have already done this rg_explorer side project to practice with rust. I found very interesting the rust language and want to master it. I am willing to work on this issue, but I probably need some help to understand this source code (or at least the relevant part of this source code to build this feature).
Best
Sometimes the layout options available in providing a List
with Text
are not quite enough.
Create widgets::WidgetList
which has WidgetListItems
as a parallel to the current List
widget. The algorithm for deciding what is rendered will be similar to the current list (effectively a viewport that contains the currently selected Text item, scrolled into view if necessary, and that only renders the items in the current view)
widgets::WidgetList
might be a slightly confusing nameText
(or even Span
s) should be migrated to accept a widget instead. Does it make sense to set the title of a block to a widget perhaps? What about the highlight character of a list? Should tables contain widgets instead of text? Pros: really flexible. Cons: really big change with some difficult backwards compatibility constraints.My particular use case for this is for https://github.com/joshka/tooters where I want to be able to do some neat things like show images using a widget wrapped around https://docs.rs/viuer/latest/viuer/ and make URLs clickable by wrapping them in OSC 8 escape sequences (as a UrlWidget, not just as text).
The Paragraph widget does not have a scroll bar.
Show the scroll bar for the Paragraph widget when the scroll
is defined.
I'm having a lot of difficulty trying to emulate a terminal through a Paragraph
widget in my shell project https://github.com/Eyesonjune18/rush. I think that it might make sense at some point to have a dedicated terminal widget that has built-in support for ANSI sequences etc.
PseudoTerminal
or Terminal
widget typeThe alternative to having a dedicated widget for this is to use a Paragraph
widget, but I've ran into quite a few problems doing so - especially in terms of the features mentioned above.
The word master
has been deprecated in favor of main
branch, but this repo defaults to master
branch.
Switch to main
branch.
Note: the prs should auto update to main branch, but might take some time to update.
There might be some time gaps between new releases so the users cannot test/use the latest functionality without using ratatui
as a git
dependency in Cargo.toml
which makes the crate unpublishable on crates.io. (crates.io doesn't accept git
dependencies)
See what atuin
did recently as a workaround: atuinsh/atuin@a515b06
Create automated nightly releases every week or so. ratatui
can be used as e.g. version = "nightly-2023-04-21"
afterwards.
Just plan things out and release more frequently.
None.
We need comments/thoughts on this.
I noticed the table widget is already scrollable via keyboard navigation: https://github.com/tui-rs-revival/ratatui/blob/main/examples/table.rs
But it is lacking of a scrollbar.
Relates to #146
Add a config scrollbar: bool
option or something similar that integrates a scrollbar to visualize the current position.
Ratatui doesn't seem to display bold text correctly even though both crossterm and termion do. I was seeing weird behavior and created this minimal repro case.
terminal.draw(|f| {
let size = f.size();
let para = Paragraph::new("This is displayed by ratatui and is not bold (but should be)")
.style(Style::default().add_modifier(Modifier::BOLD));
f.render_widget(para, size);
})?;
Text should be bold
Full source for repo:
use std::io::Stdout;
use std::{error, io, thread::sleep, time::Duration};
use ratatui::{
style::{Modifier, Style},
widgets::Paragraph,
Terminal,
};
#[cfg(feature = "crossterm")]
use ratatui::backend::CrosstermBackend;
#[cfg(feature = "termion")]
use ratatui::backend::TermionBackend;
#[cfg(feature = "crossterm")]
use crossterm::terminal;
#[cfg(feature = "termion")]
use termion::raw::{IntoRawMode, RawTerminal};
type Result<T> = std::result::Result<T, Box<dyn error::Error>>;
#[cfg(feature = "termion")]
fn display_native() {
use termion::style;
println!(
"{}This is displayed by termion and is bold{}",
style::Bold,
style::Reset
);
}
#[cfg(feature = "crossterm")]
fn display_native() {
use crossterm::style::Attribute;
println!(
"{}This is displayed by crossterm and is bold{}",
Attribute::Bold,
Attribute::Reset
);
}
#[cfg(feature = "termion")]
fn get_backend() -> Result<TermionBackend<RawTerminal<Stdout>>> {
let buffer = io::stdout().into_raw_mode()?;
Ok(TermionBackend::new(buffer))
}
#[cfg(feature = "crossterm")]
fn get_backend() -> Result<CrosstermBackend<Stdout>> {
let buffer = io::stdout();
terminal::enable_raw_mode()?;
crossterm::execute!(io::stdout(), terminal::EnterAlternateScreen)?;
Ok(CrosstermBackend::new(buffer))
}
#[cfg(feature = "termion")]
fn cleanup() {}
#[cfg(feature = "crossterm")]
fn cleanup() {
terminal::disable_raw_mode().unwrap();
crossterm::execute!(io::stdout(), terminal::LeaveAlternateScreen).unwrap();
}
fn main() -> Result<()> {
let backend = get_backend()?;
let mut terminal = Terminal::new(backend)?;
terminal.clear()?;
display_native();
sleep(Duration::from_secs(2));
terminal.clear()?;
terminal.draw(|f| {
let size = f.size();
let para = Paragraph::new("This is displayed by ratatui and is not bold (but should be)")
.style(Style::default().add_modifier(Modifier::BOLD));
f.render_widget(para, size);
})?;
sleep(Duration::from_secs(2));
terminal.clear()?;
cleanup();
Ok(())
}
Cargo.toml:
[package]
name = "scratch"
version = "0.1.0"
edition = "2021"
[features]
default = ["crossterm"]
crossterm = ["dep:crossterm", "ratatui/crossterm"]
termion = ["dep:termion", "ratatui/termion"]
[dependencies]
termion = { version = "2.0", optional = true }
crossterm = { version = "0.26", optional = true }
ratatui = { version = "0.20.0", default-features = false }
Commands:
cargo run --no-default-features --features crossterm
cargo run --no-default-features --features termion
I have a repo of some widgets I've generalized from a couple personal projects.
Widgets:
SytledList - Similar to widgets::List
, the StyledList
is a list widget. It offers more
display/decoration options, optional separators between ListItem
s and fixes a handful
of small annoyances (e.g. a selected multi-line item will always be fully displayed).
Calendar - Display a calendar for a month. This has some styling options, such as
including day headers (M, T, W ...) and whether fill the grid with days from other months.
It also has the ability to style the individual dates.
(not actually a widget) text_macros - Some macros for reducing boilerplate when working
with larger text regions. For example, rather than:
Span::styled(
"bold italic words",
Style::default()
.add_modifier(Modifier::BOLD)
.add_modifier(Modifier::ITALIC),
);
one could write:
bold!(italic!("bold italic words"))
I'm not sure of the best way to share these.
I see 3 possible solutions to "how do I share these?":
widgets
module of ratatui. I'm happy to contribute them if there's interest.ratatui-contrib
or similar).extra-widgets
is a terrible name, I'm open to suggestions!)There are pros and cons to each of the approaches.
Having a project approved library of widgets is nice for users - there are more building blocks to make software from, and the widgets from the "blessed" library likely to be kept up-to-date with the ratatui core changes. This adds more work for maintainers, but also provides an easy mechanism to ensure that components don't lag behind ratatui itself (e.g. if a widget crate builds against ratatui version x, but a project builds against ratatui version y, and wants to include the widget, there may be compatibility issues).
Having individual crates for widgets allows for more exploration and various ways to implement a concept, and and allows for more change in any given widget - a standard library of widgets, like a standard library for a programming language, may stagnate to maintain compatability for older programs and doing each widget as an independent crate helps avoid that. It hurts discoverability and crates run the risk of being abandoned forcing users to find a new fork (at best) or a new widget.
In the linked repo there are example programs for each widget in action. Additionally, in-depth rust docs can be generated from the repo - the --document-private-items
flag provides even more info.
On windows, I expected to be able to run a demo with the crossterm
backend after including ratatui
(alone) in my dependencies, since crossterm is included as a default feature.
In Cargo.toml
:
[dependencies]
ratatui = "0.20.1"
However, when I cargo build
, I get an error:
use of undeclared crate or module `crossterm`
Try to compile the gauge
example on windows:
$ cargo build
Compiling
error[E0433]: failed to resolve: use of undeclared crate or module `crossterm`
--> src\main.rs:1:5
|
1 | use crossterm::{
| ^^^^^^^^^ use of undeclared crate or module `crossterm`
error[E0432]: unresolved import `crossterm`
--> src\main.rs:1:5
|
1 | use crossterm::{
| ^^^^^^^^^ use of undeclared crate or module `crossterm`
error: cannot determine resolution for the macro `execute`
--> src\main.rs:61:5
|
61 | execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
| ^^^^^^^
|
= note: import resolution is stuck, try simplifying macro imports
error: cannot determine resolution for the macro `execute`
--> src\main.rs:72:5
|
72 | execute!(
| ^^^^^^^
|
= note: import resolution is stuck, try simplifying macro imports
error[E0433]: failed to resolve: use of undeclared crate or module `crossterm`
--> src\main.rs:98:12
|
98 | if crossterm::event::poll(timeout)? {
| ^^^^^^^^^ use of undeclared crate or module `crossterm`
Some errors have detailed explanations: E0432, E0433.
For more information about an error, try `rustc --explain E0432`.
As crossterm
is the default feature, this dependency should be installed and used automatically (unless one opts out of the default features). Right?
Just a suggestion: add this project to the list of CLI crates in Blessed.rs
This issue serves the purpose of tracking and discussing various quirks of the crate that should be addressed in one PR.
The wrapping in reflow is fairly convoluted, which makes it difficult to maintain (fix problems and add new features). This caused a problem in #193
text
module?)Improper formatting causes build/run workflows to fail instead of the lint workflow. This can make it confusing for new contributors when they forget to run cargo fmt
before committing.
Make a pull request with a commit that is not formatted using cargo fmt
.
6/7 of the workflows will fail due to the improper formatting, whereas the lint one may succeed (but does not always do so).
Similar to #149 , one could also individually wrap different Line
s inside the same paragraph. These Line
s would default to the LineComposer
used for the paragraph but can override that to use their own.
The uses cases would be the same as #149. People could use this to have differently formatted lines (truncated, word wrapped, character wrapped, etc.) inside the same paragraph with some specific scrolling and styling.
This is just an idea and probably not worth the effort if there is no demand by the user base. So we would like to have some feedback from you as both the project maintainers/contributors and users. Is this feature even desired?
When I execute one of the example code from your documentation, it prints random bytes on exit.
use std::{io, thread, time::Duration};
use ratatui::{
backend::CrosstermBackend,
widgets::{Widget, Block, Borders},
layout::{Layout, Constraint, Direction},
Terminal
};
use crossterm::{
event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
fn main() -> Result<(), io::Error> {
// setup terminal
enable_raw_mode()?;
let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
terminal.draw(|f| {
let size = f.size();
let block = Block::default()
.title("Block")
.borders(Borders::ALL);
f.render_widget(block, size);
})?;
thread::sleep(Duration::from_millis(5000));
// restore terminal
disable_raw_mode()?;
execute!(
terminal.backend_mut(),
LeaveAlternateScreen,
DisableMouseCapture
)?;
terminal.show_cursor()?;
Ok(())
}
To not print any byte to command line
None
> I added [tui-rs-revival/ratatui/wiki/Apps](https://github.com/tui-rs-revival/ratatui/wiki/Apps) (which I copied from APPS.md)
It makes sense to separate something which is not directly related to the library but in that case we need to make use of the Wiki more often to make it visible. Maybe after #184 is merged, we can remove that file and add a note in README.md about it is now a part of the Wiki or something. I'm okay with either way and I think having a separate file definitely makes the application list more apparent to the user. Need some comments on this so maybe create a issue/discussion?
Originally posted by @orhun in #179 (comment)
https://crates.io/search?q=ratatui - perhaps thats a project member from here, but if not, maybe another name change is needed.
When displaying text in Paragraph
, the calculation of the maximum number of lines is complicated by the need to wrap long horizontal lines.
For this reason, we would like the ability to get the block size of the text being displayed in a Paragraph
.
When I draw lines in vertical direction on a canvas with block as marker then I have gaps between the blocks.
In my view this in not consistent because a line has no gaps horizontall
Here is a code example on a gist of mine.
This gist produces the following output onto the terminal, see picture under additional context.
In the picture the red line is fine, however the blue line in the vertical direction produces gaps which I do not want.
For the example I have used this respo as tui dependency with the main branch on the commit 73f7f16
I reported this bug to tui-textarea https://github.com/rhysd/tui-textarea here rhysd/tui-textarea#14
They support tui and ratatui
In their demo app (very simple) the keystrokes are duplicated on windows. It works fine using tui but fails 100% using ratatui
here is gif of the behavior
The termwiz
demo repaints more than it should.
This might be an issue in the demo, or in the termwiz
backend.
Inspect:
cargo r --example demo --features termwiz --no-default-features
vs:
cargo r --example demo --features termion --no-default-features
cargo r --example demo
Ideally there should not be an obvious difference between the different backends in the example demo.
This is on a system, that doesn't have access to hardware acceleration, which I believe makes this issue more obvious.
MSRV of this crate is 1.59.0, but it is no longer tested on CI due to #80. Now Rust 1.63 is used because earlier than 1.63 cannot build cargo-make
. Since we usually don't care about old compilers when we modify source code, compatibility with old compilers can be easy broken. It should be protected by checks on CI.
N/A
1.59.0 should be tested on CI.
N/A
I'll make a pull request to fix this issue.
The table widget example is potentially misguiding users on the crossterm Events API. The table widget example uses the KeyCode enum in crossterm without filtering for the KeyEventKind::Press
, which leads in events being doubled when pressing keys. It isn't a bug per se, I just don't think that was the behavior that was intended from the snippet.
line 108-115 in this file for the exact part
With this crate's recent release, I think it would be nice to have some more general-purpose widgets added to the current repertoire. tui-rs-tree-widget is one such widget that I think this crate would benefit from having. As discussed in this issue, both the maintainer and I are interested in this merge.
Add the Tree
widget from tui-rs-tree-widget
into this repository.
There's a lot of boilerplate for common methods like style()
:
Paragraph::new("foo").style(Style::default().fg(Color::Blue).bg(Color::Red).add_modifier(Modifier::BOLD);
Make it easier to specify styles similar to Crossterm's Stylize
Paragraph::new("foo").blue().on_red().bold();
I think this can probably be implemented across every widget that supports style by adding a Styled
trait and implementing a Stylize
trait that has all the right methods (in crossterm these are generated using macros rather than the repetition I've written here).
pub trait Styled {
fn style(&self) -> Style;
fn set_style(self, style: Style) -> Self;
}
pub trait Stylize {
fn blue(self) -> Self;
fn on_red(self) -> Self;
fn bold(self) -> Self;
}
impl<T> Stylize for T
where
T: Styled,
{
fn blue(self) -> Self {
let style = self.style().fg(Color::Blue);
self.set_style(style)
}
fn on_red(self) -> Self {
let style = self.style().bg(Color::Red);
self.set_style(style)
}
fn bold(self) -> Self {
let style = self.style().add_modifier(Modifier::BOLD);
self.set_style(style)
}
}
impl<'a> Styled for Paragraph<'a> {
fn style(&self) -> Style {
self.style
}
fn set_style(self, style: Style) -> Paragraph<'a> {
Paragraph::style(self, style)
}
}
Perhaps:
Paragraph::new("foo").stylize().blue().on_red().bold();
Not sure about other options that would make sense.
This is a RFC. There are probably better ways of doing this, and I want to consider them before implementing this approach. Perhaps there's some magic that we can do using AsRef
/ Deref
for this?
First of all, thank you for making this project revive.
I'm suggesting to enable the discussions on this repository. Indeed, people may want to ask questions, share news of this project, and perhaps announce that the original owner came back.
Well, it will be a great opportunity to exchange about this project.
Hello all, I've been following fdehau/tui-rs#654 with interest!
I maintain an RSS/Atom reader called Russ that is built on tui-rs
(please feel free to add it to the list of projects using tui-rs
, as I am extremely pleased with and grateful for tui-rs
).
My question is this: given the fork, with regard to bug reports/feature requests/PRs, should I file those here, or upstream? Is the plan to merge the work in this fork upstream, or have this fork eventually replace upstream? Thank you to everyone actively working to keep tui-rs
going, it's such a lovely project.
Could you provide an example such as https://github.com/tui-rs-revival/ratatui/blob/main/examples/user_input.rs that demonstrates how to use ratatui with Tokio?
Nowadays there are many libs that provide async versions only (such as the official AWS SDK).
My use case is that I have to trigger some async fn when receiving user input.
No clear indication on how to create nested blocks.
Add an example that displays a simple nested blocks.
Right now there isn't a specific convention for commits and adopting conventional commits would be nice.
Utilize a tool for checking the PRs for conventional commits. Such as action-semantic-pull-request or cocogitto.
None.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.