From 454cf36fde7e69e50658f99566cd6aa322df152d Mon Sep 17 00:00:00 2001 From: gwenn <gtreguier@gmail.com> Date: Wed, 11 Jan 2017 19:50:14 +0100 Subject: [PATCH] Move cursor by grapheme (not by char) #107 Fix commands on word --- src/lib.rs | 2 ++ src/line_buffer.rs | 73 +++++++++++++++++++++++++--------------------- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 586c08c3..f7d79c92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,11 +16,13 @@ //! ``` #![feature(io)] #![feature(insert_str)] +#![feature(unicode)] #![allow(unknown_lints)] extern crate libc; #[macro_use] extern crate log; +extern crate std_unicode; extern crate unicode_segmentation; extern crate unicode_width; #[cfg(unix)] diff --git a/src/line_buffer.rs b/src/line_buffer.rs index 46da50a4..9b6cf1b9 100644 --- a/src/line_buffer.rs +++ b/src/line_buffer.rs @@ -1,6 +1,7 @@ //! Line buffer with current cursor position use std::iter; use std::ops::{Deref, Range}; +use std_unicode::str::UnicodeStr; use unicode_segmentation::UnicodeSegmentation; use keymap::{Anchor, At, CharSearch, Word}; @@ -299,20 +300,22 @@ impl LineBuffer { let mut pos = pos; for _ in 0..n { // eat any spaces on the left - pos -= self.buf[..pos] - .chars() + pos = self.buf[..pos] + .grapheme_indices(true) .rev() - .take_while(|ch| test(ch)) - .map(char::len_utf8) - .sum(); + .take_while(|&(_, s)| test(s)) + .last() + .map(|(i, _)| i) + .unwrap_or(pos); if pos > 0 { // eat any non-spaces on the left - pos -= self.buf[..pos] - .chars() + pos = self.buf[..pos] + .grapheme_indices(true) .rev() - .take_while(|ch| !test(ch)) - .map(char::len_utf8) - .sum(); + .take_while(|&(_, s)| !test(s)) + .last() + .map(|(i, _)| i) + .unwrap_or(pos); } if pos == 0 { break; @@ -365,17 +368,19 @@ impl LineBuffer { for _ in 0..n { // eat any non-spaces pos += self.buf[pos..] - .chars() - .take_while(|ch| !test(ch)) - .map(char::len_utf8) - .sum(); + .grapheme_indices(true) + .take_while(|&(_, s)| !test(s)) + .last() + .map(|(i, s)| i + s.len()) + .unwrap_or(0); if pos < self.buf.len() { // eat any spaces pos += self.buf[pos..] - .chars() - .take_while(test) - .map(char::len_utf8) - .sum(); + .grapheme_indices(true) + .take_while(|&(_, s)| test(s)) + .last() + .map(|(i, s)| i + s.len()) + .unwrap_or(0); } if pos == self.buf.len() { break; @@ -396,18 +401,20 @@ impl LineBuffer { for _ in 0..n { // eat any spaces pos += self.buf[pos..] - .chars() - .take_while(test) - .map(char::len_utf8) - .sum(); + .grapheme_indices(true) + .take_while(|&(_, s)| test(s)) + .last() + .map(|(i, s)| i + s.len()) + .unwrap_or(0); start = pos; if pos < self.buf.len() { // eat any non-spaces pos += self.buf[pos..] - .chars() - .take_while(|ch| !test(ch)) - .map(char::len_utf8) - .sum(); + .grapheme_indices(true) + .take_while(|&(_, s)| !test(s)) + .last() + .map(|(i, s)| i + s.len()) + .unwrap_or(0); } if pos == self.buf.len() { break; @@ -605,7 +612,7 @@ impl Deref for LineBuffer { } } -fn is_break_char(word_def: Word) -> fn(&char) -> bool { +fn is_break_char(word_def: Word) -> fn(&str) -> bool { match word_def { Word::Emacs => is_not_alphanumeric, Word::Vi => is_not_alphanumeric_and_underscore, @@ -613,14 +620,14 @@ fn is_break_char(word_def: Word) -> fn(&char) -> bool { } } -fn is_not_alphanumeric(ch: &char) -> bool { - !ch.is_alphanumeric() +fn is_not_alphanumeric(s: &str) -> bool { + !s.is_alphanumeric() } -fn is_not_alphanumeric_and_underscore(ch: &char) -> bool { - !ch.is_alphanumeric() && *ch != '_' +fn is_not_alphanumeric_and_underscore(s: &str) -> bool { + !s.is_alphanumeric() && s != "_" } -fn is_whitespace(ch: &char) -> bool { - ch.is_whitespace() +fn is_whitespace(s: &str) -> bool { + s.is_whitespace() } #[cfg(test)] -- GitLab