v0.26.0
https://github.com/ratatui/ratatui/releases/tag/v0.26.0
このリリースについては、 breaking changes を参照してください。
FOSDEM
このリリースが公開された時点で、メンテナーの1人 ( Orhun Parmaksız ) は、 FOSDEM でRatatuiについての入門的な講演を行います!講演も記録され、ライブでストリーミングされます。
イベントの詳細 here を参照してください。
お近くにお越しの際は、ぜひ Ratatui のステッカーをゲットするチャンスをお見逃しなく!
デモ: モードを破壊する
破壊モードを備えた新しいデモができました! (Ratatui の 1000 番目のコミットを祝うために作成されました)
それを実行するには:
cargo run --example demo2 --features="crossterm widget-calendar"
d
を押して、Destroy Modeをアクティブにして楽しんでください!
REFウィジェット実装🧩
多くのウィジェットは、状態を変更せずにレンダリングできるようになりました。
ウィジェットへの参照のために WidgetRef
のtrait を実装し、その実装を不変に変更しました。これにより、ウィジェットを消費せずにレンダリングすることができます。ウィジェットをウィジェットに Frame::render_widget()
に渡すことができます。また、箱入りウィジェットをレンダリングすることもできます。
注: このtrait は、機能フラグ unstable-widget-ref
の後ろにゲートされています。私たちが取るアプローチは、これに対して変更される可能性があります (以下のコードが WidgetRef
の代わりに Widget
を使用できるようにするアプローチがあるため) 。
// this might be stored in a structlet paragraph = Paragraph::new("Hello world!");
let [left, right] = area.split(&Layout::horizontal([20, 20]));frame.render_widget(¶graph, left);frame.render_widget(¶graph, right); // we can reuse the widget
let widgets: Vec<Box<dyn WidgetRef>> = vec![Box::new(Line::raw("hello"), Span::raw("world"))];for widget in widgets { widget.render_ref(area, &mut buf);}
レイアウト: flex
✨
Layout
内の要素の間隔を設定する新しい方法、Flex をサポートするようになりました。flexbox をベースにした Flex
列挙型を追加しました。
Flex::Start
(新しいデフォルト)Flex::Center
Flex::End
Flex::SpaceAround
Flex::SpaceBetween
Flex::Legacy
(古いデフォルト)
デフォルトを Flex::Start
に変更することに加えて、制約にいくつかの変更を加えました。
-
Min(v)
は、縮小するのではなく、すべてのFlex
モードで余分なスペースを割り当てるために拡大します (古い動作を保持するFlex::Legacy
を除く)。 -
余分なスペースを割り当てるために拡大し、
Min(v)
と同等に拡大する新しい制約バリアントFill(1)
を追加しました。
制約の動作に対する重大な変更ですが、ほとんどのユーザーは、特に Min()
が制約の 1 つである場合、新しい Flex::Start
で同じレイアウトを確認できるはずです。ただし、古い動作が必要な場合は、Flex::Legacy
を使用できます。
Layout::vertical([Length(25), Length(25)]).flex(Flex::Legacy)
また、不安定な機能 SegmentSize
を削除しました。
この機能の背後にある動機と詳細については、 pull request をご覧ください。
また、Constraint-Explorer TUIを構築しました。これにより、さまざまな Flex
モードで制約がどのように動作するかを比較できます。 constraint-explorer
のビデオデモについては、 pull request をチェックしてください。
カラーパレット🎨
使用できる2つの真新しい色のパレット、 Material と Tailwind があります。
ratatui::style::palette::material
モジュールには、Google 2014マテリアルデザインパレットが含まれています。
use ratatui::style::palette::material::BLUE_GRAY;Line::styled("Hello", BLUE_GRAY.c500);
ratatui::style::palette::tailwind
モジュールには、デフォルトのテールワインドカラーパレットが含まれています。これは、Tailwindカラーパレットに合った色のスタイリングコンポーネントに役立ちます。
use ratatui::style::palette::tailwind::SLATE;Line::styled("Hello", SLATE.c500);
詳細については、https://m2.material.io/design/color/the-color-system.html#tools-for-picking-colorsおよびhttps://tailwindcss.com/docs/customizing-colorsを参照してください。
アライメントコンビニエンス関数🏗️
Line
、Paragraph
、Text
に次の配置便利関数を追加しました。
Line::from("align on left").left_aligned();
Line::from("centered!").centered();
Line::from("align on right").right_aligned();
Paragraph
と Text
にも同じことが適用されます (例: Paragraph::new("Hello, world!").centered()
)。
Span
一方、次の新しい方法があります。
let span = Span::styled("Test Content", Style::new().green().italic());
// convert span to left-aligned linelet line = span.to_left_aligned_line();
// convert span to right-aligned linelet line = span.to_right_aligned_line();
// convert span to center-aligned linelet line = span.to_center_aligned_line();
パディング: 新しいコンストラクター🏗️
Padding
には新しいコンストラクターがあります。
Padding::proportional(4);
: 水平方向と垂直方向のパディングを等しくしますPadding::symmetric(5, 6);
: 左右のパディングを定義しますPadding::left(3);
: 左のパディングを定義しますPadding::right(3);
: 右のパディングを定義しますPadding::top(3);
: 上のパディングを定義しますPadding::bottom(3);
: 下のパディングを定義します
ブロック: bordered
🧱
Block
には、境界なしのブロックの作成と設定 Borders::ALL
を避けるための bordered
という名前の新しいコンストラクターメソッドがあります。
そのため、次のようにコードを簡素化できます。
Block::default().borders(Borders::ALL);Block::bordered();
色: 新しいコンストラクター🏗️
Color
は、 u32
値から構築できます。フォーマットは 0x00RRGGBB
です。
let white = Color::from_u32(0x00FFFFFF);let black = Color::from_u32(0x00000000);
また、 Color::Rgb
値を構築するための from_hsl
メソッドも追加しました。
let color: Color = Color::from_hsl(360.0, 100.0, 100.0);assert_eq!(color, Color::Rgb(255, 255, 255));
let color: Color = Color::from_hsl(0.0, 0.0, 0.0);assert_eq!(color, Color::Rgb(0, 0, 0));
HSLは、色相 (0-360度) 、飽和 (0-100%) 、および軽さ (0-100%) を略し、HSL の作業はより直感的になります。たとえば、赤い色をよりオレンジ色にしたい場合は、色のホイール上の黄色に近い色の色を変えることができます (つまり、色相を増やします) 。
レイアウト: キャッシュサイズを増やする
レイアウトのデフォルトのキャッシュサイズを16から500に増やします。
これは、 ラップトップのターミナル (171+51 = 222) に列と行を追加し、適切な尺度で2倍にし、 ラウンド数になります。これにより、すべての行とすべての列のレイアウトを2回上に保存するのに十分なエントリが提供されます。これは、ほとんどのアプリに十分なはずです。
さらに必要な場合は、キャッシュサイズを Layout::init_cache()
で設定できます。
this issue の関連する議論を参照してください。
レイアウト: 水平および垂直コンストラクター🏗️
Layout
では、次のコンストラクタを使用して、デフォルト値を持つ垂直または水平レイアウトを作成できるようになりました。
let layout = Layout::vertical([Constraint::Length(10), Constraint::Min(5)]);let layout = Layout::horizontal([Constraint::Length(10), Constraint::Min(5)]);
レイアウト: 制約を受け入れます
レイアウト コンストラクターは、AsRef<Constraint>
だけでなく、Into<Constraint>
を実装する任意の型を受け入れるようになりました。これは、レイアウトの固定サイズを指定したいが、Constraint::Length
を明示的に自分で作成したくない場合に便利です。
Layout::new(Direction::Vertical, [1, 2, 3]);Layout::horizontal([1, 2, 3]);Layout::vertical([1, 2, 3]);Layout::default().constraints([1, 2, 3]);
レイアウト: spacing
📏
これで、レイアウトのアイテム間に間隔を追加できるようになりました。
let layout = Layout::horizontal([Length(20), Length(20), Length(20)]).spacing(2);
rect: contains
🔲
ヒット テストを実行したい場合は、この新しいメソッドが適しています。(例: ユーザーが領域をクリックしたかどうか)
Rect::new(1, 2, 3, 4).contains(Position { x: 1, y: 2 }) // true
また、x 座標と y 座標 (列と行) を格納するための Position
構造体も追加しました。
rect: clamp
🦞
四角形を動的に移動できるようにしたいが、特定の領域に制限したい場合に便利な新しいメソッドがあります。
たとえば、これを使用して、移動できるがターミナル ウィンドウの外側には移動できないドラッグ可能なウィンドウを実装できます。
let window_area = Rect::new(state.x, state.y, 20, 20).clamp(area);state.x = rect.x;state.y = rect.y;
レイアウト: areas
および spacers
メソッド🍌
これで、より簡潔な方法で Rect
を複数のサブ Rect
に分割できるようになりました。
use Constraint::*;let layout = Layout::vertical([Length(1), Min(0)]);let [top, main] = layout.areas();let [above, inbetwee, below] = layout.spacers();
rect: rows/colums iterators🔲
これにより、Rect の行と列を反復処理できるようになり、セルのループが簡素化されます。
let area = Rect::new(0, 0, 3, 2);let rows: Vec<Rect> = area.rows().collect();let columns: Vec<Rect> = area.columns().collect();
表: 制約を受け入れます
テーブル コンストラクターは、AsRef<Constraint>
だけでなく、Into<Constraint>
を実装する任意の型を受け入れるようになりました。これは、テーブル列の固定サイズを指定したいが、Constraint::Length
を明示的に自分で作成したくない場合に便利です。
Table::new(rows, [1,2,3])Table::default().widths([1,2,3])
表: Iteratorを受け入れます
以前は、Table::new()
は IntoIterator<Item=Row<'a>>
を受け入れていました。引数が
IntoIterator<Item: Into<Row<'a>>>
に変更されました。これにより、呼び出しスコープからより柔軟な型を使用できますが、空のコンテナの呼び出しスコープでの型推論が一部壊れる可能性があります。
let table = Table::new(vec![], widths);// becomes let table = Table::default().widths(widths);
これは、項目が Row
に変換可能なイテレータを Table
に収集できるようになったことも意味します。
表: テキストをハイライトシンボル📊として受け入れます
これで、マルチラインシンボルを使用して、テーブル内のアイテムを強調表示できます。
let table = Table::new(rows, widths) .highlight_symbol(Text::from(vec![ "".into(), " █ ".into(), " █ ".into(), "".into(), ]));
See the demo
表: footer
📊
Table
は、下部に表示される行を設定するための footer
メソッドがあるようになりました。
let footer = Row::new(vec![ Cell::from("Footer Cell 1"), Cell::from("Footer Cell 2"),]);let table = Table::default().footer(footer);
それに加えて、 Row
の新しい top_margin
メソッドがあります。
let row = Row::default().top_margin(1);
ウィジェット実装🧩
Line
と Span
は Widget
を実装するようになりました。つまり、他のウィジェットの子として使用できます。
buffer.set_line()
を呼び出す代わりに、Line::render()
を使用してレンダリングすることもできます。
frame.render_widget(Line::raw("Hello, world!"), area);// orLine::raw("Hello, world!").render(frame, area);
Span
にも同じことが当てはまり、 buffer.set_span()
を呼び出すのではなく、 Span::render()
を使用してレンダリングできます。
行: styled
🎨
以前は、 Line
のスタイルは、ラインを構成する Span
に保存されていました。これで、 Line
自体には style
フィールドがあり、 Line::styled
メソッドで設定できます。
let style = Style::new().yellow();let content = "Hello, world!";let line = Line::styled(content, style);
コンストラクタの代わりに構造体初期化子を使用して Line
を作成するコードは、追加されたフィールドが原因でコンパイルに失敗します。これは、フィールド リストに ..Default::default()
を追加するか、コンストラクタ メソッド (Line::styled()
、Line::raw()
) または変換メソッド (Line::from()
) を使用することで簡単に修正できます。
let line = Line { spans: vec!["".into()], alignment: Alignment::Left, ..Default::default()};
スタイル: 🎨に受け入れます
すべてのスタイル関連メソッドは、Style
の代わりに S: Into<Style>
を受け入れるようになりました。Color
と Modifier
は Into<Style>
を実装しているため、より人間工学的な使用が可能になります。例:
Line::styled("hello", Style::new().red());Line::styled("world", Style::new().bold());
// can now be simplified to
Line::styled("hello", Color::Red);Line::styled("world", Modifier::BOLD);
つまり、Into<Style>
を実装するあいまいな型をすでに渡している場合は、.into()
呼び出しを削除する必要があります。
タブ: Line
のiteratorを受け入れます📑
以前は Tabs::new
が Vec
を必要としていましたが、 Into<Line>
を実装するアイテムタイプで IntoIterator
を実装するオブジェクトを受け入れることができます。
Tabs::new()
への呼び出しは、iteratorから引数が収集されたものでコンパイルされなくなります。
たとえば、 .collect()
の返品タイプが Vec<_>
であると推測できなくなるため、 Tabs::new(["a","b"].into_iter().collect())
はコンパイルされなくなります。
let table = Tabs::new((0.3).map(|i| format!("{i}")).collect());// becomes let table = Tabs::new((0.3).map(|i| format!("{i}")));
新しいボーダーセット🔲
McGugan
ボーダーセットを追加しました。これにより、境界線が狭くなります。
McGugan Boxテクニックに基づいた広い境界セット:
▁▁▁▁▁▁▁▏xxxxx▕▏xxxxx▕▔▔▔▔▔▔▔
McGugan Boxテクニックに基づいた背の高いボーダーセット:
▕▔▔▏▕xx▏▕xx▏▕▁▁▏
ターミナル: フレームカウント🔢
現在のフレームカウントを取得できます!
let mut frame = terminal.get_frame();let current_count = frame.count();println!("Current frame count: {}", current_count);
このカウントは、ディスプレイの状態が時間とともに変化する動的なコンテンツまたはアニメーションを扱う場合に特に役立ちます。フレームカウントを追跡することにより、開発者は更新またはレンダリングプロセスでコンテンツの変更を同期させることができます。
バッファ: SSO🐜
buffer::Cell
のテキスト バッファに SSO (小さな文字列の最適化) 手法を適用するようになりました。つまり、Cell::symbol
フィールドを格納するために String
ではなく CompactString
を使用します。これにより、実行時のメモリ割り当てのサイズが削減されます。
関連する議論 here を参照してください。
他の💼
Constraint::Proportional
をConstraint::Fill
に変更します ( #880 )- rect->サイズの変換方法 ( #789 )
- Implement
Display
forText
,Line
,Span
( #826 ) - Support de/serialization of TableState, ListState, and ScrollbarState via
serde
feature - Implement FromIterator for Row ( #755 )
- TERMWIZスタイルに
From
を追加 ( #726 ) Text
( #807 ) にスタイルとアライメントを追加しますList
のListItem
にイテレーターを収集 ( #757 )patch_style
およびreset_style
チェーン可能 ( #754 ) を作成します