diff --git a/README.md b/README.md
index 94dbca5..1253f23 100644
--- a/README.md
+++ b/README.md
@@ -211,10 +211,8 @@ loop {
term.draw(|f| {
// Get `ratatui::layout::Rect` where the editor should be rendered
let rect = ...;
- // `TextArea::widget` builds a widget to render the editor with tui
- let widget = textarea.widget();
- // Render the widget in terminal screen
- f.render_widget(widget, rect);
+ // Render the textarea in terminal screen
+ f.render_widget(&textarea, rect);
})?;
if let Event::Key(key) = read()? {
@@ -234,8 +232,7 @@ println!("Lines: {:?}", textarea.lines());
`TextArea` is an instance to manage the editor state. By default, it disables line numbers and highlights cursor line
with underline.
-`TextArea::widget()` builds a widget to render the current state of the editor. Create the widget and render it on each
-tick of event loop.
+`&TextArea` reference implements ratatui's `Widget` trait. Render it on every tick of event loop.
`TextArea::input()` receives inputs from tui backends. The method can take key events from backends such as
`crossterm::event::KeyEvent` or `termion::event::Key` directly if the features are enabled. The method handles default
@@ -440,7 +437,7 @@ tui-textarea = { version = "*", features = ["search"] }
### Single-line input like `` in HTML
-To use `TextArea` for single-line input widget like `` in HTML, ignore all key mappings which inserts newline.
+To use `TextArea` for a single-line input widget like `` in HTML, ignore all key mappings which inserts newline.
```rust,ignore
use crossterm::event::{Event, read};
@@ -628,9 +625,8 @@ loop {
term.draw(|f| {
let rects = ...;
- for (editor, rect) in editors.iter_mut().zip(rects.into_iter()) {
- let widget = editor.widget();
- f.render_widget(widget, rect);
+ for (editor, rect) in editors.iter().zip(rects.into_iter()) {
+ f.render_widget(editor, rect);
}
})?;
diff --git a/bench/src/lib.rs b/bench/src/lib.rs
index 480fd54..fa90f2e 100644
--- a/bench/src/lib.rs
+++ b/bench/src/lib.rs
@@ -116,7 +116,6 @@ pub trait TerminalExt {
impl TerminalExt for Terminal {
#[inline]
fn draw_textarea(&mut self, textarea: &TextArea<'_>) {
- self.draw(|f| f.render_widget(textarea.widget(), f.size()))
- .unwrap();
+ self.draw(|f| f.render_widget(textarea, f.size())).unwrap();
}
}
diff --git a/examples/editor.rs b/examples/editor.rs
index 3680348..2eded14 100644
--- a/examples/editor.rs
+++ b/examples/editor.rs
@@ -188,13 +188,12 @@ impl<'a> Editor<'a> {
let chunks = layout.split(f.size());
if search_height > 0 {
- f.render_widget(self.search.textarea.widget(), chunks[0]);
+ f.render_widget(&self.search.textarea, chunks[0]);
}
let buffer = &self.buffers[self.current];
let textarea = &buffer.textarea;
- let widget = textarea.widget();
- f.render_widget(widget, chunks[1]);
+ f.render_widget(&textarea, chunks[1]);
// Render status line
let modified = if buffer.modified { " [modified]" } else { "" };
diff --git a/examples/minimal.rs b/examples/minimal.rs
index ac37201..9850b1b 100644
--- a/examples/minimal.rs
+++ b/examples/minimal.rs
@@ -26,7 +26,7 @@ fn main() -> io::Result<()> {
loop {
term.draw(|f| {
- f.render_widget(textarea.widget(), f.size());
+ f.render_widget(&textarea, f.size());
})?;
match crossterm::event::read()?.into() {
Input { key: Key::Esc, .. } => break,
diff --git a/examples/password.rs b/examples/password.rs
index dfe6a90..e7518a1 100644
--- a/examples/password.rs
+++ b/examples/password.rs
@@ -31,8 +31,7 @@ fn main() -> io::Result<()> {
loop {
term.draw(|f| {
let chunks = layout.split(f.size());
- let widget = textarea.widget();
- f.render_widget(widget, chunks[0]);
+ f.render_widget(&textarea, chunks[0]);
})?;
match crossterm::event::read()?.into() {
diff --git a/examples/popup_placeholder.rs b/examples/popup_placeholder.rs
index d705761..136de5c 100644
--- a/examples/popup_placeholder.rs
+++ b/examples/popup_placeholder.rs
@@ -38,7 +38,7 @@ fn main() -> io::Result<()> {
textarea.set_placeholder_text("prompt message");
loop {
term.draw(|f| {
- f.render_widget(textarea.widget(), area);
+ f.render_widget(&textarea, area);
})?;
match crossterm::event::read()?.into() {
Input { key: Key::Esc, .. } => break,
diff --git a/examples/single_line.rs b/examples/single_line.rs
index 1b13f29..1b33df9 100644
--- a/examples/single_line.rs
+++ b/examples/single_line.rs
@@ -50,8 +50,7 @@ fn main() -> io::Result<()> {
loop {
term.draw(|f| {
let chunks = layout.split(f.size());
- let widget = textarea.widget();
- f.render_widget(widget, chunks[0]);
+ f.render_widget(&textarea, chunks[0]);
})?;
match crossterm::event::read()?.into() {
diff --git a/examples/split.rs b/examples/split.rs
index 6d7afd8..9454651 100644
--- a/examples/split.rs
+++ b/examples/split.rs
@@ -54,8 +54,7 @@ fn main() -> io::Result<()> {
term.draw(|f| {
let chunks = layout.split(f.size());
for (textarea, chunk) in textarea.iter().zip(chunks.iter()) {
- let widget = textarea.widget();
- f.render_widget(widget, *chunk);
+ f.render_widget(textarea, *chunk);
}
})?;
match crossterm::event::read()?.into() {
diff --git a/examples/termion.rs b/examples/termion.rs
index 3a73fe2..95c5662 100644
--- a/examples/termion.rs
+++ b/examples/termion.rs
@@ -57,8 +57,7 @@ fn main() -> Result<(), Box> {
Event::Tick => {}
}
term.draw(|f| {
- let widget = textarea.widget();
- f.render_widget(widget, f.size());
+ f.render_widget(&textarea, f.size());
})?;
}
diff --git a/examples/termwiz.rs b/examples/termwiz.rs
index d76349a..a6103f5 100644
--- a/examples/termwiz.rs
+++ b/examples/termwiz.rs
@@ -22,8 +22,7 @@ fn main() -> Result<(), Box> {
// The event loop
loop {
term.draw(|f| {
- let widget = textarea.widget();
- f.render_widget(widget, f.size());
+ f.render_widget(&textarea, f.size());
})?;
if let Some(input) = term
diff --git a/examples/tuirs_editor.rs b/examples/tuirs_editor.rs
index c40a74e..ad953fc 100644
--- a/examples/tuirs_editor.rs
+++ b/examples/tuirs_editor.rs
@@ -190,13 +190,12 @@ impl<'a> Editor<'a> {
let chunks = layout.split(f.size());
if search_height > 0 {
- f.render_widget(self.search.textarea.widget(), chunks[0]);
+ f.render_widget(&self.search.textarea, chunks[0]);
}
let buffer = &self.buffers[self.current];
let textarea = &buffer.textarea;
- let widget = textarea.widget();
- f.render_widget(widget, chunks[1]);
+ f.render_widget(&textarea, chunks[1]);
// Render status line
let modified = if buffer.modified { " [modified]" } else { "" };
diff --git a/examples/tuirs_minimal.rs b/examples/tuirs_minimal.rs
index 2c41cba..743863c 100644
--- a/examples/tuirs_minimal.rs
+++ b/examples/tuirs_minimal.rs
@@ -28,7 +28,7 @@ fn main() -> io::Result<()> {
loop {
term.draw(|f| {
- f.render_widget(textarea.widget(), f.size());
+ f.render_widget(&textarea, f.size());
})?;
match crossterm::event::read()?.into() {
Input { key: Key::Esc, .. } => break,
diff --git a/examples/tuirs_termion.rs b/examples/tuirs_termion.rs
index 63ac412..7429b3e 100644
--- a/examples/tuirs_termion.rs
+++ b/examples/tuirs_termion.rs
@@ -57,8 +57,7 @@ fn main() -> Result<(), Box> {
Event::Tick => {}
}
term.draw(|f| {
- let widget = textarea.widget();
- f.render_widget(widget, f.size());
+ f.render_widget(&textarea, f.size());
})?;
}
diff --git a/examples/variable.rs b/examples/variable.rs
index bed500e..cb07a01 100644
--- a/examples/variable.rs
+++ b/examples/variable.rs
@@ -34,7 +34,7 @@ fn main() -> io::Result<()> {
.direction(Direction::Vertical)
.constraints([Constraint::Length(height), Constraint::Min(0)])
.split(f.size());
- f.render_widget(textarea.widget(), chunks[0]);
+ f.render_widget(&textarea, chunks[0]);
})?;
match crossterm::event::read()?.into() {
Input { key: Key::Esc, .. } => break,
diff --git a/examples/vim.rs b/examples/vim.rs
index ce0679c..0e22edb 100644
--- a/examples/vim.rs
+++ b/examples/vim.rs
@@ -419,7 +419,7 @@ fn main() -> io::Result<()> {
let mut vim = Vim::new(Mode::Normal);
loop {
- term.draw(|f| f.render_widget(textarea.widget(), f.size()))?;
+ term.draw(|f| f.render_widget(&textarea, f.size()))?;
vim = match vim.transition(crossterm::event::read()?.into(), &mut textarea) {
Transition::Mode(mode) if vim.mode != mode => {
diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock
index b7fd1e5..ce852f2 100644
--- a/fuzz/Cargo.lock
+++ b/fuzz/Cargo.lock
@@ -453,7 +453,7 @@ dependencies = [
[[package]]
name = "tui-textarea"
-version = "0.5.1"
+version = "0.5.2"
dependencies = [
"arbitrary",
"crossterm",
diff --git a/src/cursor.rs b/src/cursor.rs
index 4e51449..b54c636 100644
--- a/src/cursor.rs
+++ b/src/cursor.rs
@@ -233,7 +233,7 @@ pub enum CursorMove {
/// ```
/// # use ratatui::buffer::Buffer;
/// # use ratatui::layout::Rect;
- /// # use ratatui::widgets::Widget;
+ /// # use ratatui::widgets::Widget as _;
/// use tui_textarea::{TextArea, CursorMove};
///
/// // Let's say terminal height is 8.
@@ -244,7 +244,7 @@ pub enum CursorMove {
/// # // Call `render` at least once to populate terminal size
/// # let r = Rect { x: 0, y: 0, width: 24, height: 8 };
/// # let mut b = Buffer::empty(r.clone());
- /// # textarea.widget().render(r, &mut b);
+ /// # textarea.render(r, &mut b);
///
/// // Move cursor to the end of lines (line 20). It is outside the viewport (line 1 to line 8)
/// textarea.move_cursor(CursorMove::Bottom);
@@ -378,7 +378,7 @@ mod tests {
fn in_viewport() {
use crate::ratatui::buffer::Buffer;
use crate::ratatui::layout::Rect;
- use crate::ratatui::widgets::Widget;
+ use crate::ratatui::widgets::Widget as _;
use crate::{CursorMove, TextArea};
let mut textarea: TextArea = (0..20).map(|i| i.to_string()).collect();
@@ -389,7 +389,7 @@ mod tests {
height: 8,
};
let mut b = Buffer::empty(r);
- textarea.widget().render(r, &mut b);
+ textarea.render(r, &mut b);
textarea.move_cursor(CursorMove::Bottom);
assert_eq!(textarea.cursor(), (19, 0));
diff --git a/src/scroll.rs b/src/scroll.rs
index 875f906..23f301f 100644
--- a/src/scroll.rs
+++ b/src/scroll.rs
@@ -18,7 +18,7 @@ pub enum Scrolling {
/// ```
/// # use ratatui::buffer::Buffer;
/// # use ratatui::layout::Rect;
- /// # use ratatui::widgets::Widget;
+ /// # use ratatui::widgets::Widget as _;
/// use tui_textarea::{TextArea, Scrolling};
///
/// // Let's say terminal height is 8.
@@ -28,7 +28,7 @@ pub enum Scrolling {
/// # // Call `render` at least once to populate terminal size
/// # let r = Rect { x: 0, y: 0, width: 24, height: 8 };
/// # let mut b = Buffer::empty(r.clone());
- /// # textarea.widget().render(r, &mut b);
+ /// # textarea.render(r, &mut b);
///
/// // Scroll down by 2 lines.
/// textarea.scroll(Scrolling::Delta{rows: 2, cols: 0});
@@ -44,7 +44,7 @@ pub enum Scrolling {
/// ```
/// # use ratatui::buffer::Buffer;
/// # use ratatui::layout::Rect;
- /// # use ratatui::widgets::Widget;
+ /// # use ratatui::widgets::Widget as _;
/// use tui_textarea::{TextArea, Scrolling};
///
/// // Let's say terminal height is 8.
@@ -54,7 +54,7 @@ pub enum Scrolling {
/// # // Call `render` at least once to populate terminal size
/// # let r = Rect { x: 0, y: 0, width: 24, height: 8 };
/// # let mut b = Buffer::empty(r.clone());
- /// # textarea.widget().render(r, &mut b);
+ /// # textarea.render(r, &mut b);
///
/// // Scroll down by one page (8 lines)
/// textarea.scroll(Scrolling::PageDown);
@@ -70,7 +70,7 @@ pub enum Scrolling {
/// ```
/// # use ratatui::buffer::Buffer;
/// # use ratatui::layout::Rect;
- /// # use ratatui::widgets::Widget;
+ /// # use ratatui::widgets::Widget as _;
/// use tui_textarea::{TextArea, Scrolling, CursorMove};
///
/// // Let's say terminal height is 8.
@@ -80,13 +80,13 @@ pub enum Scrolling {
/// # // Call `render` at least once to populate terminal size
/// # let r = Rect { x: 0, y: 0, width: 24, height: 8 };
/// # let mut b = Buffer::empty(r.clone());
- /// # textarea.widget().render(r.clone(), &mut b);
+ /// # textarea.render(r.clone(), &mut b);
///
/// // Go to the last line at first
/// textarea.move_cursor(CursorMove::Bottom);
/// assert_eq!(textarea.cursor(), (19, 0));
/// # // Call `render` to populate terminal size
- /// # textarea.widget().render(r.clone(), &mut b);
+ /// # textarea.render(r.clone(), &mut b);
///
/// // Scroll up by one page (8 lines)
/// textarea.scroll(Scrolling::PageUp);
@@ -100,7 +100,7 @@ pub enum Scrolling {
/// ```
/// # use ratatui::buffer::Buffer;
/// # use ratatui::layout::Rect;
- /// # use ratatui::widgets::Widget;
+ /// # use ratatui::widgets::Widget as _;
/// use tui_textarea::{TextArea, Scrolling};
///
/// // Let's say terminal height is 8.
@@ -110,7 +110,7 @@ pub enum Scrolling {
/// # // Call `render` at least once to populate terminal size
/// # let r = Rect { x: 0, y: 0, width: 24, height: 8 };
/// # let mut b = Buffer::empty(r.clone());
- /// # textarea.widget().render(r, &mut b);
+ /// # textarea.render(r, &mut b);
///
/// // Scroll down by half-page (4 lines)
/// textarea.scroll(Scrolling::HalfPageDown);
@@ -126,7 +126,7 @@ pub enum Scrolling {
/// ```
/// # use ratatui::buffer::Buffer;
/// # use ratatui::layout::Rect;
- /// # use ratatui::widgets::Widget;
+ /// # use ratatui::widgets::Widget as _;
/// use tui_textarea::{TextArea, Scrolling, CursorMove};
///
/// // Let's say terminal height is 8.
@@ -136,13 +136,13 @@ pub enum Scrolling {
/// # // Call `render` at least once to populate terminal size
/// # let r = Rect { x: 0, y: 0, width: 24, height: 8 };
/// # let mut b = Buffer::empty(r.clone());
- /// # textarea.widget().render(r.clone(), &mut b);
+ /// # textarea.render(r.clone(), &mut b);
///
/// // Go to the last line at first
/// textarea.move_cursor(CursorMove::Bottom);
/// assert_eq!(textarea.cursor(), (19, 0));
/// # // Call `render` to populate terminal size
- /// # textarea.widget().render(r.clone(), &mut b);
+ /// # textarea.render(r.clone(), &mut b);
///
/// // Scroll up by half-page (4 lines)
/// textarea.scroll(Scrolling::HalfPageUp);
@@ -193,7 +193,7 @@ mod tests {
fn delta() {
use crate::ratatui::buffer::Buffer;
use crate::ratatui::layout::Rect;
- use crate::ratatui::widgets::Widget;
+ use crate::ratatui::widgets::Widget as _;
use crate::TextArea;
let mut textarea: TextArea = (0..20).map(|i| i.to_string()).collect();
@@ -204,7 +204,7 @@ mod tests {
height: 8,
};
let mut b = Buffer::empty(r);
- textarea.widget().render(r, &mut b);
+ textarea.render(r, &mut b);
textarea.scroll(Scrolling::Delta { rows: 2, cols: 0 });
assert_eq!(textarea.cursor(), (2, 0));
diff --git a/src/textarea.rs b/src/textarea.rs
index 0efd170..6c216f2 100644
--- a/src/textarea.rs
+++ b/src/textarea.rs
@@ -9,7 +9,7 @@ use crate::scroll::Scrolling;
#[cfg(feature = "search")]
use crate::search::Search;
use crate::util::{spaces, Pos};
-use crate::widget::{Renderer, Viewport};
+use crate::widget::Viewport;
use crate::word::{find_word_exclusive_end_forward, find_word_start_backward};
#[cfg(feature = "ratatui")]
use ratatui::text::Line;
@@ -55,13 +55,18 @@ impl fmt::Display for YankText {
}
}
-/// A type to manage state of textarea.
+/// A type to manage state of textarea. These are some important methods:
///
-/// [`TextArea::default`] creates an empty textarea. [`TextArea::new`] creates a textarea with given text lines.
-/// [`TextArea::from`] creates a textarea from an iterator of lines. [`TextArea::input`] handles key input.
-/// [`TextArea::widget`] builds a widget to render. And [`TextArea::lines`] returns line texts.
+/// - [`TextArea::default`] creates an empty textarea.
+/// - [`TextArea::new`] creates a textarea with given text lines.
+/// - [`TextArea::from`] creates a textarea from an iterator of lines.
+/// - [`TextArea::input`] handles key input.
+/// - [`TextArea::lines`] returns line texts.
/// ```
/// use tui_textarea::{TextArea, Input, Key};
+/// use ratatui::backend::CrosstermBackend;
+/// use ratatui::layout::{Constraint, Direction, Layout};
+/// use ratatui::Terminal;
///
/// let mut textarea = TextArea::default();
///
@@ -69,12 +74,35 @@ impl fmt::Display for YankText {
/// let input = Input { key: Key::Char('a'), ctrl: false, alt: false, shift: false };
/// textarea.input(input);
///
-/// // Get widget to render.
-/// let widget = textarea.widget();
-///
/// // Get lines as String.
/// println!("Lines: {:?}", textarea.lines());
/// ```
+///
+/// It implements [`ratatui::widgets::Widget`] trait so it can be rendered to a
+/// terminal screen via [`ratatui::terminal::Frame::render_widget`] method.
+/// ```no_run
+/// use ratatui::backend::CrosstermBackend;
+/// use ratatui::layout::{Constraint, Direction, Layout};
+/// use ratatui::Terminal;
+/// use tui_textarea::TextArea;
+///
+/// let mut textarea = TextArea::default();
+///
+/// let layout = Layout::default()
+/// .direction(Direction::Vertical)
+/// .constraints([Constraint::Min(1)].as_ref());
+/// let backend = CrosstermBackend::new(std::io::stdout());
+/// let mut term = Terminal::new(backend).unwrap();
+///
+/// loop {
+/// term.draw(|f| {
+/// let chunks = layout.split(f.size());
+/// f.render_widget(&textarea, chunks[0]);
+/// }).unwrap();
+///
+/// // ...
+/// }
+/// ```
#[derive(Clone, Debug)]
pub struct TextArea<'a> {
lines: Vec,
@@ -1589,32 +1617,41 @@ impl<'a> TextArea<'a> {
/// Build a ratatui (or tui-rs) widget to render the current state of the textarea. The widget instance returned
/// from this method can be rendered with [`ratatui::terminal::Frame::render_widget`].
+ ///
+ /// This method was deprecated at v0.5.3 and is no longer necessary. Instead you can directly pass `&TextArea`
+ /// reference to the `Frame::render_widget` method call.
/// ```no_run
- /// use ratatui::backend::CrosstermBackend;
- /// use ratatui::layout::{Constraint, Direction, Layout};
- /// use ratatui::Terminal;
- /// use tui_textarea::TextArea;
+ /// # use ratatui::layout::Rect;
+ /// # use ratatui::Terminal;
+ /// # use ratatui::widgets::Widget as _;
+ /// # use ratatui::backend::CrosstermBackend;
+ /// # use tui_textarea::TextArea;
+ /// #
+ /// # let backend = CrosstermBackend::new(std::io::stdout());
+ /// # let mut term = Terminal::new(backend).unwrap();
+ /// # let textarea = TextArea::default();
+ /// #
+ /// # #[allow(deprecated)]
+ /// # term.draw(|f| {
+ /// # let rect = Rect {
+ /// # x: 0,
+ /// # y: 0,
+ /// # width: 24,
+ /// # height: 8,
+ /// # };
+ /// // v0.5.2 or earlier
+ /// f.render_widget(textarea.widget(), rect);
///
- /// let mut textarea = TextArea::default();
- ///
- /// let layout = Layout::default()
- /// .direction(Direction::Vertical)
- /// .constraints([Constraint::Min(1)].as_ref());
- /// let backend = CrosstermBackend::new(std::io::stdout());
- /// let mut term = Terminal::new(backend).unwrap();
- ///
- /// loop {
- /// term.draw(|f| {
- /// let chunks = layout.split(f.size());
- /// let widget = textarea.widget();
- /// f.render_widget(widget, chunks[0]);
- /// }).unwrap();
- ///
- /// // ...
- /// }
+ /// // v0.5.3 or later
+ /// f.render_widget(&textarea, rect);
+ /// # }).unwrap();
/// ```
+ #[deprecated(
+ since = "0.5.3",
+ note = "calling this method is no longer neccessary on rendering a textarea. pass &TextArea reference to `Frame::render_widget` method call directly"
+ )]
pub fn widget(&'a self) -> impl Widget + 'a {
- Renderer::new(self)
+ self
}
/// Set the style of textarea. By default, textarea is not styled.
@@ -2277,7 +2314,7 @@ impl<'a> TextArea<'a> {
/// ```
/// # use ratatui::buffer::Buffer;
/// # use ratatui::layout::Rect;
- /// # use ratatui::widgets::Widget;
+ /// # use ratatui::widgets::Widget as _;
/// use tui_textarea::TextArea;
///
/// // Let's say terminal height is 8.
@@ -2287,7 +2324,7 @@ impl<'a> TextArea<'a> {
/// # // Call `render` at least once to populate terminal size
/// # let r = Rect { x: 0, y: 0, width: 24, height: 8 };
/// # let mut b = Buffer::empty(r.clone());
- /// # textarea.widget().render(r, &mut b);
+ /// # textarea.render(r, &mut b);
///
/// // Scroll down by 15 lines. Since terminal height is 8, cursor will go out
/// // the viewport.
@@ -2330,7 +2367,7 @@ mod tests {
fn scroll() {
use crate::ratatui::buffer::Buffer;
use crate::ratatui::layout::Rect;
- use crate::ratatui::widgets::Widget;
+ use crate::ratatui::widgets::Widget as _;
let mut textarea: TextArea = (0..20).map(|i| i.to_string()).collect();
let r = Rect {
@@ -2340,7 +2377,7 @@ mod tests {
height: 8,
};
let mut b = Buffer::empty(r);
- textarea.widget().render(r, &mut b);
+ textarea.render(r, &mut b);
textarea.scroll((15, 0));
assert_eq!(textarea.cursor(), (15, 0));
diff --git a/src/widget.rs b/src/widget.rs
index c0d3862..0901e61 100644
--- a/src/widget.rs
+++ b/src/widget.rs
@@ -11,14 +11,14 @@ use std::sync::atomic::{AtomicU64, Ordering};
#[cfg(feature = "tuirs")]
use tui::text::Spans as Line;
-// &mut 'a (u16, u16, u16, u16) is not available since Renderer instance totally takes over the ownership of TextArea
+// &mut 'a (u16, u16, u16, u16) is not available since `render` method takes immutable reference of TextArea
// instance. In the case, the TextArea instance cannot be accessed from any other objects since it is mutablly
// borrowed.
//
-// `tui::terminal::Frame::render_stateful_widget` would be an assumed way to render a stateful widget. But at this
-// point we stick with using `tui::terminal::Frame::render_widget` because it is simpler API. Users don't need to
+// `ratatui::terminal::Frame::render_stateful_widget` would be an assumed way to render a stateful widget. But at this
+// point we stick with using `ratatui::terminal::Frame::render_widget` because it is simpler API. Users don't need to
// manage states of textarea instances separately.
-// https://docs.rs/tui/latest/tui/terminal/struct.Frame.html#method.render_stateful_widget
+// https://docs.rs/ratatui/latest/ratatui/terminal/struct.Frame.html#method.render_stateful_widget
#[derive(Default, Debug)]
pub struct Viewport(AtomicU64);
@@ -80,36 +80,30 @@ impl Viewport {
}
}
-pub struct Renderer<'a>(&'a TextArea<'a>);
-
-impl<'a> Renderer<'a> {
- pub fn new(textarea: &'a TextArea<'a>) -> Self {
- Self(textarea)
- }
-
+impl<'a> TextArea<'a> {
#[inline]
- fn text(&self, top_row: usize, height: usize) -> Text<'a> {
- let lines_len = self.0.lines().len();
+ fn text_widget(&'a self, top_row: usize, height: usize) -> Text<'a> {
+ let lines_len = self.lines().len();
let lnum_len = num_digits(lines_len);
let bottom_row = cmp::min(top_row + height, lines_len);
let mut lines = Vec::with_capacity(bottom_row - top_row);
- for (i, line) in self.0.lines()[top_row..bottom_row].iter().enumerate() {
- lines.push(self.0.line_spans(line.as_str(), top_row + i, lnum_len));
+ for (i, line) in self.lines()[top_row..bottom_row].iter().enumerate() {
+ lines.push(self.line_spans(line.as_str(), top_row + i, lnum_len));
}
Text::from(lines)
}
#[inline]
- fn placeholder_text(&self) -> Text<'a> {
- let cursor = Span::styled(" ", self.0.cursor_style);
- let text = Span::raw(self.0.placeholder.as_str());
+ fn placeholder_widget(&'a self) -> Text<'a> {
+ let cursor = Span::styled(" ", self.cursor_style);
+ let text = Span::raw(self.placeholder.as_str());
Text::from(Line::from(vec![cursor, text]))
}
}
-impl<'a> Widget for Renderer<'a> {
+impl Widget for &TextArea<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
- let Rect { width, height, .. } = if let Some(b) = self.0.block() {
+ let Rect { width, height, .. } = if let Some(b) = self.block() {
b.inner(area)
} else {
area
@@ -125,15 +119,15 @@ impl<'a> Widget for Renderer<'a> {
}
}
- let cursor = self.0.cursor();
- let (top_row, top_col) = self.0.viewport.scroll_top();
+ let cursor = self.cursor();
+ let (top_row, top_col) = self.viewport.scroll_top();
let top_row = next_scroll_top(top_row, cursor.0 as u16, height);
let top_col = next_scroll_top(top_col, cursor.1 as u16, width);
- let (text, style) = if !self.0.placeholder.is_empty() && self.0.is_empty() {
- (self.placeholder_text(), self.0.placeholder_style)
+ let (text, style) = if !self.placeholder.is_empty() && self.is_empty() {
+ (self.placeholder_widget(), self.placeholder_style)
} else {
- (self.text(top_row as usize, height as usize), self.0.style())
+ (self.text_widget(top_row as _, height as _), self.style())
};
// To get fine control over the text color and the surrrounding block they have to be rendered separately
@@ -141,8 +135,8 @@ impl<'a> Widget for Renderer<'a> {
let mut text_area = area;
let mut inner = Paragraph::new(text)
.style(style)
- .alignment(self.0.alignment());
- if let Some(b) = self.0.block() {
+ .alignment(self.alignment());
+ if let Some(b) = self.block() {
text_area = b.inner(area);
b.clone().render(area, buf)
}
@@ -151,7 +145,7 @@ impl<'a> Widget for Renderer<'a> {
}
// Store scroll top position for rendering on the next tick
- self.0.viewport.store(top_row, top_col, width, height);
+ self.viewport.store(top_row, top_col, width, height);
inner.render(text_area, buf);
}