Skip to content

Commit

Permalink
Merge branch 'nushell:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
maxomatic458 authored Jan 18, 2024
2 parents 980f921 + 2f3eb3e commit e716386
Show file tree
Hide file tree
Showing 14 changed files with 1,338 additions and 367 deletions.
795 changes: 586 additions & 209 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ version = "0.28.0"
doctest = true

[dependencies]
arboard = { version = "3.3.0", optional = true, default-features = false, features = ["wayland-data-control"] }
chrono = { version = "0.4.19", default-features = false, features = [
"clock",
"serde",
] }
clipboard = { version = "0.5.0", optional = true }
crossbeam = { version = "0.8.2", optional = true }
crossterm = { version = "0.27.0", features = ["serde"] }
fd-lock = "3.0.3"
Expand All @@ -44,7 +44,7 @@ bashisms = []
external_printer = ["crossbeam"]
sqlite = ["rusqlite/bundled", "serde_json"]
sqlite-dynlib = ["rusqlite", "serde_json"]
system_clipboard = ["clipboard"]
system_clipboard = ["arboard"]

[[example]]
name = "cwd_aware_hinter"
Expand Down
10 changes: 5 additions & 5 deletions src/core_editor/clip_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,20 +76,20 @@ pub fn get_default_clipboard() -> LocalClipboard {
#[cfg(feature = "system_clipboard")]
mod system_clipboard {
use super::*;
use clipboard::{ClipboardContext, ClipboardProvider};
use arboard::Clipboard as Arboard;

/// Wrapper around [`clipboard`](https://docs.rs/clipboard) crate
///
/// Requires that the feature `system_clipboard` is enabled
pub struct SystemClipboard {
cb: ClipboardContext,
cb: Arboard,
local_copy: String,
mode: ClipboardMode,
}

impl SystemClipboard {
pub fn new() -> Self {
let cb = ClipboardProvider::new().unwrap();
let cb = Arboard::new().unwrap();
SystemClipboard {
cb,
local_copy: String::new(),
Expand All @@ -101,12 +101,12 @@ mod system_clipboard {
impl Clipboard for SystemClipboard {
fn set(&mut self, content: &str, mode: ClipboardMode) {
self.local_copy = content.to_owned();
let _ = self.cb.set_contents(content.to_owned());
let _ = self.cb.set_text(content);
self.mode = mode;
}

fn get(&mut self) -> (String, ClipboardMode) {
let system_content = self.cb.get_contents().unwrap_or_default();
let system_content = self.cb.get_text().unwrap_or_default();
if system_content == self.local_copy {
// We assume the content was yanked inside the line editor and the last yank determined the mode.
(system_content, self.mode)
Expand Down
231 changes: 194 additions & 37 deletions src/core_editor/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use crate::{core_editor::get_default_clipboard, EditCommand};
pub struct Editor {
line_buffer: LineBuffer,
cut_buffer: Box<dyn Clipboard>,

edit_stack: EditStack<LineBuffer>,
last_undo_behavior: UndoBehavior,
selection_anchor: Option<usize>,
}

impl Default for Editor {
Expand All @@ -21,6 +21,7 @@ impl Default for Editor {
cut_buffer: Box::new(get_default_clipboard()),
edit_stack: EditStack::new(),
last_undo_behavior: UndoBehavior::CreateUndoPoint,
selection_anchor: None,
}
}
}
Expand All @@ -40,28 +41,32 @@ impl Editor {

pub(crate) fn run_edit_command(&mut self, command: &EditCommand) {
match command {
EditCommand::MoveToStart => self.line_buffer.move_to_start(),
EditCommand::MoveToLineStart => self.line_buffer.move_to_line_start(),
EditCommand::MoveToEnd => self.line_buffer.move_to_end(),
EditCommand::MoveToLineEnd => self.line_buffer.move_to_line_end(),
EditCommand::MoveToPosition(pos) => self.line_buffer.set_insertion_point(*pos),
EditCommand::MoveLeft => self.line_buffer.move_left(),
EditCommand::MoveRight => self.line_buffer.move_right(),
EditCommand::MoveWordLeft => self.line_buffer.move_word_left(),
EditCommand::MoveBigWordLeft => self.line_buffer.move_big_word_left(),
EditCommand::MoveWordRight => self.line_buffer.move_word_right(),
EditCommand::MoveWordRightStart => self.line_buffer.move_word_right_start(),
EditCommand::MoveBigWordRightStart => self.line_buffer.move_big_word_right_start(),
EditCommand::MoveWordRightEnd => self.line_buffer.move_word_right_end(),
EditCommand::MoveBigWordRightEnd => self.line_buffer.move_big_word_right_end(),
EditCommand::InsertChar(c) => self.line_buffer.insert_char(*c),
EditCommand::MoveToStart { select } => self.move_to_start(*select),
EditCommand::MoveToLineStart { select } => self.move_to_line_start(*select),
EditCommand::MoveToEnd { select } => self.move_to_end(*select),
EditCommand::MoveToLineEnd { select } => self.move_to_line_end(*select),
EditCommand::MoveToPosition { position, select } => {
self.move_to_position(*position, *select)
}
EditCommand::MoveLeft { select } => self.move_left(*select),
EditCommand::MoveRight { select } => self.move_right(*select),
EditCommand::MoveWordLeft { select } => self.move_word_left(*select),
EditCommand::MoveBigWordLeft { select } => self.move_big_word_left(*select),
EditCommand::MoveWordRight { select } => self.move_word_right(*select),
EditCommand::MoveWordRightStart { select } => self.move_word_right_start(*select),
EditCommand::MoveBigWordRightStart { select } => {
self.move_big_word_right_start(*select)
}
EditCommand::MoveWordRightEnd { select } => self.move_word_right_end(*select),
EditCommand::MoveBigWordRightEnd { select } => self.move_big_word_right_end(*select),
EditCommand::InsertChar(c) => self.insert_char(*c),
EditCommand::Complete => {}
EditCommand::InsertString(str) => self.line_buffer.insert_str(str),
EditCommand::InsertNewline => self.line_buffer.insert_newline(),
EditCommand::InsertString(str) => self.insert_str(str),
EditCommand::InsertNewline => self.insert_newline(),
EditCommand::ReplaceChar(chr) => self.replace_char(*chr),
EditCommand::ReplaceChars(n_chars, str) => self.replace_chars(*n_chars, str),
EditCommand::Backspace => self.line_buffer.delete_left_grapheme(),
EditCommand::Delete => self.line_buffer.delete_right_grapheme(),
EditCommand::Backspace => self.backspace(),
EditCommand::Delete => self.delete(),
EditCommand::CutChar => self.cut_char(),
EditCommand::BackspaceWord => self.line_buffer.delete_word_left(),
EditCommand::DeleteWord => self.line_buffer.delete_word_right(),
Expand Down Expand Up @@ -90,16 +95,31 @@ impl Editor {
EditCommand::Redo => self.redo(),
EditCommand::CutRightUntil(c) => self.cut_right_until_char(*c, false, true),
EditCommand::CutRightBefore(c) => self.cut_right_until_char(*c, true, true),
EditCommand::MoveRightUntil(c) => self.move_right_until_char(*c, false, true),
EditCommand::MoveRightBefore(c) => self.move_right_until_char(*c, true, true),
EditCommand::MoveRightUntil { c, select } => {
self.move_right_until_char(*c, false, true, *select)
}
EditCommand::MoveRightBefore { c, select } => {
self.move_right_until_char(*c, true, true, *select)
}
EditCommand::CutLeftUntil(c) => self.cut_left_until_char(*c, false, true),
EditCommand::CutLeftBefore(c) => self.cut_left_until_char(*c, true, true),
EditCommand::MoveLeftUntil(c) => self.move_left_until_char(*c, false, true),
EditCommand::MoveLeftBefore(c) => self.move_left_until_char(*c, true, true),
EditCommand::MoveLeftUntil { c, select } => {
self.move_left_until_char(*c, false, true, *select)
}
EditCommand::MoveLeftBefore { c, select } => {
self.move_left_until_char(*c, true, true, *select)
}
EditCommand::SelectAll => self.select_all(),
EditCommand::CutSelection => self.cut_selection(),
EditCommand::CopySelection => self.copy_selection(),
}
if !matches!(command.edit_type(), EditType::MoveCursor { select: true }) {
self.selection_anchor = None;
}
if let EditType::MoveCursor { select: true } = command.edit_type() {}

let new_undo_behavior = match (command, command.edit_type()) {
(_, EditType::MoveCursor) => UndoBehavior::MoveCursor,
(_, EditType::MoveCursor { .. }) => UndoBehavior::MoveCursor,
(EditCommand::InsertChar(c), EditType::EditText) => UndoBehavior::InsertCharacter(*c),
(EditCommand::Delete, EditType::EditText) => {
let deleted_char = self.edit_stack.current().grapheme_right().chars().next();
Expand All @@ -112,8 +132,21 @@ impl Editor {
(_, EditType::UndoRedo) => UndoBehavior::UndoRedo,
(_, _) => UndoBehavior::CreateUndoPoint,
};

self.update_undo_state(new_undo_behavior);
}
fn update_selection_anchor(&mut self, select: bool) {
self.selection_anchor = if select {
self.selection_anchor
.or_else(|| Some(self.insertion_point()))
} else {
None
};
}
fn move_to_position(&mut self, position: usize, select: bool) {
self.update_selection_anchor(select);
self.line_buffer.set_insertion_point(position)
}

pub(crate) fn move_line_up(&mut self) {
self.line_buffer.move_line_up();
Expand Down Expand Up @@ -170,25 +203,24 @@ impl Editor {
self.edit_stack.reset();
}

pub(crate) fn move_to_start(&mut self, undo_behavior: UndoBehavior) {
pub(crate) fn move_to_start(&mut self, select: bool) {
self.update_selection_anchor(select);
self.line_buffer.move_to_start();
self.update_undo_state(undo_behavior);
}

pub(crate) fn move_to_end(&mut self, undo_behavior: UndoBehavior) {
pub(crate) fn move_to_end(&mut self, select: bool) {
self.update_selection_anchor(select);
self.line_buffer.move_to_end();
self.update_undo_state(undo_behavior);
}

#[allow(dead_code)]
pub(crate) fn move_to_line_start(&mut self, undo_behavior: UndoBehavior) {
pub(crate) fn move_to_line_start(&mut self, select: bool) {
self.update_selection_anchor(select);
self.line_buffer.move_to_line_start();
self.update_undo_state(undo_behavior);
}

pub(crate) fn move_to_line_end(&mut self, undo_behavior: UndoBehavior) {
pub(crate) fn move_to_line_end(&mut self, select: bool) {
self.update_selection_anchor(select);
self.line_buffer.move_to_line_end();
self.update_undo_state(undo_behavior);
}

fn undo(&mut self) {
Expand All @@ -201,7 +233,7 @@ impl Editor {
self.line_buffer = val.clone();
}

fn update_undo_state(&mut self, undo_behavior: UndoBehavior) {
pub(crate) fn update_undo_state(&mut self, undo_behavior: UndoBehavior) {
if matches!(undo_behavior, UndoBehavior::UndoRedo) {
self.last_undo_behavior = UndoBehavior::UndoRedo;
return;
Expand Down Expand Up @@ -357,6 +389,7 @@ impl Editor {
}

fn insert_cut_buffer_before(&mut self) {
self.delete_selection();
match self.cut_buffer.get() {
(content, ClipboardMode::Normal) => {
self.line_buffer.insert_str(&content);
Expand All @@ -375,6 +408,7 @@ impl Editor {
}

fn insert_cut_buffer_after(&mut self) {
self.delete_selection();
match self.cut_buffer.get() {
(content, ClipboardMode::Normal) => {
self.line_buffer.move_right();
Expand All @@ -393,15 +427,29 @@ impl Editor {
}
}

fn move_right_until_char(&mut self, c: char, before_char: bool, current_line: bool) {
fn move_right_until_char(
&mut self,
c: char,
before_char: bool,
current_line: bool,
select: bool,
) {
self.update_selection_anchor(select);
if before_char {
self.line_buffer.move_right_before(c, current_line);
} else {
self.line_buffer.move_right_until(c, current_line);
}
}

fn move_left_until_char(&mut self, c: char, before_char: bool, current_line: bool) {
fn move_left_until_char(
&mut self,
c: char,
before_char: bool,
current_line: bool,
select: bool,
) {
self.update_selection_anchor(select);
if before_char {
self.line_buffer.move_left_before(c, current_line);
} else {
Expand Down Expand Up @@ -462,6 +510,115 @@ impl Editor {

self.line_buffer.insert_str(string);
}

fn move_left(&mut self, select: bool) {
self.update_selection_anchor(select);
self.line_buffer.move_left();
}

fn move_right(&mut self, select: bool) {
self.update_selection_anchor(select);
self.line_buffer.move_right();
}

fn select_all(&mut self) {
self.selection_anchor = Some(0);
self.line_buffer.move_to_end();
}

fn cut_selection(&mut self) {
if let Some((start, end)) = self.get_selection() {
let cut_slice = &self.line_buffer.get_buffer()[start..end];
self.cut_buffer.set(cut_slice, ClipboardMode::Normal);
self.line_buffer.clear_range_safe(start, end);
self.selection_anchor = None;
}
}

fn copy_selection(&mut self) {
if let Some((start, end)) = self.get_selection() {
let cut_slice = &self.line_buffer.get_buffer()[start..end];
self.cut_buffer.set(cut_slice, ClipboardMode::Normal);
}
}

/// If a selection is active returns the selected range, otherwise None.
/// The range is guaranteed to be ascending.
pub fn get_selection(&self) -> Option<(usize, usize)> {
self.selection_anchor.map(|selection_anchor| {
if self.insertion_point() > selection_anchor {
(selection_anchor, self.insertion_point())
} else {
(self.insertion_point(), selection_anchor)
}
})
}

fn delete_selection(&mut self) {
if let Some((start, end)) = self.get_selection() {
self.line_buffer.clear_range_safe(start, end);
self.selection_anchor = None;
}
}

fn backspace(&mut self) {
if self.selection_anchor.is_some() {
self.delete_selection();
} else {
self.line_buffer.delete_left_grapheme();
}
}

fn delete(&mut self) {
if self.selection_anchor.is_some() {
self.delete_selection();
} else {
self.line_buffer.delete_right_grapheme();
}
}

fn move_word_left(&mut self, select: bool) {
self.move_to_position(self.line_buffer.word_left_index(), select);
}

fn move_big_word_left(&mut self, select: bool) {
self.move_to_position(self.line_buffer.big_word_left_index(), select);
}

fn move_word_right(&mut self, select: bool) {
self.move_to_position(self.line_buffer.word_right_index(), select);
}

fn move_word_right_start(&mut self, select: bool) {
self.move_to_position(self.line_buffer.word_right_start_index(), select);
}

fn move_big_word_right_start(&mut self, select: bool) {
self.move_to_position(self.line_buffer.big_word_right_start_index(), select);
}

fn move_word_right_end(&mut self, select: bool) {
self.move_to_position(self.line_buffer.word_right_end_index(), select);
}

fn move_big_word_right_end(&mut self, select: bool) {
self.move_to_position(self.line_buffer.big_word_right_end_index(), select);
}

fn insert_char(&mut self, c: char) {
self.delete_selection();
self.line_buffer.insert_char(c);
}

fn insert_str(&mut self, str: &str) {
self.delete_selection();
self.line_buffer.insert_str(str);
}

fn insert_newline(&mut self) {
self.delete_selection();
self.line_buffer.insert_newline();
}
}

#[cfg(test)]
Expand Down
Loading

0 comments on commit e716386

Please sign in to comment.