diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index 5e015daed9313197ec8ad9993a5966e681ac7c7a..9fda75f5cfec7fdcadbc1a0f0944b8f850b35060 100755
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -345,6 +345,7 @@ public:
     void moveToTargetColumn();
     void setTargetColumn() {
         m_targetColumn = leftDist();
+        m_visualTargetColumn = m_targetColumn;
         //qDebug() << "TARGET: " << m_targetColumn;
     }
     void moveToNextWord(bool simple, bool deleteWord = false);
@@ -422,6 +423,7 @@ public:
     RangeMode m_rangemode;
 
     bool m_fakeEnd;
+    bool m_anchorPastEnd, m_positionPastEnd; // '$' & 'l' in visual mode can move past eol
 
     bool isSearchMode() const
         { return m_mode == SearchForwardMode || m_mode == SearchBackwardMode; }
@@ -506,7 +508,8 @@ public:
 
     // for restoring cursor position
     int m_savedYankPosition;
-    int m_targetColumn;
+    int m_targetColumn; // -1 if past end of line
+    int m_visualTargetColumn; // 'l' can move past eol in visual mode only
 
     int m_cursorWidth;
 
@@ -547,11 +550,13 @@ void FakeVimHandler::Private::init()
     m_passing = false;
     m_findPending = false;
     m_fakeEnd = false;
+    m_positionPastEnd = m_anchorPastEnd = false;
     m_lastSearchForward = true;
     m_register = '"';
     m_gflag = false;
     m_visualMode = NoVisualMode;
     m_targetColumn = 0;
+    m_visualTargetColumn = 0;
     m_movetype = MoveInclusive;
     m_anchor = 0;
     m_savedYankPosition = 0;
@@ -854,6 +859,15 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
             }
         }
 
+        if (m_positionPastEnd) {
+            moveBehindEndOfLine();
+            moveRight();
+        }
+
+        if (m_anchorPastEnd) {
+            m_anchor++;
+        }
+
         if (m_submode != TransformSubMode) {
             if (m_submode == YankSubMode)
                 m_savedYankPosition = qMin(anchor(), position());
@@ -861,6 +875,8 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
             if (m_movetype == MoveLineWise)
                 m_registers[m_register].rangemode = RangeLineMode;
         }
+
+        m_positionPastEnd = m_anchorPastEnd = false;
     }
 
     if (m_submode == ChangeSubMode) {
@@ -1324,6 +1340,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
         setTargetColumn();
         if (m_submode == NoSubMode)
             m_targetColumn = -1;
+        if (isVisualMode())
+            m_visualTargetColumn = -1;
         finishMovement("%1$", count());
     } else if (key == ',') {
         // FIXME: use some other mechanism
@@ -1575,8 +1593,13 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
         finishMovement("%1k", count());
     } else if (key == 'l' || key == Key_Right || key == ' ') {
         m_movetype = MoveExclusive;
+        setAnchor();
+        bool pastEnd = count() >= rightDist() - 1;
         moveRight(qMax(0, qMin(count(), rightDist() - (m_submode==NoSubMode))));
         setTargetColumn();
+        if (pastEnd && isVisualMode()) {
+            m_visualTargetColumn = -1;
+        }
         finishMovement("%1l", count());
     } else if (key == 'L') {
         m_tc = EDITOR(cursorForPosition(QPoint(0, EDITOR(height()))));
@@ -1610,6 +1633,10 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
         setPosition(anchor());
         m_anchor = pos;
         std::swap(m_marks['<'], m_marks['>']);
+        std::swap(m_positionPastEnd, m_anchorPastEnd);
+        setTargetColumn();
+        if (m_positionPastEnd)
+            m_visualTargetColumn = -1;
         updateSelection();
     } else if (key == 'o' || key == 'O') {
         beginEditBlock();
@@ -1858,6 +1885,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
         }
     }
 
+    m_positionPastEnd = (m_visualTargetColumn == -1) && isVisualMode();
+
     return handled;
 }
 
@@ -3192,6 +3221,7 @@ int FakeVimHandler::Private::lineForPosition(int pos) const
 void FakeVimHandler::Private::enterVisualMode(VisualMode visualMode)
 {
     setAnchor();
+    m_positionPastEnd = m_anchorPastEnd = false;
     m_visualMode = visualMode;
     m_marks['<'] = m_tc.position();
     m_marks['>'] = m_tc.position();