diff --git a/src/edit/commands.js b/src/edit/commands.js
index fe39ed727f63b123e3b0386f10f933c13459a5f8..0b0125d1e9e658d40933b95c57fc1c5e4c8f35e1 100644
--- a/src/edit/commands.js
+++ b/src/edit/commands.js
@@ -106,9 +106,17 @@ export let commands = {
     if (cm.somethingSelected()) cm.indentSelection("add")
     else cm.execCommand("insertTab")
   },
+  // Swap the two chars left and right of each selection's head.
+  // Move cursor behind the two swapped characters afterwards.
+  //
+  // Doesn't consider line feeds a character.
+  // Doesn't scan more than one line above to find a character.
+  // Doesn't do anything on an empty line.
+  // Doesn't do anything with non-empty selections.
   transposeChars: cm => runInOp(cm, () => {
     let ranges = cm.listSelections(), newSel = []
     for (let i = 0; i < ranges.length; i++) {
+      if (!ranges[i].empty()) continue
       let cur = ranges[i].head, line = getLine(cm.doc, cur.line).text
       if (line) {
         if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1)
@@ -118,10 +126,12 @@ export let commands = {
                           Pos(cur.line, cur.ch - 2), cur, "+transpose")
         } else if (cur.line > cm.doc.first) {
           let prev = getLine(cm.doc, cur.line - 1).text
-          if (prev)
+          if (prev) {
+            cur = new Pos(cur.line, 1)
             cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +
                             prev.charAt(prev.length - 1),
-                            Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose")
+                            Pos(cur.line - 1, prev.length - 1), cur, "+transpose")
+          }
         }
       }
       newSel.push(new Range(cur, cur))
diff --git a/test/emacs_test.js b/test/emacs_test.js
index 124575c72421e447e80d02c5ee16d9651a499b01..628651c786b2d97ee774d28b95dc74a429bfe883 100644
--- a/test/emacs_test.js
+++ b/test/emacs_test.js
@@ -111,7 +111,7 @@
   sim("transposeChar", "abcd\ne",
       "Ctrl-F", "Ctrl-T", "Ctrl-T", txt("bcad\ne"), at(0, 3),
       "Ctrl-F", "Ctrl-T", "Ctrl-T", "Ctrl-T", txt("bcda\ne"), at(0, 4),
-      "Ctrl-F", "Ctrl-T", txt("bcde\na"), at(1, 0));
+      "Ctrl-F", "Ctrl-T", txt("bcde\na"), at(1, 1));
 
   sim("manipWordCase", "foo BAR bAZ",
       "Alt-C", "Alt-L", "Alt-U", txt("Foo bar BAZ"),