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));
     }
 }