Skip to content

Commit

Permalink
Merge pull request #38 from birkenfeld/stable
Browse files Browse the repository at this point in the history
Replace use of unstable features
  • Loading branch information
kkawakam committed Jun 3, 2016
2 parents 6f81925 + 47c5f25 commit 65f45a3
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 23 deletions.
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
language: rust
rust:
- nightly
- 1.9.0
- beta
- nightly
script:
- cargo build --verbose
- cargo test --verbose
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ license = "MIT"
libc = "0.2.7"
nix = "0.5.0"
unicode-width = "0.1.3"
encode_unicode = "0.1.3"
clippy = {version = "~0.0.58", optional = true}

[dev-dependencies]
Expand Down
106 changes: 106 additions & 0 deletions src/char_iter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//! An iterator over the `char`s of a reader.
//!
//! A copy of the unstable code from the stdlib's std::io::Read::chars.
use std::error;
use std::fmt;
use std::io;
use std::io::Read;
use std::str;

pub fn chars<R: Read>(read: R) -> Chars<R> where R: Sized {
Chars { inner: read }
}

// https://tools.ietf.org/html/rfc3629
static UTF8_CHAR_WIDTH: [u8; 256] = [
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBF
0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDF
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEF
4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF
];

/// Given a first byte, determine how many bytes are in this UTF-8 character
#[inline]
fn utf8_char_width(b: u8) -> usize {
return UTF8_CHAR_WIDTH[b as usize] as usize;
}

pub struct Chars<R> {
inner: R,
}

#[derive(Debug)]
pub enum CharsError {
NotUtf8,
Other(io::Error),
}

impl<R: Read> Iterator for Chars<R> {
type Item = Result<char, CharsError>;

fn next(&mut self) -> Option<Result<char, CharsError>> {
let mut buf = [0];
let first_byte = match self.inner.read(&mut buf) {
Ok(0) => return None,
Ok(..) => buf[0],
Err(e) => return Some(Err(CharsError::Other(e))),
};
let width = utf8_char_width(first_byte);
if width == 1 { return Some(Ok(first_byte as char)) }
if width == 0 { return Some(Err(CharsError::NotUtf8)) }
let mut buf = [first_byte, 0, 0, 0];
{
let mut start = 1;
while start < width {
match self.inner.read(&mut buf[start..width]) {
Ok(0) => return Some(Err(CharsError::NotUtf8)),
Ok(n) => start += n,
Err(e) => return Some(Err(CharsError::Other(e))),
}
}
}
Some(match str::from_utf8(&buf[..width]).ok() {
Some(s) => Ok(s.chars().next().unwrap()),
None => Err(CharsError::NotUtf8),
})
}
}

impl error::Error for CharsError {
fn description(&self) -> &str {
match *self {
CharsError::NotUtf8 => "invalid utf8 encoding",
CharsError::Other(ref e) => error::Error::description(e),
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
CharsError::NotUtf8 => None,
CharsError::Other(ref e) => e.cause(),
}
}
}

impl fmt::Display for CharsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CharsError::NotUtf8 => {
"byte stream did not contain valid utf8".fmt(f)
}
CharsError::Other(ref e) => e.fmt(f),
}
}
}
8 changes: 5 additions & 3 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use std::error;
use std::fmt;
use nix;

use char_iter;

/// The error type for Rustyline errors that can arise from
/// I/O related errors or Errno when using the nix-rust library
#[derive(Debug)]
Expand All @@ -13,7 +15,7 @@ pub enum ReadlineError {
/// Error from syscall
Errno(nix::Error),
/// Chars Error
Char(io::CharsError),
Char(char_iter::CharsError),
/// EOF (Ctrl-d)
Eof,
/// Ctrl-C
Expand Down Expand Up @@ -56,8 +58,8 @@ impl From<nix::Error> for ReadlineError {
}
}

impl From<io::CharsError> for ReadlineError {
fn from(err: io::CharsError) -> ReadlineError {
impl From<char_iter::CharsError> for ReadlineError {
fn from(err: char_iter::CharsError) -> ReadlineError {
ReadlineError::Char(err)
}
}
24 changes: 10 additions & 14 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@
//! Err(_) => println!("No input"),
//! }
//! ```
#![feature(io)]
#![feature(iter_arith)]
#![feature(unicode)]
#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

extern crate libc;
extern crate nix;
extern crate unicode_width;
extern crate encode_unicode;

pub mod completion;
#[allow(non_camel_case_types)]
Expand All @@ -31,9 +29,10 @@ pub mod error;
pub mod history;
mod kill_ring;
pub mod line_buffer;
mod char_iter;

use std::fmt;
use std::io::{self, Read, Write};
use std::io::{self, Write};
use std::mem;
use std::path::Path;
use std::result;
Expand All @@ -42,6 +41,7 @@ use std::sync::atomic;
use nix::errno::Errno;
use nix::sys::signal;
use nix::sys::termios;
use encode_unicode::CharExt;

use completion::Completer;
use consts::{KeyPress, char_to_key_press};
Expand Down Expand Up @@ -327,9 +327,7 @@ fn edit_insert(s: &mut State, ch: char) -> Result<()> {
if push {
if s.cursor.col + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0) < s.cols {
// Avoid a full update of the line in the trivial case.
let bits = ch.encode_utf8();
let bits = bits.as_slice();
write_and_flush(s.out, bits)
write_and_flush(s.out, ch.to_utf8().as_bytes())
} else {
s.refresh_line()
}
Expand Down Expand Up @@ -527,7 +525,7 @@ fn edit_history_next(s: &mut State, history: &History, prev: bool) -> Result<()>
}

/// Completes the line/word
fn complete_line<R: io::Read>(chars: &mut io::Chars<R>,
fn complete_line<R: io::Read>(chars: &mut char_iter::Chars<R>,
s: &mut State,
completer: &Completer)
-> Result<Option<char>> {
Expand Down Expand Up @@ -580,7 +578,7 @@ fn complete_line<R: io::Read>(chars: &mut io::Chars<R>,

/// Incremental search
#[cfg_attr(feature="clippy", allow(if_not_else))]
fn reverse_incremental_search<R: io::Read>(chars: &mut io::Chars<R>,
fn reverse_incremental_search<R: io::Read>(chars: &mut char_iter::Chars<R>,
s: &mut State,
history: &History)
-> Result<Option<KeyPress>> {
Expand Down Expand Up @@ -657,7 +655,7 @@ fn reverse_incremental_search<R: io::Read>(chars: &mut io::Chars<R>,
Ok(Some(key))
}

fn escape_sequence<R: io::Read>(chars: &mut io::Chars<R>) -> Result<KeyPress> {
fn escape_sequence<R: io::Read>(chars: &mut char_iter::Chars<R>) -> Result<KeyPress> {
// Read the next two bytes representing the escape sequence.
let seq1 = try!(chars.next().unwrap());
if seq1 == '[' {
Expand Down Expand Up @@ -735,7 +733,7 @@ fn readline_edit(prompt: &str,
kill_ring.reset();
let mut s = State::new(&mut stdout, prompt, MAX_LINE, get_columns(), history.len());
let stdin = io::stdin();
let mut chars = stdin.lock().chars();
let mut chars = char_iter::chars(stdin.lock());
loop {
let c = chars.next().unwrap();
if c.is_err() && SIGWINCH.compare_and_swap(true, false, atomic::Ordering::SeqCst) {
Expand Down Expand Up @@ -1164,12 +1162,10 @@ mod test {

#[test]
fn complete_line() {
use std::io::Read;

let mut out = ::std::io::sink();
let mut s = init_state(&mut out, "rus", 3, 80);
let input = b"\n";
let mut chars = input.chars();
let mut chars = ::char_iter::chars(&input[..]);
let completer = SimpleCompleter;
let ch = super::complete_line(&mut chars, &mut s, &completer).unwrap();
assert_eq!(Some('\n'), ch);
Expand Down
10 changes: 5 additions & 5 deletions src/line_buffer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Line buffer with current cursor position
use std::ops::Deref;
use std::ops::{Add, Deref};

/// Maximum buffer size for the line read
pub static MAX_LINE: usize = 4096;
Expand Down Expand Up @@ -259,15 +259,15 @@ impl LineBuffer {
.rev()
.take_while(|ch| test(*ch))
.map(char::len_utf8)
.sum();
.fold(0, Add::add);
if pos > 0 {
// eat any non-spaces on the left
pos -= self.buf[..pos]
.chars()
.rev()
.take_while(|ch| !test(*ch))
.map(char::len_utf8)
.sum();
.fold(0, Add::add);
}
Some(pos)
}
Expand Down Expand Up @@ -305,15 +305,15 @@ impl LineBuffer {
.chars()
.take_while(|ch| !ch.is_alphanumeric())
.map(char::len_utf8)
.sum();
.fold(0, Add::add);
let start = pos;
if pos < self.buf.len() {
// eat any non-spaces
pos += self.buf[pos..]
.chars()
.take_while(|ch| ch.is_alphanumeric())
.map(char::len_utf8)
.sum();
.fold(0, Add::add);
}
Some((start, pos))
} else {
Expand Down

0 comments on commit 65f45a3

Please sign in to comment.