diff --git a/src/keymap.rs b/src/keymap.rs index 30985b3876193a268a5871af6d21ad5d768af63f..39e9053afe1994bd4e57c6f0652cb0405af913ba 100644 --- a/src/keymap.rs +++ b/src/keymap.rs @@ -35,7 +35,7 @@ pub enum Cmd { SelfInsert(RepeatCount, char), Suspend, TransposeChars, - TransposeWords, + TransposeWords(RepeatCount), Unknown, UpcaseWord, ViCharSearch(RepeatCount, CharSearch), @@ -230,7 +230,7 @@ impl EditState { } } KeyPress::Meta('L') => Cmd::DowncaseWord, - KeyPress::Meta('T') => Cmd::TransposeWords, + KeyPress::Meta('T') => Cmd::TransposeWords(n), KeyPress::Meta('U') => Cmd::UpcaseWord, KeyPress::Meta('Y') => Cmd::YankPop, _ => self.common(key, n, positive), diff --git a/src/lib.rs b/src/lib.rs index cd8d61ac13ba94ba6d7ce0e8df42c44eb4f45708..bbad52af0889519b011775002959c73982a97a73 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -508,8 +508,8 @@ fn edit_word(s: &mut State, a: WordAction) -> Result<()> { } } -fn edit_transpose_words(s: &mut State) -> Result<()> { - if s.line.transpose_words() { +fn edit_transpose_words(s: &mut State, n: RepeatCount) -> Result<()> { + if s.line.transpose_words(n) { s.refresh_line() } else { Ok(()) @@ -1028,10 +1028,10 @@ fn readline_edit<C: Completer>(prompt: &str, editor.kill_ring.reset(); try!(edit_word(&mut s, WordAction::LOWERCASE)) } - Cmd::TransposeWords => { + Cmd::TransposeWords(n) => { // transpose words editor.kill_ring.reset(); - try!(edit_transpose_words(&mut s)) + try!(edit_transpose_words(&mut s, n)) } Cmd::UpcaseWord => { // uppercase word after point diff --git a/src/line_buffer.rs b/src/line_buffer.rs index 255b6b8e494874017e65474c222c5fff10549272..3a38192c80f0ff11765609d6062e39656a1775a7 100644 --- a/src/line_buffer.rs +++ b/src/line_buffer.rs @@ -546,43 +546,30 @@ impl LineBuffer { } /// Transpose two words - pub fn transpose_words(&mut self) -> bool { - // prevword___oneword__ - // ^ ^ ^ - // prev_start start self.pos/end + pub fn transpose_words(&mut self, n: RepeatCount) -> bool { let word_def = Word::Emacs; - if let Some(start) = self.prev_word_pos(self.pos, word_def, 1) { - if let Some(prev_start) = self.prev_word_pos(start, word_def, 1) { - let (_, prev_end) = self.next_end_of_word_pos(prev_start, word_def, 1).unwrap(); - if prev_end >= start { - return false; - } - let (_, mut end) = self.next_end_of_word_pos(start, word_def, 1).unwrap(); - if end < self.pos { - if self.pos < self.buf.len() { - let (s, _) = self.next_end_of_word_pos(self.pos, word_def, 1).unwrap(); - end = s; - } else { - end = self.pos; - } - } + self.move_to_next_word(At::End, word_def, n); + let w2_end = self.pos; + self.move_to_prev_word(word_def, 1); + let w2_beg = self.pos; + self.move_to_prev_word(word_def, n); + let w1_beg = self.pos; + self.move_to_next_word(At::End, word_def, 1); + let w1_end = self.pos; + if w1_beg == w2_beg || w2_beg < w1_end { + return false; + } - let oneword = self.buf.drain(start..end).collect::<String>(); - let sep = self.buf.drain(prev_end..start).collect::<String>(); - let prevword = self.buf.drain(prev_start..prev_end).collect::<String>(); + let w1 = self.buf[w1_beg..w1_end].to_string(); - let mut idx = prev_start; - self.insert_str(idx, &oneword); - idx += oneword.len(); - self.insert_str(idx, &sep); - idx += sep.len(); - self.insert_str(idx, &prevword); + let w2 = self.buf.drain(w2_beg..w2_end).collect::<String>(); + self.insert_str(w2_beg, &w1); - self.pos = idx + prevword.len(); - return true; - } - } - false + self.buf.drain(w1_beg..w1_end); + self.insert_str(w1_beg, &w2); + + self.pos = w2_end; + true } /// Replaces the content between [`start`..`end`] with `text` and positions the cursor to the end of text. @@ -1011,19 +998,19 @@ mod test { #[test] fn transpose_words() { let mut s = LineBuffer::init("ßeta / δelta__", 15); - assert!(s.transpose_words()); + assert!(s.transpose_words(1)); assert_eq!("δelta__ / ßeta", s.buf); assert_eq!(16, s.pos); let mut s = LineBuffer::init("ßeta / δelta", 14); - assert!(s.transpose_words()); + assert!(s.transpose_words(1)); assert_eq!("δelta / ßeta", s.buf); assert_eq!(14, s.pos); let mut s = LineBuffer::init(" / δelta", 8); - assert!(!s.transpose_words()); + assert!(!s.transpose_words(1)); let mut s = LineBuffer::init("ßeta / __", 9); - assert!(!s.transpose_words()); + assert!(!s.transpose_words(1)); } }