зеркало из
https://github.com/glebtv/tui-textarea.git
synced 2026-09-03 14:26:17 +03:00
implement Scrolling enum to specify scrolling more flexibly
this is a breaking change. next release should be v0.2.0.
Этот коммит содержится в:
@@ -415,7 +415,7 @@ notify how to move the cursor.
|
||||
| `textarea.set_search_pattern(pattern)` | Set a pattern for text search |
|
||||
| `textarea.search_forward(match_cursor)` | Move cursor to next match of text search |
|
||||
| `textarea.search_back(match_cursor)` | Move cursor to previous match of text search |
|
||||
| `textarea.scroll(rows, cols)` | Scroll the viewport |
|
||||
| `textarea.scroll(scrolling)` | Scroll the viewport |
|
||||
|
||||
To define your own key mappings, simply call the above methods in your code instead of `TextArea::input()` method. The
|
||||
following example defines modal key mappings like Vim.
|
||||
@@ -468,8 +468,8 @@ loop {
|
||||
Input { key: Key::Esc, .. } => textarea.set_search_pattern("").unwrap(),
|
||||
Input { key: Key::Char('n'), .. } => textarea.search_forward(),
|
||||
Input { key: Key::Char('N'), .. } => textarea.search_back(),
|
||||
Input { key: Key::Char('e'), ctrl: true .. } => textarea.scroll(1, 0),
|
||||
Input { key: Key::Char('y'), ctrl: true .. } => textarea.scroll(-1, 0),
|
||||
Input { key: Key::Char('e'), ctrl: true .. } => textarea.scroll((1, 0)),
|
||||
Input { key: Key::Char('y'), ctrl: true .. } => textarea.scroll((-1, 0)),
|
||||
_ => {},
|
||||
},
|
||||
Mode::Insert => match read()?.into() {
|
||||
|
||||
@@ -4,8 +4,9 @@ use crate::word::{find_word_start_backward, find_word_start_forward};
|
||||
use arbitrary::Arbitrary;
|
||||
use std::cmp;
|
||||
|
||||
/// Specify how to move the cursor. This type is marked as `#[non_exhaustive]` since more variations may be supported in the
|
||||
/// future.
|
||||
/// Specify how to move the cursor.
|
||||
///
|
||||
/// This type is marked as `#[non_exhaustive]` since more variations may be supported in the future.
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
|
||||
|
||||
@@ -8,7 +8,9 @@ use crossterm::event::{
|
||||
#[cfg(feature = "termion")]
|
||||
use termion::event::{Event as TermionEvent, Key as TermionKey, MouseEvent as TermionMouseEvent};
|
||||
|
||||
/// Backend-agnostic key input kind. This type is marked as `#[non_exhaustive]` since more keys may be supported in the future.
|
||||
/// Backend-agnostic key input kind.
|
||||
///
|
||||
/// This type is marked as `#[non_exhaustive]` since more keys may be supported in the future.
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
|
||||
|
||||
@@ -17,4 +17,4 @@ mod word;
|
||||
|
||||
pub use cursor::CursorMove;
|
||||
pub use input::{Input, Key};
|
||||
pub use textarea::TextArea;
|
||||
pub use textarea::{Scrolling, TextArea};
|
||||
|
||||
@@ -12,6 +12,57 @@ use tui::style::{Modifier, Style};
|
||||
use tui::text::Spans;
|
||||
use tui::widgets::{Block, Widget};
|
||||
|
||||
/// Specify how to scroll the textarea.
|
||||
///
|
||||
/// This type is marked as `#[non_exhaustive]` since more variations may be supported in the future. Note that the cursor will
|
||||
/// not move until it goes out the viewport. See also: [`TextArea::scroll`]
|
||||
#[non_exhaustive]
|
||||
pub enum Scrolling {
|
||||
/// Scroll the textarea by rows (vertically) and columns (horizontally). Passing positive scroll amounts to `rows` and `cols`
|
||||
/// scolls it to down and right. Negative integers means the opposite directions. `(i16, i16)` pair can be converted into
|
||||
/// `Scrolling::Delta` where 1st element means rows and 2nd means columns.
|
||||
///
|
||||
/// ```
|
||||
/// # use tui::buffer::Buffer;
|
||||
/// # use tui::layout::Rect;
|
||||
/// # use tui::widgets::Widget;
|
||||
/// use tui_textarea::{TextArea, Scrolling};
|
||||
///
|
||||
/// // Let's say terminal height is 8.
|
||||
///
|
||||
/// // Create textarea with 20 lines "0", "1", "2", "3", ...
|
||||
/// let mut textarea: TextArea = (0..20).into_iter().map(|i| i.to_string()).collect();
|
||||
/// # // 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);
|
||||
///
|
||||
/// // Scroll down by 2 lines.
|
||||
/// textarea.scroll(Scrolling::Delta{rows: 2, cols: 0});
|
||||
/// assert_eq!(textarea.cursor(), (2, 0));
|
||||
///
|
||||
/// // (1, 0) is converted into Scrolling::Delta{rows: 1, cols: 0}
|
||||
/// textarea.scroll((1, 0));
|
||||
/// assert_eq!(textarea.cursor(), (3, 0));
|
||||
/// ```
|
||||
Delta { rows: i16, cols: i16 },
|
||||
}
|
||||
|
||||
impl Scrolling {
|
||||
fn scroll(self, viewport: &mut Viewport) {
|
||||
let (rows, cols) = match self {
|
||||
Self::Delta { rows, cols } => (rows, cols),
|
||||
};
|
||||
viewport.scroll(rows, cols);
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(i16, i16)> for Scrolling {
|
||||
fn from((rows, cols): (i16, i16)) -> Self {
|
||||
Self::Delta { rows, cols }
|
||||
}
|
||||
}
|
||||
|
||||
/// A type to manage state of textarea.
|
||||
///
|
||||
/// [`TextArea::default`] creates an empty textarea. [`TextArea::new`] creates a textarea with given text lines.
|
||||
@@ -448,14 +499,14 @@ impl<'a> TextArea<'a> {
|
||||
key: Key::MouseScrollDown,
|
||||
..
|
||||
} => {
|
||||
self.scroll(1, 0);
|
||||
self.scroll((1, 0));
|
||||
false
|
||||
}
|
||||
Input {
|
||||
key: Key::MouseScrollUp,
|
||||
..
|
||||
} => {
|
||||
self.scroll(-1, 0);
|
||||
self.scroll((-1, 0));
|
||||
false
|
||||
}
|
||||
_ => false,
|
||||
@@ -527,14 +578,14 @@ impl<'a> TextArea<'a> {
|
||||
key: Key::MouseScrollDown,
|
||||
..
|
||||
} => {
|
||||
self.scroll(1, 0);
|
||||
self.scroll((1, 0));
|
||||
false
|
||||
}
|
||||
Input {
|
||||
key: Key::MouseScrollUp,
|
||||
..
|
||||
} => {
|
||||
self.scroll(-1, 0);
|
||||
self.scroll((-1, 0));
|
||||
false
|
||||
}
|
||||
_ => false,
|
||||
@@ -1527,10 +1578,9 @@ impl<'a> TextArea<'a> {
|
||||
self.search.style = style;
|
||||
}
|
||||
|
||||
/// Scroll the textarea by `rows` lines (vertically) and `cols` columns (horizontally). Positive scroll amount means
|
||||
/// scrolling down or right. And negative scroll amount means scrolling up or left. The cursor will not move until
|
||||
/// it goes out the viewport. When the cursor position is outside the viewport after scroll, the cursor position will
|
||||
/// be adjusted to stay in the viewport using the same logic as [`CursorMove::InViewport`].
|
||||
/// Scroll the textarea. See [`Scrolling`] for the argument.
|
||||
/// The cursor will not move until it goes out the viewport. When the cursor position is outside the viewport after scroll,
|
||||
/// the cursor position will be adjusted to stay in the viewport using the same logic as [`CursorMove::InViewport`].
|
||||
///
|
||||
/// ```
|
||||
/// # use tui::buffer::Buffer;
|
||||
@@ -1549,13 +1599,13 @@ impl<'a> TextArea<'a> {
|
||||
///
|
||||
/// // Scroll down by 15 lines. Since terminal height is 8, cursor will go out
|
||||
/// // the viewport.
|
||||
/// textarea.scroll(15, 0);
|
||||
/// textarea.scroll((15, 0));
|
||||
/// // So the cursor position was updated to stay in the viewport after the scrolling.
|
||||
/// assert_eq!(textarea.cursor(), (15, 0));
|
||||
///
|
||||
/// // Scroll up by 5 lines. Since the scroll amount is smaller than the terminal
|
||||
/// // height, cursor position will not be updated.
|
||||
/// textarea.scroll(-5, 0);
|
||||
/// textarea.scroll((-5, 0));
|
||||
/// assert_eq!(textarea.cursor(), (15, 0));
|
||||
///
|
||||
/// // Scroll up by 5 lines again. The terminal height is 8. So a cursor reaches to
|
||||
@@ -1563,11 +1613,11 @@ impl<'a> TextArea<'a> {
|
||||
/// // scrolled up by 5 lines, scrolling up by 5 lines again makes the cursor overrun
|
||||
/// // the viewport by 5 - 2 = 3 lines. To keep the cursor stay in the viewport, the
|
||||
/// // cursor position will be adjusted from line 15 to line 12.
|
||||
/// textarea.scroll(-5, 0);
|
||||
/// textarea.scroll((-5, 0));
|
||||
/// assert_eq!(textarea.cursor(), (12, 0));
|
||||
/// ```
|
||||
pub fn scroll(&mut self, rows: i16, cols: i16) {
|
||||
self.viewport.scroll(rows, cols);
|
||||
pub fn scroll(&mut self, scrolling: impl Into<Scrolling>) {
|
||||
scrolling.into().scroll(&mut self.viewport);
|
||||
self.move_cursor(CursorMove::InViewport);
|
||||
}
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user