Commit 5dc7fa19 authored by AdminXVII's avatar AdminXVII

Merge branch 'fix-borrow' into 'master'

Update to Rust 2018

See merge request !21
parents 75790748 8a760ac0
Pipeline #4891 passed with stage
in 2 minutes and 43 seconds
......@@ -11,6 +11,7 @@ exclude = [
"CONTRIBUTING.md",
".travis.yml",
]
edition = "2018"
[lib]
name = "liner"
......
......@@ -88,6 +88,12 @@ impl FromIterator<char> for Buffer {
}
}
impl Default for Buffer {
fn default() -> Self {
Self::new()
}
}
impl Buffer {
pub fn new() -> Self {
Buffer {
......@@ -210,17 +216,13 @@ impl Buffer {
pub fn remove(&mut self, start: usize, end: usize) -> usize {
let s = self.remove_raw(start, end);
let num_removed = s.len();
let act = Action::Remove {
start: start,
text: s,
};
self.push_action(act);
self.push_action(Action::Remove { start, text: s });
num_removed
}
pub fn insert(&mut self, start: usize, text: &[char]) {
let act = Action::Insert {
start: start,
start,
text: text.into(),
};
act.do_on(self);
......
......@@ -5,7 +5,7 @@ use termion::raw::IntoRawMode;
use super::*;
use keymap;
pub type ColorClosure = Box<Fn(&str) -> String>;
pub type ColorClosure = Box<dyn Fn(&str) -> String>;
/// The default for `Context.word_divider_fn`.
pub fn get_buffer_words(buf: &Buffer) -> Vec<(usize, usize)> {
......@@ -48,11 +48,17 @@ pub enum KeyBindings {
pub struct Context {
pub history: History,
pub word_divider_fn: Box<Fn(&Buffer) -> Vec<(usize, usize)>>,
pub word_divider_fn: Box<dyn Fn(&Buffer) -> Vec<(usize, usize)>>,
pub key_bindings: KeyBindings,
pub buf: String,
}
impl Default for Context {
fn default() -> Self {
Self::new()
}
}
impl Context {
pub fn new() -> Self {
Context {
......@@ -103,17 +109,15 @@ impl Context {
f: Option<ColorClosure>,
buffer: B,
) -> io::Result<String> {
let res = {
let mut stdout = stdout().into_raw_mode()?;
let mut ed = Editor::new_with_init_buffer(stdout, prompt, f, self, buffer)?;
match self.key_bindings {
let stdout = stdout().into_raw_mode()?;
let keybindings = self.key_bindings;
let ed = Editor::new_with_init_buffer(stdout, prompt, f, self, buffer)?;
match keybindings {
KeyBindings::Emacs => Self::handle_keys(keymap::Emacs::new(), ed, handler),
KeyBindings::Vi => Self::handle_keys(keymap::Vi::new(), ed, handler),
}
};
//self.revert_all_history();
res
}
fn handle_keys<'a, W: Write, M: KeyMap, C: Completer>(
......
......@@ -4,12 +4,12 @@ use std::io;
use termion::{self, clear, color, cursor};
use super::complete::Completer;
use context::ColorClosure;
use event::*;
use crate::context::ColorClosure;
use crate::event::*;
use crate::util;
use crate::Buffer;
use crate::Context;
use itertools::Itertools;
use util;
use Buffer;
use Context;
/// Represents the position of the cursor relative to words in the buffer.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
......@@ -158,13 +158,13 @@ impl<'a, W: io::Write> Editor<'a, W> {
let mut ed = Editor {
prompt: prompt.into(),
cursor: 0,
out: out,
out,
closure: f,
new_buf: buffer.into(),
hist_buf: Buffer::new(),
hist_buf_valid: false,
cur_history_loc: None,
context: context,
context,
show_completions_hint: None,
show_autosuggestions: true,
term_cursor_line: 1,
......@@ -264,7 +264,7 @@ impl<'a, W: io::Write> Editor<'a, W> {
fn refresh_search(&mut self, forward: bool) {
let search_history_loc = self.search_history_loc();
self.history_subset_index = self.context.history.search_index(&self.new_buf);
if self.history_subset_index.len() > 0 {
if !self.history_subset_index.is_empty() {
self.history_subset_loc = if forward {
Some(0)
} else {
......@@ -302,7 +302,7 @@ impl<'a, W: io::Write> Editor<'a, W> {
if !self.is_search() {
self.freshen_history();
self.refresh_search(forward);
} else if self.history_subset_index.len() > 0 {
} else if !self.history_subset_index.is_empty() {
self.history_subset_loc = if let Some(p) = self.history_subset_loc {
if forward {
if p < self.history_subset_index.len() - 1 {
......@@ -310,13 +310,11 @@ impl<'a, W: io::Write> Editor<'a, W> {
} else {
Some(0)
}
} else {
if p > 0 {
} else if p > 0 {
Some(p - 1)
} else {
Some(self.history_subset_index.len() - 1)
}
}
} else {
None
};
......@@ -381,7 +379,7 @@ impl<'a, W: io::Write> Editor<'a, W> {
let col_width = 2 + w as usize / cols;
let cols = max(1, w as usize / col_width);
let mut lines = completions.len() / cols;
let lines = completions.len() / cols;
let mut i = 0;
for (index, com) in completions.iter().enumerate() {
......@@ -562,7 +560,7 @@ impl<'a, W: io::Write> Editor<'a, W> {
None => {
self.history_subset_index =
self.context.history.get_history_subset(&self.new_buf);
if self.history_subset_index.len() > 0 {
if !self.history_subset_index.is_empty() {
self.history_subset_loc = Some(self.history_subset_index.len() - 1);
self.cur_history_loc = Some(
self.history_subset_index[self.history_subset_index.len() - 1],
......@@ -574,7 +572,7 @@ impl<'a, W: io::Write> Editor<'a, W> {
} else {
match self.cur_history_loc {
Some(i) if i > 0 => self.cur_history_loc = Some(i - 1),
None if self.context.history.len() > 0 => {
None if !self.context.history.is_empty() => {
self.cur_history_loc = Some(self.context.history.len() - 1)
}
_ => (),
......@@ -617,13 +615,13 @@ impl<'a, W: io::Write> Editor<'a, W> {
/// Moves to the start of history (ie. the earliest history entry).
pub fn move_to_start_of_history(&mut self) -> io::Result<()> {
self.hist_buf_valid = false;
if self.context.history.len() > 0 {
self.cur_history_loc = Some(0);
self.move_cursor_to_end_of_line()
} else {
if self.context.history.is_empty() {
self.cur_history_loc = None;
self.no_newline = true;
self.display()
} else {
self.cur_history_loc = Some(0);
self.move_cursor_to_end_of_line()
}
}
......@@ -863,13 +861,13 @@ impl<'a, W: io::Write> Editor<'a, W> {
fn search_prompt(&mut self) -> (String, usize) {
if self.is_search() {
// If we are searching override prompt to search prompt.
let (hplace, color) = if self.history_subset_index.len() > 0 {
let (hplace, color) = if self.history_subset_index.is_empty() {
(0, color::Red.fg_str())
} else {
(
self.history_subset_loc.unwrap_or(0) + 1,
color::Green.fg_str(),
)
} else {
(0, color::Red.fg_str())
};
(
format!(
......
use crate::Editor;
use std::io::Write;
use termion::event::Key;
use Editor;
pub struct Event<'a, 'out: 'a, W: Write + 'a> {
pub editor: &'a mut Editor<'out, W>,
......@@ -9,10 +9,7 @@ pub struct Event<'a, 'out: 'a, W: Write + 'a> {
impl<'a, 'out: 'a, W: Write + 'a> Event<'a, 'out, W> {
pub fn new(editor: &'a mut Editor<'out, W>, kind: EventKind) -> Self {
Event {
editor: editor,
kind: kind,
}
Event { editor, kind }
}
}
......
......@@ -41,6 +41,12 @@ pub struct History {
compaction_writes: usize,
}
impl Default for History {
fn default() -> Self {
Self::new()
}
}
impl History {
/// Create new History structure.
pub fn new() -> History {
......@@ -121,7 +127,7 @@ impl History {
Err(_) => break,
}
}
self.to_max_size();
self.truncate();
if !self.load_duplicates {
let mut tmp_buffers: Vec<Buffer> = Vec::with_capacity(self.buffers.len());
// Remove duplicates from loaded history if we do not want it.
......@@ -185,7 +191,7 @@ impl History {
let mut file = BufWriter::new(File::create(&path)?);
// Write the commands to the history file.
for command in buf.into_iter() {
let _ = file.write_all(&String::from(command).as_bytes());
let _ = file.write_all(&command.as_bytes());
let _ = file.write_all(b"\n");
}
}
......@@ -224,6 +230,11 @@ impl History {
self.buffers.len()
}
/// Is the history empty
pub fn is_empty(&self) -> bool {
self.buffers.is_empty()
}
/// Add a command to the history buffer and remove the oldest commands when the max history
/// size has been met. If writing to the disk is enabled, this function will be used for
/// logging history to the designated history file.
......@@ -301,8 +312,7 @@ impl History {
I: Iterator<Item = usize>,
{
vals.filter_map(|i| self.buffers.get(i).map(|t| (i, t)))
.filter(|(_i, tested)| tested.starts_with(search_term))
.next()
.find(|(_i, tested)| tested.starts_with(search_term))
.map(|(i, _)| i)
}
......@@ -331,11 +341,10 @@ impl History {
if starts {
v.push(*i);
}
if contains && !starts && tested != search_term {
return true;
}
contains && !starts && tested != search_term
} else {
false
}
return false;
})
.collect();
ret.append(&mut v);
......@@ -356,7 +365,7 @@ impl History {
self.file_name.as_ref().map(|s| s.as_str())
}
fn to_max_size(&mut self) {
fn truncate(&mut self) {
// Find how many lines we need to move backwards
// in the file to remove all the old commands.
if self.buffers.len() >= self.max_file_size {
......@@ -368,7 +377,7 @@ impl History {
}
fn overwrite_history<P: AsRef<Path>>(&mut self, path: P) -> io::Result<String> {
self.to_max_size();
self.truncate();
let mut file = BufWriter::new(File::create(&path)?);
// Write the commands to the history file.
......
use std::io::{self, Write};
use termion::event::Key;
use CursorPosition;
use Editor;
use KeyMap;
use crate::CursorPosition;
use crate::Editor;
use crate::KeyMap;
/// Emacs keybindings for `Editor`. This is the default for `Context::read_line()`.
///
......@@ -61,7 +61,7 @@ impl Emacs {
fn handle_last_arg_fetch<'a, W: Write>(&mut self, ed: &mut Editor<'a, W>) -> io::Result<()> {
// Empty history means no last arg to fetch.
if ed.context().history.len() == 0 {
if ed.context().history.is_empty() {
return Ok(());
}
......@@ -171,12 +171,9 @@ fn emacs_move_word<W: Write>(ed: &mut Editor<W>, direction: EmacsMoveDir) -> io:
#[cfg(test)]
mod tests {
use super::*;
use crate::{Completer, Context, Editor, KeyMap};
use std::io::Write;
use termion::event::Key;
use Completer;
use Context;
use Editor;
use KeyMap;
fn simulate_keys<'a, 'b, W: Write, M: KeyMap, I>(
keymap: &mut M,
......
use super::complete::Completer;
use event::*;
use crate::complete::Completer;
use crate::event::*;
use crate::Editor;
use std::io::{self, ErrorKind, Write};
use termion::event::Key;
use Editor;
pub trait KeyMap: Default {
fn handle_key_core<'a, W: Write>(
......@@ -82,9 +82,9 @@ pub use emacs::Emacs;
#[cfg(test)]
mod tests {
use super::*;
use crate::Context;
use std::io::ErrorKind;
use termion::event::Key::*;
use Context;
#[derive(Default)]
struct TestKeyMap;
......
......@@ -2,8 +2,9 @@ use std::io::{self, Write};
use std::{cmp, mem};
use termion::event::Key;
use Editor;
use KeyMap;
use crate::buffer::Buffer;
use crate::Editor;
use crate::KeyMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum CharMovement {
......@@ -281,7 +282,7 @@ fn vi_move_word_end<W: Write>(
ed.move_cursor_to(cursor)
}
fn find_char(buf: &::buffer::Buffer, start: usize, ch: char, count: usize) -> Option<usize> {
fn find_char(buf: &Buffer, start: usize, ch: char, count: usize) -> Option<usize> {
assert!(count > 0);
buf.chars()
.enumerate()
......@@ -291,7 +292,7 @@ fn find_char(buf: &::buffer::Buffer, start: usize, ch: char, count: usize) -> Op
.map(|(i, _)| i)
}
fn find_char_rev(buf: &::buffer::Buffer, start: usize, ch: char, count: usize) -> Option<usize> {
fn find_char_rev(buf: &Buffer, start: usize, ch: char, count: usize) -> Option<usize> {
assert!(count > 0);
let rstart = buf.num_chars() - start;
buf.chars()
......@@ -393,8 +394,7 @@ impl Vi {
ed.no_eol = self.mode() == Mode::Normal;
self.movement_reset = self.mode() != Mode::Insert;
match last_mode {
Delete(start_pos) => {
if let Delete(start_pos) = last_mode {
// perform the delete operation
match move_type {
Exclusive => ed.delete_until(start_pos)?,
......@@ -410,8 +410,6 @@ impl Vi {
self.count = 0;
self.secondary_count = 0;
}
_ => {}
};
// in normal mode, count goes back to 0 after movement
if original_mode == Normal {
......@@ -759,7 +757,7 @@ impl Vi {
ed.move_cursor_to_start_of_line()?;
self.pop_mode_after_movement(Exclusive, ed)
}
Key::Char(i @ '0'...'9') => {
Key::Char(i @ '0'..='9') => {
let i = i.to_digit(10).unwrap();
// count = count * 10 + i
self.count = self.count.saturating_mul(10).saturating_add(i);
......@@ -898,7 +896,7 @@ impl Vi {
self.handle_key_normal(key, ed)
}
// handle numeric keys
(Key::Char('0'...'9'), _) => self.handle_key_normal(key, ed),
(Key::Char('0'..='9'), _) => self.handle_key_normal(key, ed),
(Key::Char('c'), Some(Key::Char('c'))) | (Key::Char('d'), None) => {
// updating the last command buffer doesn't really make sense in this context.
// Repeating 'dd' will simply erase and already erased line. Any other commands
......@@ -1062,14 +1060,10 @@ impl KeyMap for Vi {
#[cfg(test)]
mod tests {
use super::*;
use crate::{Buffer, Completer, Context, Editor, KeyMap};
use std::io::Write;
use termion::event::Key;
use termion::event::Key::*;
use Buffer;
use Completer;
use Context;
use Editor;
use KeyMap;
fn simulate_keys<'a, 'b, W: Write, M: KeyMap, I>(
keymap: &mut M,
......@@ -2701,7 +2695,7 @@ mod tests {
let out = Vec::new();
let mut ed = Editor::new(out, "prompt".to_owned(), None, &mut context).unwrap();
ed.insert_str_after_cursor("...").unwrap();
ed.insert_str_after_cursor("..=").unwrap();
let pos1 = ed.cursor();
ed.insert_str_after_cursor("word").unwrap();
let pos2 = ed.cursor();
......@@ -2723,9 +2717,9 @@ mod tests {
let out = Vec::new();
let mut ed = Editor::new(out, "prompt".to_owned(), None, &mut context).unwrap();
ed.insert_str_after_cursor("... ").unwrap();
ed.insert_str_after_cursor("..= ").unwrap();
let pos1 = ed.cursor();
ed.insert_str_after_cursor("...").unwrap();
ed.insert_str_after_cursor("..=").unwrap();
let pos2 = ed.cursor();
ed.insert_str_after_cursor("word").unwrap();
let pos3 = ed.cursor();
......@@ -2755,7 +2749,7 @@ mod tests {
let pos2 = ed.cursor();
ed.insert_str_after_cursor("some").unwrap();
let pos3 = ed.cursor();
ed.insert_str_after_cursor("... ").unwrap();
ed.insert_str_after_cursor("..= ").unwrap();
let pos4 = ed.cursor();
ed.insert_str_after_cursor("words").unwrap();
let pos5 = ed.cursor();
......@@ -2816,7 +2810,7 @@ mod tests {
let pos1 = ed.cursor();
ed.insert_str_after_cursor("some").unwrap();
let pos2 = ed.cursor();
ed.insert_str_after_cursor("... ").unwrap();
ed.insert_str_after_cursor("..= ").unwrap();
ed.insert_str_after_cursor("words").unwrap();
let pos3 = ed.cursor();
......
......@@ -66,14 +66,9 @@ pub fn remove_codes(input: &str) -> Cow<str> {
']' => s = AnsiState::Osc,
_ => s = AnsiState::Norm,
},
AnsiState::Csi => match c {
'A'...'Z' | 'a'...'z' => s = AnsiState::Norm,
AnsiState::Csi if c.is_ascii_alphabetic() => s = AnsiState::Norm,
AnsiState::Osc if c == '\x07' => s = AnsiState::Norm,
_ => (),
},
AnsiState::Osc => match c {
'\x07' => s = AnsiState::Norm,
_ => (),
},
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment