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 a006ff116be5616fb3551f8845e3aa1dbf0b1f0f..29f2dd4ab269de37533017218640fc2cf8eb0ea1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -512,8 +512,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(()) @@ -1032,10 +1032,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 3c77e5beba063bb68b295730924f928250b0cb24..ef2be1692d08ae07d23482bdfd74577dbe513401 100644 --- a/src/line_buffer.rs +++ b/src/line_buffer.rs @@ -553,43 +553,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. @@ -999,19 +986,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)); } }