Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for scrolling #252

Merged
merged 33 commits into from
Sep 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
589e43f
[VIM-2104] Use side scroll offset for horizontal scrolling
citizenmatt Aug 20, 2020
4cebaa8
Fix scrolljump
citizenmatt Aug 20, 2020
d08da77
Split scrollPositionIntoView method into two
citizenmatt Aug 20, 2020
d878c3e
Improve handling of scrolljump
citizenmatt Sep 1, 2020
8a42bff
Add tests for scrolloff and scrolljump
citizenmatt Sep 2, 2020
111c1eb
Add tests for ScrollLineUpAction
citizenmatt Sep 2, 2020
a5de935
Add tests for ScrollLineDownAction
citizenmatt Sep 2, 2020
632e9fa
Remove incorrect mappings for page up/down
citizenmatt Sep 2, 2020
3cf42c8
Add tests for ScrollPageDownAction
citizenmatt Sep 2, 2020
c8a1938
Add tests for ScrollPageUpAction
citizenmatt Sep 2, 2020
8f90ff8
Add tests for ScrollFirstScreenLinePageStartAction
citizenmatt Sep 2, 2020
be0adb8
Add tests for ScrollLastScreenLinePageStartAction
citizenmatt Sep 3, 2020
a7ba6d6
Add tests for ScrollFirstScreenLine actions
citizenmatt Sep 3, 2020
63d9a33
Add tests for ScrollLastScreenLine actions
citizenmatt Sep 3, 2020
7321099
Add tests for ScrollMiddleScreenLine actions
citizenmatt Sep 3, 2020
5ca0298
Add tests for ScrollHalfPage actions
citizenmatt Sep 3, 2020
6260168
Add internal action to show inline inlays
citizenmatt Sep 6, 2020
2091bbc
Improve cursor position handling with inlay hints
citizenmatt Sep 8, 2020
53a687f
Fix issues with side scrolling and inline inlays
citizenmatt Sep 15, 2020
df3a533
Fix arithmetic for scrolling columns
citizenmatt Sep 16, 2020
d693906
Add tests and fixes for ScrollColumnRightAction
citizenmatt Sep 16, 2020
64502fb
Reformat comments
citizenmatt Sep 16, 2020
eabe430
Add tests and fixes for ScrollColumnLeftAction
citizenmatt Sep 16, 2020
fa17af8
Fix keeping caret on screen with preceding inlay
citizenmatt Sep 16, 2020
007f33b
Add zL scroll half screen width action
citizenmatt Sep 16, 2020
26dae9b
Add zH scroll half screen width action
citizenmatt Sep 17, 2020
78f1c84
Use test inlay renderer for consistent width
citizenmatt Sep 17, 2020
63db148
Merge branch 'master' into VIM-2104
citizenmatt Sep 17, 2020
2dc54ea
Use deterministic width for inlays
citizenmatt Sep 17, 2020
cd0d503
Convert test to option test
AlexPl292 Sep 22, 2020
0a863f3
Small formatting
AlexPl292 Sep 22, 2020
1d8ac4f
Move scroll data objects up to avoid conflicts
AlexPl292 Sep 23, 2020
1c21968
Merge branch 'master' into VIM-2104
AlexPl292 Sep 23, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions resources/META-INF/includes/VimActions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@
<vimAction implementation="com.maddyhome.idea.vim.action.motion.scroll.MotionScrollLastScreenColumnAction" mappingModes="NXO" keys="ze"/>
<vimAction implementation="com.maddyhome.idea.vim.action.motion.scroll.MotionScrollColumnLeftAction" mappingModes="NXO" keys="zl,z«Right»"/>
<vimAction implementation="com.maddyhome.idea.vim.action.motion.scroll.MotionScrollColumnRightAction" mappingModes="NXO" keys="zh,z«Left»"/>
<vimAction implementation="com.maddyhome.idea.vim.action.motion.scroll.MotionScrollHalfWidthLeftAction" mappingModes="NXO" keys="zL"/>
<vimAction implementation="com.maddyhome.idea.vim.action.motion.scroll.MotionScrollHalfWidthRightAction" mappingModes="NXO" keys="zH"/>
<vimAction implementation="com.maddyhome.idea.vim.action.motion.updown.MotionShiftDownAction" mappingModes="NV" keys="«S-Down»"/>
<vimAction implementation="com.maddyhome.idea.vim.action.motion.updown.MotionShiftUpAction" mappingModes="NV" keys="«S-Up»"/>
<vimAction implementation="com.maddyhome.idea.vim.action.motion.leftright.MotionShiftRightAction" mappingModes="NV" keys="«S-Right»"/>
Expand Down
3 changes: 2 additions & 1 deletion resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@
</action>

<!-- Internal -->
<action id="VimInternalAddInlays" class="com.maddyhome.idea.vim.action.internal.AddInlaysAction" text="Add Test Inlays | IdeaVim Internal" internal="true"/>
<action id="VimInternalAddBlockInlays" class="com.maddyhome.idea.vim.action.internal.AddBlockInlaysAction" text="Add Test Block Inlays | IdeaVim Internal" internal="true"/>
<action id="VimInternalAddInlineInlays" class="com.maddyhome.idea.vim.action.internal.AddInlineInlaysAction" text="Add Test Inline Inlays | IdeaVim Internal" internal="true"/>

<action id="VimShortcutKeyAction" class="com.maddyhome.idea.vim.action.VimShortcutKeyAction"/>
<action id="VimActions" class="com.maddyhome.idea.vim.ui.VimActions"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import java.util.*
import javax.swing.UIManager
import kotlin.math.max

class AddInlaysAction : AnAction() {
class AddBlockInlaysAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) {
val dataContext = e.dataContext
val editor = getEditor(dataContext) ?: return
Expand Down Expand Up @@ -111,7 +111,7 @@ class AddInlaysAction : AnAction() {
return if (text == null) 0 else fontMetrics.stringWidth(text)
}

private inner class MyFontMetrics internal constructor(editor: Editor, familyName: String?, size: Int) {
private inner class MyFontMetrics(editor: Editor, familyName: String?, size: Int) {
val metrics: FontMetrics
fun isActual(editor: Editor, familyName: String, size: Int): Boolean {
val font = metrics.font
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2020 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.maddyhome.idea.vim.action.internal

import com.intellij.codeInsight.daemon.impl.HintRenderer
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.VisualPosition
import com.maddyhome.idea.vim.helper.EditorHelper
import java.util.*
import kotlin.math.max

class AddInlineInlaysAction : AnAction() {
companion object {
private val random = Random()
}

override fun actionPerformed(e: AnActionEvent) {
val dataContext = e.dataContext
val editor = getEditor(dataContext) ?: return
val inlayModel = editor.inlayModel
val currentVisualLine = editor.caretModel.primaryCaret.visualPosition.line
var i = random.nextInt(10)
val lineLength = EditorHelper.getLineLength(editor, EditorHelper.visualLineToLogicalLine(editor, currentVisualLine))
while (i < lineLength) {
val relatesToPrecedingText = random.nextInt(10) > 7
val text = "a".repeat(max(1, random.nextInt(7)))
val offset = EditorHelper.visualPositionToOffset(editor, VisualPosition(currentVisualLine, i))
// We don't need a custom renderer, just use the standard parameter hint renderer
inlayModel.addInlineElement(offset, relatesToPrecedingText, HintRenderer(if (relatesToPrecedingText) ":$text" else "$text:"))
// Every 20 chars +/- 5 chars
i += 20 + (random.nextInt(10) - 5)
}
}

private fun getEditor(dataContext: DataContext): Editor? {
return CommonDataKeys.EDITOR.getData(dataContext)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ class MotionScrollColumnLeftAction : VimActionHandler.SingleExecution() {
override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_IGNORE_SIDE_SCROLL_JUMP)

override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
return VimPlugin.getMotion().scrollColumn(editor, cmd.count)
return VimPlugin.getMotion().scrollColumns(editor, cmd.count)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ class MotionScrollColumnRightAction : VimActionHandler.SingleExecution() {
override val flags: EnumSet<CommandFlags> = EnumSet.of(CommandFlags.FLAG_IGNORE_SIDE_SCROLL_JUMP)

override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
return VimPlugin.getMotion().scrollColumn(editor, -cmd.count)
return VimPlugin.getMotion().scrollColumns(editor, -cmd.count)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ class MotionScrollFirstScreenColumnAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_READONLY

override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
return VimPlugin.getMotion().scrollColumnToFirstScreenColumn(editor)
return VimPlugin.getMotion().scrollCaretColumnToFirstScreenColumn(editor)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.enumSetOf
import java.util.*

class MotionScrollFirstScreenLineAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_READONLY

override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_IGNORE_SCROLL_JUMP)

override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
return VimPlugin.getMotion().scrollLineToFirstScreenLine(editor, cmd.rawCount, false)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,24 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.enumSetOf
import java.util.*

class MotionScrollFirstScreenLinePageStartAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_READONLY

override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_IGNORE_SCROLL_JUMP)

override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
var line = cmd.rawCount
if (line == 0) {
val nextVisualLine = EditorHelper.getVisualLineAtBottomOfScreen(editor) + 1
line = EditorHelper.visualLineToLogicalLine(editor, nextVisualLine) + 1 // rawCount is 1 based
var rawCount = cmd.rawCount
if (rawCount == 0) {
val nextVisualLine = EditorHelper.normalizeVisualLine(editor,
EditorHelper.getVisualLineAtBottomOfScreen(editor) + 1)
rawCount = EditorHelper.visualLineToLogicalLine(editor, nextVisualLine) + 1 // rawCount is 1 based
}
return VimPlugin.getMotion().scrollLineToFirstScreenLine(editor, line, true)
return VimPlugin.getMotion().scrollLineToFirstScreenLine(editor, rawCount, true)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.enumSetOf
import java.util.*

class MotionScrollFirstScreenLineStartAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_READONLY

override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_IGNORE_SCROLL_JUMP)

override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
return VimPlugin.getMotion().scrollLineToFirstScreenLine(editor, cmd.rawCount, true)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.enumSetOf
import java.util.*

class MotionScrollHalfPageDownAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_READONLY

override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_IGNORE_SCROLL_JUMP)

override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
return VimPlugin.getMotion().scrollScreen(editor, cmd.rawCount, true)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2020 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.maddyhome.idea.vim.action.motion.scroll

import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.enumSetOf
import java.util.*

/*
For the following four commands the cursor follows the screen. If the
character that the cursor is on is moved off the screen, the cursor is moved
to the closest character that is on the screen. The value of 'sidescroll' is
not used.

*zH*
zH Move the view on the text half a screenwidth to the
left, thus scroll the text half a screenwidth to the
right. This only works when 'wrap' is off.

[count] is used but undocumented.
*/
class MotionScrollHalfWidthLeftAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_READONLY

override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_IGNORE_SIDE_SCROLL_JUMP)

override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
// Vim's screen width is the full screen width, including columns used for gutters.
return VimPlugin.getMotion().scrollColumns(editor, cmd.count * (EditorHelper.getApproximateScreenWidth(editor) / 2));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2020 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.maddyhome.idea.vim.action.motion.scroll

import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.enumSetOf
import java.util.*

/*
For the following four commands the cursor follows the screen. If the
character that the cursor is on is moved off the screen, the cursor is moved
to the closest character that is on the screen. The value of 'sidescroll' is
not used.

*zH*
zH Move the view on the text half a screenwidth to the
left, thus scroll the text half a screenwidth to the
right. This only works when 'wrap' is off.

[count] is used but undocumented.
*/
class MotionScrollHalfWidthRightAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_READONLY

override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_IGNORE_SIDE_SCROLL_JUMP)

override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
// Vim's screen width is the full screen width, including columns used for gutters.
return VimPlugin.getMotion().scrollColumns(editor, -cmd.count * (EditorHelper.getApproximateScreenWidth(editor) / 2));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ class MotionScrollLastScreenColumnAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_READONLY

override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
return VimPlugin.getMotion().scrollColumnToLastScreenColumn(editor)
return VimPlugin.getMotion().scrollCaretColumnToLastScreenColumn(editor)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.enumSetOf
import java.util.*

class MotionScrollLastScreenLineAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_READONLY

override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_IGNORE_SCROLL_JUMP)

override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
return VimPlugin.getMotion().scrollLineToLastScreenLine(editor, cmd.rawCount, false)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,37 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.enumSetOf
import java.util.*

class MotionScrollLastScreenLinePageStartAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_READONLY

override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_IGNORE_SCROLL_JUMP)

override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
val motion = VimPlugin.getMotion()
var line = cmd.rawCount
if (line == 0) {
val prevVisualLine = EditorHelper.getVisualLineAtTopOfScreen(editor) - 1
line = EditorHelper.visualLineToLogicalLine(editor, prevVisualLine) + 1 // rawCount is 1 based
return motion.scrollLineToLastScreenLine(editor, line, true)

// Without [count]: Redraw with the line just above the window at the bottom of the window. Put the cursor in that
// line, at the first non-blank in the line.
if (cmd.rawCount == 0) {
val prevVisualLine = EditorHelper.normalizeVisualLine(editor,
EditorHelper.getVisualLineAtTopOfScreen(editor) - 1)
val logicalLine = EditorHelper.visualLineToLogicalLine(editor, prevVisualLine)
return motion.scrollLineToLastScreenLine(editor, logicalLine + 1, true)
}

// [count]z^ first scrolls [count] to the bottom of the window, then moves the caret to the line that is now at
// the top, and then move that line to the bottom of the window
line = EditorHelper.normalizeLine(editor, line)
if (motion.scrollLineToLastScreenLine(editor, line, true)) {
line = EditorHelper.getVisualLineAtTopOfScreen(editor)
line = EditorHelper.visualLineToLogicalLine(editor, line) + 1 // rawCount is 1 based
return motion.scrollLineToLastScreenLine(editor, line, true)
var logicalLine = EditorHelper.normalizeLine(editor, cmd.rawCount - 1)
if (motion.scrollLineToLastScreenLine(editor, logicalLine + 1, false)) {
logicalLine = EditorHelper.visualLineToLogicalLine(editor, EditorHelper.getVisualLineAtTopOfScreen(editor))
return motion.scrollLineToLastScreenLine(editor, logicalLine + 1, true)
}

return false
}
}