Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

implement select #45

Merged
merged 7 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ impl<'a> Editor<'a> {
key: Key::Char('g' | 'n'),
ctrl: true,
alt: false,
..
}
| Input { key: Key::Down, .. } => {
if !textarea.search_forward(false) {
Expand All @@ -275,11 +276,13 @@ impl<'a> Editor<'a> {
key: Key::Char('g'),
ctrl: false,
alt: true,
..
}
| Input {
key: Key::Char('p'),
ctrl: true,
alt: false,
..
}
| Input { key: Key::Up, .. } => {
if !textarea.search_back(false) {
Expand Down
3 changes: 3 additions & 0 deletions examples/tuirs_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ impl<'a> Editor<'a> {
key: Key::Char('g' | 'n'),
ctrl: true,
alt: false,
..
}
| Input { key: Key::Down, .. } => {
if !textarea.search_forward(false) {
Expand All @@ -277,11 +278,13 @@ impl<'a> Editor<'a> {
key: Key::Char('g'),
ctrl: false,
alt: true,
..
}
| Input {
key: Key::Char('p'),
ctrl: true,
alt: false,
..
}
| Input { key: Key::Up, .. } => {
if !textarea.search_back(false) {
Expand Down
40 changes: 33 additions & 7 deletions src/highlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,23 @@ use std::iter;
use tui::text::Spans as Line;
use unicode_width::UnicodeWidthChar as _;

#[derive(Debug)]
enum Boundary {
Cursor(Style),
#[cfg(feature = "search")]
Search(Style),
Select(Style),
End,
}

impl Boundary {
fn cmp(&self, other: &Boundary) -> Ordering {
fn rank(b: &Boundary) -> u8 {
match b {
Boundary::Cursor(_) => 2,
Boundary::Cursor(_) => 3,
#[cfg(feature = "search")]
Boundary::Search(_) => 1,
Boundary::Select(_) => 2,
Boundary::End => 0,
}
}
Expand All @@ -36,6 +39,7 @@ impl Boundary {
#[cfg(feature = "search")]
Boundary::Search(s) => Some(*s),
Boundary::End => None,
Boundary::Select(s) => Some(*s),
}
}
}
Expand Down Expand Up @@ -100,10 +104,17 @@ pub struct LineHighlighter<'a> {
cursor_style: Style,
tab_len: u8,
mask: Option<char>,
select_style: Style,
}

impl<'a> LineHighlighter<'a> {
pub fn new(line: &'a str, cursor_style: Style, tab_len: u8, mask: Option<char>) -> Self {
pub fn new(
line: &'a str,
cursor_style: Style,
tab_len: u8,
mask: Option<char>,
select_style: Style,
) -> Self {
Self {
line,
spans: vec![],
Expand All @@ -113,6 +124,7 @@ impl<'a> LineHighlighter<'a> {
cursor_style,
tab_len,
mask,
select_style,
}
}

Expand All @@ -122,6 +134,11 @@ impl<'a> LineHighlighter<'a> {
.push(Span::styled(format!("{}{} ", pad, row + 1), style));
}

pub fn select(&mut self, start: usize, end: usize, style: Style) {
self.boundaries.push((Boundary::Select(style), start));
self.boundaries.push((Boundary::End, end));
}

pub fn cursor_line(&mut self, cursor_col: usize, style: Style) {
if let Some((start, c)) = self.line.char_indices().nth(cursor_col) {
self.boundaries
Expand Down Expand Up @@ -153,6 +170,7 @@ impl<'a> LineHighlighter<'a> {
cursor_style,
cursor_at_end,
mask,
select_style,
} = self;
let mut builder = DisplayTextBuilder::new(tab_len, mask);

Expand All @@ -172,10 +190,18 @@ impl<'a> LineHighlighter<'a> {
let mut style = style_begin;
let mut start = 0;
let mut stack = vec![];

let mut dont_add_cursor = false;
for (next_boundary, end) in boundaries {
if start < end {
spans.push(Span::styled(builder.build(&line[start..end]), style));
// add extra select space at line end to indicate
// that the \n will be deleted / included
if end > line.chars().count() && style == select_style {
spans.push(Span::styled(builder.build(&line[start..end - 1]), style));
spans.push(Span::styled(" ", style));
dont_add_cursor = true;
} else {
spans.push(Span::styled(builder.build(&line[start..end]), style));
}
}

style = if let Some(s) = next_boundary.style() {
Expand All @@ -186,13 +212,13 @@ impl<'a> LineHighlighter<'a> {
};
start = end;
}

if start != line.len() {
if start < line.len() {
spans.push(Span::styled(builder.build(&line[start..]), style));
}
if cursor_at_end {
if cursor_at_end && !dont_add_cursor {
spans.push(Span::styled(" ", cursor_style));
}

Line::from(spans)
}
}
Expand Down
17 changes: 15 additions & 2 deletions src/input/crossterm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,15 @@ impl From<KeyEvent> for Input {

let ctrl = key.modifiers.contains(KeyModifiers::CONTROL);
let alt = key.modifiers.contains(KeyModifiers::ALT);
let shift = key.modifiers.contains(KeyModifiers::SHIFT);
let key = Key::from(key.code);

Self { key, ctrl, alt }
Self {
key,
ctrl,
alt,
shift,
}
}
}

Expand All @@ -72,7 +78,14 @@ impl From<MouseEvent> for Input {
let key = Key::from(mouse.kind);
let ctrl = mouse.modifiers.contains(KeyModifiers::CONTROL);
let alt = mouse.modifiers.contains(KeyModifiers::ALT);
Self { key, ctrl, alt }
let shift = mouse.modifiers.contains(KeyModifiers::SHIFT);

Self {
key,
ctrl,
alt,
shift,
}
}
}

Expand Down
11 changes: 9 additions & 2 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ impl Default for Key {
/// textarea.input(Input {
/// key: Key::Char('a'),
/// ctrl: true,
/// alt: false,
/// alt: false,shift:false
/// });
/// ```
#[derive(Debug, Clone, Default, PartialEq, Hash)]
Expand All @@ -102,6 +102,8 @@ pub struct Input {
pub ctrl: bool,
/// Alt modifier key. `true` means Alt key was pressed.
pub alt: bool,
// Shift key. `true` means Shift key was pressed.
pub shift: bool,
}

#[cfg(test)]
Expand All @@ -110,7 +112,12 @@ mod tests {

#[allow(dead_code)]
pub(crate) fn input(key: Key, ctrl: bool, alt: bool) -> Input {
Input { key, ctrl, alt }
Input {
key,
ctrl,
alt,
shift: false,
}
}

#[test]
Expand Down
9 changes: 8 additions & 1 deletion src/input/termion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ impl From<KeyEvent> for Input {
fn from(key: KeyEvent) -> Self {
let mut ctrl = false;
let mut alt = false;
let shift = false;
let key = match key {
KeyEvent::Char('\n' | '\r') => Key::Enter,
KeyEvent::Char(c) => Key::Char(c),
Expand Down Expand Up @@ -44,7 +45,12 @@ impl From<KeyEvent> for Input {
_ => Key::Null,
};

Input { key, ctrl, alt }
Input {
key,
ctrl,
alt,
shift,
}
}
}

Expand All @@ -71,6 +77,7 @@ impl From<MouseEvent> for Input {
key,
ctrl: false,
alt: false,
shift: false,
}
}
}
Expand Down
27 changes: 21 additions & 6 deletions src/input/termwiz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,13 @@ impl From<KeyEvent> for Input {
let key = Key::from(key);
let ctrl = modifiers.contains(Modifiers::CTRL);
let alt = modifiers.contains(Modifiers::ALT);

Self { key, ctrl, alt }
let shift = modifiers.contains(Modifiers::SHIFT);
Self {
key,
ctrl,
alt,
shift,
}
}
}

Expand Down Expand Up @@ -77,8 +82,13 @@ impl From<MouseEvent> for Input {
let key = Key::from(mouse_buttons);
let ctrl = modifiers.contains(Modifiers::CTRL);
let alt = modifiers.contains(Modifiers::ALT);

Self { key, ctrl, alt }
let shift = modifiers.contains(Modifiers::SHIFT);
Self {
key,
ctrl,
alt,
shift,
}
}
}

Expand All @@ -94,8 +104,13 @@ impl From<PixelMouseEvent> for Input {
let key = Key::from(mouse_buttons);
let ctrl = modifiers.contains(Modifiers::CTRL);
let alt = modifiers.contains(Modifiers::ALT);

Self { key, ctrl, alt }
let shift = modifiers.contains(Modifiers::SHIFT);
Self {
key,
ctrl,
alt,
shift,
}
}
}

Expand Down
Loading