Make Editor `Send`able and Sync`able` for gluon.
And reintroduce `set_completer`.
diff --git a/Cargo.toml b/Cargo.toml
index 7ef2aa4..52188d8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rustyline"
-version = "1.0.0"
+version = "2.0.0-alpha"
authors = ["Katsu Kawakami <kkawa1570@gmail.com>"]
description = "Rustyline, a readline implementation based on Antirez's Linenoise"
documentation = "http://docs.rs/rustyline"
diff --git a/src/keymap.rs b/src/keymap.rs
index 98e7f39..3652493 100644
--- a/src/keymap.rs
+++ b/src/keymap.rs
@@ -1,7 +1,6 @@
//! Bindings from keys to command for Emacs and Vi modes
-use std::cell::RefCell;
use std::collections::HashMap;
-use std::rc::Rc;
+use std::sync::{Arc, RwLock};
use super::Result;
use config::Config;
@@ -274,7 +273,7 @@
/// Tranform key(s) to commands based on current input mode
pub struct InputState {
mode: EditMode,
- custom_bindings: Rc<RefCell<HashMap<KeyPress, Cmd>>>,
+ custom_bindings: Arc<RwLock<HashMap<KeyPress, Cmd>>>,
input_mode: InputMode, // vi only ?
// numeric arguments: http://web.mit.edu/gnu/doc/html/rlman_1.html#SEC7
num_args: i16,
@@ -299,7 +298,7 @@
impl InputState {
pub fn new(
config: &Config,
- custom_bindings: Rc<RefCell<HashMap<KeyPress, Cmd>>>,
+ custom_bindings: Arc<RwLock<HashMap<KeyPress, Cmd>>>,
) -> InputState {
InputState {
mode: config.edit_mode(),
@@ -384,13 +383,16 @@
key = try!(self.emacs_digit_argument(rdr, wrt, digit));
}
let (n, positive) = self.emacs_num_args(); // consume them in all cases
- if let Some(cmd) = self.custom_bindings.borrow().get(&key) {
- debug!(target: "rustyline", "Custom command: {:?}", cmd);
- return Ok(if cmd.is_repeatable() {
- cmd.redo(Some(n), wrt)
- } else {
- cmd.clone()
- });
+ {
+ let bindings = self.custom_bindings.read().unwrap();
+ if let Some(cmd) = bindings.get(&key) {
+ debug!(target: "rustyline", "Custom command: {:?}", cmd);
+ return Ok(if cmd.is_repeatable() {
+ cmd.redo(Some(n), wrt)
+ } else {
+ cmd.clone()
+ });
+ }
}
let cmd = match key {
KeyPress::Char(c) => if positive {
@@ -501,17 +503,20 @@
}
let no_num_args = self.num_args == 0;
let n = self.vi_num_args(); // consume them in all cases
- if let Some(cmd) = self.custom_bindings.borrow().get(&key) {
- debug!(target: "rustyline", "Custom command: {:?}", cmd);
- return Ok(if cmd.is_repeatable() {
- if no_num_args {
- cmd.redo(None, wrt)
+ {
+ let bindings = self.custom_bindings.read().unwrap();
+ if let Some(cmd) = bindings.get(&key) {
+ debug!(target: "rustyline", "Custom command: {:?}", cmd);
+ return Ok(if cmd.is_repeatable() {
+ if no_num_args {
+ cmd.redo(None, wrt)
+ } else {
+ cmd.redo(Some(n), wrt)
+ }
} else {
- cmd.redo(Some(n), wrt)
- }
- } else {
- cmd.clone()
- });
+ cmd.clone()
+ });
+ }
}
let cmd = match key {
KeyPress::Char('$') |
@@ -666,13 +671,16 @@
fn vi_insert<R: RawReader>(&mut self, rdr: &mut R, wrt: &mut Refresher) -> Result<Cmd> {
let key = try!(rdr.next_key(false));
- if let Some(cmd) = self.custom_bindings.borrow().get(&key) {
- debug!(target: "rustyline", "Custom command: {:?}", cmd);
- return Ok(if cmd.is_repeatable() {
- cmd.redo(None, wrt)
- } else {
- cmd.clone()
- });
+ {
+ let bindings = self.custom_bindings.read().unwrap();
+ if let Some(cmd) = bindings.get(&key) {
+ debug!(target: "rustyline", "Custom command: {:?}", cmd);
+ return Ok(if cmd.is_repeatable() {
+ cmd.redo(None, wrt)
+ } else {
+ cmd.clone()
+ });
+ }
}
let cmd = match key {
KeyPress::Char(c) => if self.input_mode == InputMode::Replace {
diff --git a/src/lib.rs b/src/lib.rs
index cf8408c..3fb9a2a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -41,13 +41,12 @@
mod tty;
-use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;
use std::io::{self, Write};
use std::path::Path;
-use std::rc::Rc;
use std::result;
+use std::sync::{Arc, Mutex, RwLock};
use unicode_width::UnicodeWidthStr;
use tty::{RawMode, RawReader, Renderer, Term, Terminal};
@@ -350,9 +349,9 @@
let mut stdout = editor.term.create_writer();
- editor.reset_kill_ring();
+ editor.reset_kill_ring(); // TODO recreate a new kill ring vs Arc<Mutex<KillRing>>
let mut s = State::new(&mut stdout, prompt, editor.history.len(), hinter);
- let mut input_state = InputState::new(&editor.config, Rc::clone(&editor.custom_bindings));
+ let mut input_state = InputState::new(&editor.config, Arc::clone(&editor.custom_bindings));
s.line.set_delete_listener(editor.kill_ring.clone());
s.line.set_change_listener(s.changes.clone());
@@ -483,12 +482,14 @@
}
Cmd::Yank(n, anchor) => {
// retrieve (yank) last item killed
- if let Some(text) = editor.kill_ring.borrow_mut().yank() {
+ let mut kill_ring = editor.kill_ring.lock().unwrap();
+ if let Some(text) = kill_ring.yank() {
try!(s.edit_yank(&input_state, text, anchor, n))
}
}
Cmd::ViYankTo(ref mvt) => if let Some(text) = s.line.copy(mvt) {
- editor.kill_ring.borrow_mut().kill(&text, Mode::Append)
+ let mut kill_ring = editor.kill_ring.lock().unwrap();
+ kill_ring.kill(&text, Mode::Append)
},
// TODO CTRL-_ // undo
Cmd::AcceptLine => {
@@ -543,7 +544,8 @@
}
Cmd::YankPop => {
// yank-pop
- if let Some((yank_size, text)) = editor.kill_ring.borrow_mut().yank_pop() {
+ let mut kill_ring = editor.kill_ring.lock().unwrap();
+ if let Some((yank_size, text)) = kill_ring.yank_pop() {
try!(s.edit_yank_pop(yank_size, text))
}
}
@@ -653,9 +655,9 @@
term: Terminal,
history: History,
helper: Option<H>,
- kill_ring: Rc<RefCell<KillRing>>,
+ kill_ring: Arc<Mutex<KillRing>>,
config: Config,
- custom_bindings: Rc<RefCell<HashMap<KeyPress, Cmd>>>,
+ custom_bindings: Arc<RwLock<HashMap<KeyPress, Cmd>>>,
}
impl<H: Helper> Editor<H> {
@@ -671,9 +673,9 @@
term,
history: History::with_config(config),
helper: None,
- kill_ring: Rc::new(RefCell::new(KillRing::new(60))),
+ kill_ring: Arc::new(Mutex::new(KillRing::new(60))),
config,
- custom_bindings: Rc::new(RefCell::new(HashMap::new())),
+ custom_bindings: Arc::new(RwLock::new(HashMap::new())),
}
}
@@ -746,13 +748,20 @@
self.helper = helper;
}
+ #[deprecated(since = "2.0.0", note = "Use set_helper instead")]
+ pub fn set_completer(&mut self, completer: Option<H>) {
+ self.helper = completer;
+ }
+
/// Bind a sequence to a command.
pub fn bind_sequence(&mut self, key_seq: KeyPress, cmd: Cmd) -> Option<Cmd> {
- self.custom_bindings.borrow_mut().insert(key_seq, cmd)
+ let mut bindings = self.custom_bindings.write().unwrap();
+ bindings.insert(key_seq, cmd)
}
/// Remove a binding for the given sequence.
pub fn unbind_sequence(&mut self, key_seq: KeyPress) -> Option<Cmd> {
- self.custom_bindings.borrow_mut().remove(&key_seq)
+ let mut bindings = self.custom_bindings.write().unwrap();
+ bindings.remove(&key_seq)
}
/// ```
@@ -777,7 +786,8 @@
}
fn reset_kill_ring(&self) {
- self.kill_ring.borrow_mut().reset();
+ let mut kill_ring = self.kill_ring.lock().unwrap();
+ kill_ring.reset();
}
}
diff --git a/src/line_buffer.rs b/src/line_buffer.rs
index 31fd672..7c16bb1 100644
--- a/src/line_buffer.rs
+++ b/src/line_buffer.rs
@@ -6,6 +6,7 @@
use std::ops::{Deref, Index, Range};
use std::rc::Rc;
use std::string::Drain;
+use std::sync::{Arc, Mutex};
use unicode_segmentation::UnicodeSegmentation;
/// Maximum buffer size for the line read
@@ -52,7 +53,7 @@
pub struct LineBuffer {
buf: String, // Edited line buffer (rl_line_buffer)
pos: usize, // Current cursor position (byte position) (rl_point)
- dl: Option<Rc<RefCell<DeleteListener>>>,
+ dl: Option<Arc<Mutex<DeleteListener>>>,
cl: Option<Rc<RefCell<ChangeListener>>>,
}
@@ -85,7 +86,7 @@
lb
}
- pub fn set_delete_listener(&mut self, dl: Rc<RefCell<DeleteListener>>) {
+ pub fn set_delete_listener(&mut self, dl: Arc<Mutex<DeleteListener>>) {
self.dl = Some(dl);
}
pub fn remove_delete_listener(&mut self) {
@@ -678,7 +679,8 @@
fn drain(&mut self, range: Range<usize>, dir: Direction) -> Drain {
for dl in &self.dl {
- if let Ok(mut dl) = dl.try_borrow_mut() {
+ let mut lock = dl.try_lock();
+ if let Ok(mut dl) = lock {
dl.delete(range.start, &self.buf[range.start..range.end], dir);
}
}
@@ -768,7 +770,8 @@
};
if notify {
if let Some(dl) = self.dl.as_ref() {
- dl.borrow_mut().start_killing()
+ let mut dl = dl.lock().unwrap();
+ dl.start_killing()
}
}
let killed = match *mvt {
@@ -807,7 +810,8 @@
};
if notify {
if let Some(dl) = self.dl.as_ref() {
- dl.borrow_mut().stop_killing()
+ let mut dl = dl.lock().unwrap();
+ dl.stop_killing()
}
}
killed
diff --git a/src/test/mod.rs b/src/test/mod.rs
index 6732e08..d3216de 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -1,6 +1,5 @@
-use std::cell::RefCell;
use std::collections::HashMap;
-use std::rc::Rc;
+use std::sync::{Arc, RwLock};
use super::{Editor, Result};
use completion::Completer;
@@ -35,7 +34,7 @@
let mut out = Sink::new();
let mut s = init_state(&mut out, "rus", 3);
let config = Config::default();
- let mut input_state = InputState::new(&config, Rc::new(RefCell::new(HashMap::new())));
+ let mut input_state = InputState::new(&config, Arc::new(RwLock::new(HashMap::new())));
let keys = &[KeyPress::Enter];
let mut rdr = keys.iter();
let completer = SimpleCompleter;