FakeVim: Emulate Vim option "scrolloff" ("so")

Change-Id: Ied0a85ec834232a040b447d70f113daca9e4c035
Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
Lukas Holecek
2013-03-03 11:42:24 +01:00
committed by hjk
parent 96ad87376c
commit db8722fdd8
3 changed files with 41 additions and 9 deletions

View File

@@ -195,6 +195,7 @@ FakeVimSettings *theFakeVimSettings()
createAction(s, ConfigSmartCase, false, _("SmartCase"), _("scs")); createAction(s, ConfigSmartCase, false, _("SmartCase"), _("scs"));
createAction(s, ConfigWrapScan, true, _("WrapScan"), _("ws")); createAction(s, ConfigWrapScan, true, _("WrapScan"), _("ws"));
createAction(s, ConfigShowCmd, true, _("ShowCmd"), _("sc")); createAction(s, ConfigShowCmd, true, _("ShowCmd"), _("sc"));
createAction(s, ConfigScrollOff, 0, _("ScrollOff"), _("so"));
createAction(s, ConfigBackspace, _("indent,eol,start"), _("ConfigBackspace"), _("bs")); createAction(s, ConfigBackspace, _("indent,eol,start"), _("ConfigBackspace"), _("bs"));
createAction(s, ConfigIsKeyword, _("@,48-57,_,192-255,a-z,A-Z"), _("IsKeyword"), _("isk")); createAction(s, ConfigIsKeyword, _("@,48-57,_,192-255,a-z,A-Z"), _("IsKeyword"), _("isk"));
createAction(s, ConfigClipboard, QString(), _("Clipboard"), _("cb")); createAction(s, ConfigClipboard, QString(), _("Clipboard"), _("cb"));

View File

@@ -90,7 +90,8 @@ enum FakeVimSettingsCode
ConfigShowMarks, ConfigShowMarks,
ConfigPassControlKey, ConfigPassControlKey,
ConfigClipboard, ConfigClipboard,
ConfigShowCmd ConfigShowCmd,
ConfigScrollOff
}; };
class FakeVimSettings : public QObject class FakeVimSettings : public QObject

View File

@@ -1492,9 +1492,11 @@ public:
int logicalToPhysicalColumn(int logical, const QString &text) const; int logicalToPhysicalColumn(int logical, const QString &text) const;
Column cursorColumn() const; // as visible on screen Column cursorColumn() const; // as visible on screen
int firstVisibleLine() const; int firstVisibleLine() const;
void setScrollBarValue(int line);
void scrollToLine(int line); void scrollToLine(int line);
void scrollUp(int count); void scrollUp(int count);
void scrollDown(int count) { scrollUp(-count); } void scrollDown(int count) { scrollUp(-count); }
void updateScrollOffset();
void alignViewportToCursor(Qt::AlignmentFlag align, int line = -1, void alignViewportToCursor(Qt::AlignmentFlag align, int line = -1,
bool moveToNonBlank = false); bool moveToNonBlank = false);
@@ -2564,6 +2566,8 @@ void FakeVimHandler::Private::moveDown(int n)
block = document()->lastBlock(); block = document()->lastBlock();
setPosition(block.position() + qMax(0, qMin(block.length() - 2, col))); setPosition(block.position() + qMax(0, qMin(block.length() - 2, col)));
moveToTargetColumn(); moveToTargetColumn();
updateScrollOffset();
} }
bool FakeVimHandler::Private::moveToNextParagraph(int count) bool FakeVimHandler::Private::moveToNextParagraph(int count)
@@ -3334,13 +3338,13 @@ bool FakeVimHandler::Private::handleMovement(const Input &input)
} else if (input.is(']')) { } else if (input.is(']')) {
m_subsubmode = CloseSquareSubSubMode; m_subsubmode = CloseSquareSubSubMode;
} else if (input.isKey(Key_PageDown) || input.isControl('f')) { } else if (input.isKey(Key_PageDown) || input.isControl('f')) {
moveDown(count * (linesOnScreen() - 2) - cursorLineOnScreen()); moveDown(count * (linesOnScreen() - 2));
scrollToLine(cursorLine()); scrollToLine(cursorLine());
handleStartOfLine(); handleStartOfLine();
movement = _("f"); movement = _("f");
} else if (input.isKey(Key_PageUp) || input.isControl('b')) { } else if (input.isKey(Key_PageUp) || input.isControl('b')) {
moveUp(count * (linesOnScreen() - 2) + cursorLineOnScreen()); moveUp(count * (linesOnScreen() - 2));
scrollToLine(cursorLine() + linesOnScreen() - 2); scrollToLine(qMax(0, cursorLine() - linesOnScreen()));
handleStartOfLine(); handleStartOfLine();
movement = _("b"); movement = _("b");
} else if (input.isKey(Key_BracketLeft) || input.isKey(Key_BracketRight)) { } else if (input.isKey(Key_BracketLeft) || input.isKey(Key_BracketRight)) {
@@ -5994,13 +5998,22 @@ int FakeVimHandler::Private::linesInDocument() const
return document()->lastBlock().length() <= 1 ? count - 1 : count; return document()->lastBlock().length() <= 1 ? count - 1 : count;
} }
void FakeVimHandler::Private::setScrollBarValue(int line)
{
QScrollBar *scrollBar = EDITOR(verticalScrollBar());
// Convert line number to scroll bar value.
const int maxValue = scrollBar->maximum();
const int scrollLines = qMax(1, linesInDocument() - linesOnScreen());
const int value = maxValue >= scrollLines ? line * maxValue / scrollLines : line;
scrollBar->setValue(value);
}
void FakeVimHandler::Private::scrollToLine(int line) void FakeVimHandler::Private::scrollToLine(int line)
{ {
// FIXME: works only for QPlainTextEdit setScrollBarValue(line);
QScrollBar *scrollBar = EDITOR(verticalScrollBar()); updateScrollOffset();
//qDebug() << "SCROLL: " << scrollBar->value() << line;
scrollBar->setValue(line);
//QTC_CHECK(firstVisibleLine() == line);
} }
int FakeVimHandler::Private::firstVisibleLine() const int FakeVimHandler::Private::firstVisibleLine() const
@@ -6020,6 +6033,23 @@ void FakeVimHandler::Private::scrollUp(int count)
scrollToLine(cursorLine() - cursorLineOnScreen() - count); scrollToLine(cursorLine() - cursorLineOnScreen() - count);
} }
void FakeVimHandler::Private::updateScrollOffset()
{
// Precision of scroll offset depends on singleStep property of vertical scroll bar.
const int screenLines = linesOnScreen();
const int offset = qMin(theFakeVimSetting(ConfigScrollOff)->value().toInt(), screenLines / 2);
const int line = cursorLine();
const int scrollLine = firstVisibleLine();
int d = line - scrollLine;
if (d < offset) {
setScrollBarValue(scrollLine - offset + d);
} else {
d = screenLines - d;
if (d <= offset)
setScrollBarValue(scrollLine + offset - d);
}
}
void FakeVimHandler::Private::alignViewportToCursor(AlignmentFlag align, int line, void FakeVimHandler::Private::alignViewportToCursor(AlignmentFlag align, int line,
bool moveToNonBlank) bool moveToNonBlank)
{ {