mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-05-15 18:34:05 +02:00
Remove traces of the experimental API
This commit is contained in:
parent
0e8ec4d445
commit
01e4c80adb
src/main/java/com/maddyhome/idea/vim
vim-engine/src/main/kotlin/com/maddyhome/idea/vim
action/change/insert
api
common
@ -146,19 +146,6 @@ public class ChangeGroup extends VimChangeGroupBase {
|
||||
return new Pair<>(range, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertLineAround(@NotNull VimEditor editor, @NotNull ExecutionContext context, int shift) {
|
||||
com.maddyhome.idea.vim.newapi.ChangeGroupKt.insertLineAround(editor, context, shift);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteRange2(@NotNull VimEditor editor,
|
||||
@NotNull VimCaret caret,
|
||||
@NotNull TextRange range,
|
||||
@NotNull SelectionType type) {
|
||||
return com.maddyhome.idea.vim.newapi.ChangeGroupKt.deleteRange(editor, caret, range, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the case of count characters
|
||||
*
|
||||
|
@ -1,211 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE.txt file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
|
||||
package com.maddyhome.idea.vim.newapi
|
||||
|
||||
import com.intellij.codeInsight.editorActions.EnterHandler
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.editor.Caret
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.util.PsiUtilBase
|
||||
import com.intellij.util.text.CharArrayUtil
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||
import com.maddyhome.idea.vim.api.LineDeleteShift
|
||||
import com.maddyhome.idea.vim.api.VimCaret
|
||||
import com.maddyhome.idea.vim.api.VimChangeGroupBase
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.VimMotionGroupBase
|
||||
import com.maddyhome.idea.vim.api.getLeadingCharacterOffset
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.api.normalizeOffset
|
||||
import com.maddyhome.idea.vim.command.SelectionType
|
||||
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||
import com.maddyhome.idea.vim.common.EditorLine
|
||||
import com.maddyhome.idea.vim.common.IndentConfig
|
||||
import com.maddyhome.idea.vim.common.OperatedRange
|
||||
import com.maddyhome.idea.vim.common.TextRange
|
||||
import com.maddyhome.idea.vim.common.VimRange
|
||||
import com.maddyhome.idea.vim.common.including
|
||||
import com.maddyhome.idea.vim.common.offset
|
||||
import com.maddyhome.idea.vim.helper.vimChangeActionSwitchMode
|
||||
import com.maddyhome.idea.vim.helper.vimLastColumn
|
||||
|
||||
internal fun changeRange(
|
||||
editor: Editor,
|
||||
caret: Caret,
|
||||
range: TextRange,
|
||||
type: SelectionType,
|
||||
context: DataContext,
|
||||
) {
|
||||
val vimEditor = IjVimEditor(editor)
|
||||
val vimRange = toVimRange(range, type)
|
||||
|
||||
var col = 0
|
||||
var lines = 0
|
||||
if (type === SelectionType.BLOCK_WISE) {
|
||||
lines = VimChangeGroupBase.getLinesCountInVisualBlock(IjVimEditor(editor), range)
|
||||
col = editor.offsetToLogicalPosition(range.startOffset).column
|
||||
if (caret.vimLastColumn == VimMotionGroupBase.LAST_COLUMN) {
|
||||
col = VimMotionGroupBase.LAST_COLUMN
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the range
|
||||
val vimCaret = IjVimCaret(caret)
|
||||
val indent = editor.offsetToLogicalPosition(vimEditor.getLeadingCharacterOffset(vimCaret.getLine().line)).column
|
||||
val deletedInfo = injector.vimMachine.delete(vimRange, vimEditor, vimCaret)
|
||||
if (deletedInfo != null) {
|
||||
if (deletedInfo is OperatedRange.Lines) {
|
||||
// Add new line in case of linewise motion
|
||||
val existingLine = if (vimEditor.fileSize() != 0L) {
|
||||
if (deletedInfo.shiftType != LineDeleteShift.NO_NL) {
|
||||
vimEditor.addLine(deletedInfo.lineAbove)
|
||||
} else {
|
||||
EditorLine.Pointer.init(deletedInfo.lineAbove.line, vimEditor)
|
||||
}
|
||||
} else {
|
||||
EditorLine.Pointer.init(0, vimEditor)
|
||||
}
|
||||
|
||||
val offset = injector.motion.moveCaretToLineWithStartOfLineOption(vimEditor, existingLine.line, vimCaret)
|
||||
// TODO: 29.12.2021 IndentConfig is not abstract
|
||||
val indentText = IndentConfig.create(editor).createIndentBySize(indent)
|
||||
vimEditor.insertText(offset.offset, indentText)
|
||||
val caretOffset = offset + indentText.length
|
||||
vimCaret.moveToOffset(caretOffset)
|
||||
VimPlugin.getChange().insertBeforeCursor(editor.vim, context.vim)
|
||||
} else {
|
||||
when (deletedInfo) {
|
||||
is OperatedRange.Characters -> {
|
||||
vimCaret.moveToOffset(deletedInfo.leftOffset.point)
|
||||
}
|
||||
is OperatedRange.Block -> TODO()
|
||||
else -> TODO()
|
||||
}
|
||||
if (type == SelectionType.BLOCK_WISE) {
|
||||
VimPlugin.getChange().setInsertRepeat(lines, col, false)
|
||||
}
|
||||
editor.vimChangeActionSwitchMode = VimStateMachine.Mode.INSERT
|
||||
}
|
||||
} else {
|
||||
VimPlugin.getChange().insertBeforeCursor(editor.vim, context.vim)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun deleteRange(
|
||||
editor: VimEditor,
|
||||
caret: VimCaret,
|
||||
range: TextRange,
|
||||
type: SelectionType,
|
||||
): Boolean {
|
||||
val vimRange = toVimRange(range, type)
|
||||
|
||||
val deletedInfo = injector.vimMachine.delete(vimRange, editor, caret)
|
||||
if (deletedInfo != null) {
|
||||
when (deletedInfo) {
|
||||
is OperatedRange.Characters -> {
|
||||
val newOffset = editor.normalizeOffset(deletedInfo.leftOffset.point, false)
|
||||
caret.moveToOffset(newOffset)
|
||||
}
|
||||
is OperatedRange.Block -> TODO()
|
||||
is OperatedRange.Lines -> {
|
||||
if (deletedInfo.shiftType != LineDeleteShift.NL_ON_START) {
|
||||
val line = deletedInfo.lineAbove.toPointer(editor)
|
||||
val offset = injector.motion.moveCaretToLineWithStartOfLineOption(editor, line.line, caret)
|
||||
caret.moveToOffset(offset)
|
||||
} else {
|
||||
val logicalLine = EditorLine.Pointer.init((deletedInfo.lineAbove.line - 1).coerceAtLeast(0), editor)
|
||||
val offset = injector.motion.moveCaretToLineWithStartOfLineOption(editor, logicalLine.line, caret)
|
||||
caret.moveToOffset(offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return deletedInfo != null
|
||||
}
|
||||
|
||||
/**
|
||||
* XXX: This implementation is incorrect!
|
||||
*
|
||||
* Known issues of this code:
|
||||
* - Indent is incorrect when `o` for kotlin code like
|
||||
* ```
|
||||
* if (true) {
|
||||
* }
|
||||
* ```
|
||||
* This is probably the kotlin issue, but still
|
||||
* - `*` character doesn't appear when `o` in javadoc section
|
||||
*/
|
||||
internal fun insertLineAround(editor: VimEditor, context: ExecutionContext, shift: Int) {
|
||||
val project = (editor as IjVimEditor).editor.project
|
||||
|
||||
VimPlugin.getChange().initInsert(editor, context, VimStateMachine.Mode.INSERT)
|
||||
|
||||
if (!VimStateMachine.getInstance(editor).isDotRepeatInProgress) {
|
||||
for (vimCaret in editor.carets()) {
|
||||
val caret = (vimCaret as IjVimCaret).caret
|
||||
val line = vimCaret.getLine()
|
||||
|
||||
// Current line indent
|
||||
val lineStartOffset = editor.getLineRange(line).first.point
|
||||
val text = editor.editor.document.charsSequence
|
||||
val lineStartWsEndOffset = CharArrayUtil.shiftForward(text, lineStartOffset, " \t")
|
||||
val indent = text.subSequence(lineStartOffset, lineStartWsEndOffset)
|
||||
|
||||
// Calculating next line with minding folders
|
||||
val lineEndOffset = if (shift == 1) {
|
||||
VimPlugin.getMotion().moveCaretToCurrentLineEnd(editor, IjVimCaret(caret))
|
||||
} else {
|
||||
VimPlugin.getMotion().moveCaretToCurrentLineStart(editor, caret.vim)
|
||||
}
|
||||
val position = EditorLine.Offset.init(editor.offsetToBufferPosition(lineEndOffset).line + shift, editor)
|
||||
|
||||
val insertedLine = editor.addLine(position)
|
||||
VimPlugin.getChange().saveStrokes("\n")
|
||||
|
||||
var lineStart = editor.getLineRange(insertedLine).first
|
||||
val initialLineStart = lineStart
|
||||
|
||||
// Set up indent
|
||||
// Firstly set up primitive indent
|
||||
editor.insertText(lineStart, indent)
|
||||
lineStart = (lineStart.point + indent.length).offset
|
||||
|
||||
if (project != null) {
|
||||
// Secondly set up language smart indent
|
||||
val language = PsiUtilBase.getLanguageInEditor(caret, project)
|
||||
val newIndent = EnterHandler.adjustLineIndentNoCommit(language, editor.editor.document, editor.editor, lineStart.point)
|
||||
lineStart = if (newIndent >= 0) newIndent.offset else lineStart
|
||||
}
|
||||
VimPlugin.getChange()
|
||||
.saveStrokes(
|
||||
editor.editor.document.getText(
|
||||
com.intellij.openapi.util.TextRange(
|
||||
initialLineStart.point,
|
||||
lineStart.point,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
vimCaret.moveToOffset(lineStart.point)
|
||||
}
|
||||
}
|
||||
|
||||
injector.scroll.scrollCaretIntoView(editor)
|
||||
}
|
||||
|
||||
internal fun toVimRange(range: TextRange, type: SelectionType): VimRange {
|
||||
return when (type) {
|
||||
SelectionType.LINE_WISE -> {
|
||||
VimRange.Line.Offsets(range.startOffset.offset, range.endOffset.offset)
|
||||
}
|
||||
SelectionType.CHARACTER_WISE -> VimRange.Character.Range(range.startOffset including range.endOffset)
|
||||
SelectionType.BLOCK_WISE -> VimRange.Block(range.startOffset.offset, range.endOffset.offset)
|
||||
}
|
||||
}
|
@ -53,7 +53,6 @@ import com.maddyhome.idea.vim.api.VimscriptExecutor
|
||||
import com.maddyhome.idea.vim.api.VimscriptFunctionService
|
||||
import com.maddyhome.idea.vim.api.VimscriptParser
|
||||
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||
import com.maddyhome.idea.vim.common.VimMachine
|
||||
import com.maddyhome.idea.vim.diagnostic.VimLogger
|
||||
import com.maddyhome.idea.vim.ex.ExOutputModel
|
||||
import com.maddyhome.idea.vim.extension.VimExtensionRegistrar
|
||||
@ -159,8 +158,6 @@ internal class IjVimInjector : VimInjectorBase() {
|
||||
get() = service<IjVimApplication>()
|
||||
override val executionContextManager: ExecutionContextManager
|
||||
get() = service<IjExecutionContextManager>()
|
||||
override val vimMachine: VimMachine
|
||||
get() = service<VimMachineImpl>()
|
||||
override val enabler: VimEnabler
|
||||
get() = service<IjVimEnabler>()
|
||||
override val digraphGroup: VimDigraphGroup
|
||||
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE.txt file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
|
||||
package com.maddyhome.idea.vim.newapi
|
||||
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.maddyhome.idea.vim.common.VimMachineBase
|
||||
|
||||
@Service
|
||||
internal class VimMachineImpl : VimMachineBase()
|
@ -33,12 +33,7 @@ public class InsertNewLineBelowAction : ChangeEditorActionHandler.SingleExecutio
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
if (editor.isOneLineMode()) return false
|
||||
@Suppress("ConstantConditionIf")
|
||||
if (false) {
|
||||
injector.changeGroup.insertLineAround(editor, context, 1)
|
||||
} else {
|
||||
insertNewLineBelow(editor, context)
|
||||
}
|
||||
insertNewLineBelow(editor, context)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -55,12 +50,7 @@ public class InsertNewLineAboveAction : ChangeEditorActionHandler.SingleExecutio
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
if (editor.isOneLineMode()) return false
|
||||
@Suppress("ConstantConditionIf")
|
||||
if (false) {
|
||||
injector.changeGroup.insertLineAround(editor, context, 0)
|
||||
} else {
|
||||
insertNewLineAbove(editor, context)
|
||||
}
|
||||
insertNewLineAbove(editor, context)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,6 @@ public interface VimChangeGroup {
|
||||
|
||||
public fun insertPreviousInsert(editor: VimEditor, context: ExecutionContext, exit: Boolean, operatorArguments: OperatorArguments)
|
||||
|
||||
public fun insertLineAround(editor: VimEditor, context: ExecutionContext, shift: Int)
|
||||
|
||||
public fun initInsert(editor: VimEditor, context: ExecutionContext, mode: VimStateMachine.Mode)
|
||||
|
||||
public fun processEscape(editor: VimEditor, context: ExecutionContext?, operatorArguments: OperatorArguments)
|
||||
@ -96,8 +94,6 @@ public interface VimChangeGroup {
|
||||
operatorArguments: OperatorArguments,
|
||||
saveToRegister: Boolean = true,
|
||||
): Boolean
|
||||
public fun deleteRange2(editor: VimEditor, caret: VimCaret, range: TextRange, type: SelectionType): Boolean
|
||||
|
||||
public fun changeCharacters(editor: VimEditor, caret: VimCaret, operatorArguments: OperatorArguments): Boolean
|
||||
|
||||
public fun changeEndOfLine(editor: VimEditor, caret: VimCaret, count: Int, operatorArguments: OperatorArguments): Boolean
|
||||
|
@ -14,12 +14,8 @@ import com.maddyhome.idea.vim.command.VimStateMachine
|
||||
import com.maddyhome.idea.vim.common.EditorLine
|
||||
import com.maddyhome.idea.vim.common.LiveRange
|
||||
import com.maddyhome.idea.vim.common.Offset
|
||||
import com.maddyhome.idea.vim.common.OperatedRange
|
||||
import com.maddyhome.idea.vim.common.Pointer
|
||||
import com.maddyhome.idea.vim.common.TextRange
|
||||
import com.maddyhome.idea.vim.common.VimRange
|
||||
import com.maddyhome.idea.vim.common.offset
|
||||
import com.maddyhome.idea.vim.common.pointer
|
||||
|
||||
/**
|
||||
* Every line in [VimEditor] ends with a new line TODO <- this is probably not true already
|
||||
@ -133,7 +129,6 @@ public interface VimEditor {
|
||||
public var vimChangeActionSwitchMode: VimStateMachine.Mode?
|
||||
public var vimKeepingVisualOperatorAction: Boolean
|
||||
|
||||
public fun deleteDryRun(range: VimRange): OperatedRange?
|
||||
public fun fileSize(): Long
|
||||
public fun text(): CharSequence
|
||||
|
||||
@ -273,13 +268,6 @@ public interface VimEditor {
|
||||
}
|
||||
|
||||
public interface MutableVimEditor : VimEditor {
|
||||
/**
|
||||
* Returns actually deleted range and the according text, if any.
|
||||
*
|
||||
* TODO: How to make a clear code difference between [delete] and [deleteDryRun]. How to make sure that [deleteDryRun]
|
||||
* will be called before [delete]? Should we call [deleteDryRun] before [delete]?
|
||||
*/
|
||||
public fun delete(range: VimRange)
|
||||
public fun addLine(atPosition: EditorLine.Offset): EditorLine.Pointer?
|
||||
public fun insertText(atPosition: Offset, text: CharSequence)
|
||||
public fun replaceString(start: Int, end: Int, newString: String)
|
||||
@ -293,77 +281,6 @@ public abstract class LinearEditor : VimEditor {
|
||||
public abstract class MutableLinearEditor : MutableVimEditor, LinearEditor() {
|
||||
public abstract fun deleteRange(leftOffset: Offset, rightOffset: Offset)
|
||||
|
||||
public override fun delete(range: VimRange) {
|
||||
when (range) {
|
||||
is VimRange.Block -> TODO()
|
||||
is VimRange.Character.Multiple -> TODO()
|
||||
is VimRange.Character.Range -> {
|
||||
deleteRange(range.offsetAbove(), range.offsetBelow())
|
||||
}
|
||||
is VimRange.Line.Multiple -> TODO()
|
||||
is VimRange.Line.Range -> {
|
||||
val startOffset = getLineRange(range.lineAbove()).first
|
||||
val endOffset = getLineRange(range.lineBelow()).second
|
||||
deleteRange(startOffset, endOffset)
|
||||
}
|
||||
is VimRange.Line.Offsets -> {
|
||||
var startOffset = getLineRange(getLine(range.offsetAbove())).first
|
||||
var endOffset = getLineRange(getLine(range.offsetBelow())).second
|
||||
var shiftType = LineDeleteShift.NO_NL
|
||||
if (endOffset.point < fileSize() && charAt(endOffset.point.pointer) == '\n') {
|
||||
endOffset = (endOffset.point + 1).offset
|
||||
shiftType = LineDeleteShift.NL_ON_END
|
||||
} else if (startOffset.point > 0 && lfMakesNewLine) {
|
||||
startOffset = (startOffset.point - 1).offset
|
||||
shiftType = LineDeleteShift.NL_ON_START
|
||||
}
|
||||
val (newStart, newEnd) = search((startOffset to endOffset), this, shiftType)?.first ?: return
|
||||
deleteRange(newStart, newEnd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun deleteDryRun(range: VimRange): OperatedRange? {
|
||||
return when (range) {
|
||||
is VimRange.Block -> TODO()
|
||||
is VimRange.Character.Multiple -> TODO()
|
||||
is VimRange.Character.Range -> {
|
||||
val textToDelete = getText(range.offsetAbove(), range.offsetBelow())
|
||||
OperatedRange.Characters(textToDelete, range.offsetAbove(), range.offsetBelow())
|
||||
}
|
||||
is VimRange.Line.Multiple -> TODO()
|
||||
is VimRange.Line.Range -> {
|
||||
val startOffset = getLineRange(range.lineAbove()).first
|
||||
val endOffset = getLineRange(range.lineBelow()).second
|
||||
@Suppress("UNUSED_VARIABLE") val textToDelete = getText(startOffset, endOffset)
|
||||
TODO()
|
||||
}
|
||||
is VimRange.Line.Offsets -> {
|
||||
val lineAbove = getLine(range.offsetAbove())
|
||||
var startOffset = getLineRange(lineAbove).first
|
||||
val lineBelow = getLine(range.offsetBelow())
|
||||
var endOffset = getLineRange(lineBelow).second
|
||||
var shiftType = LineDeleteShift.NO_NL
|
||||
if (endOffset.point < fileSize() && charAt(endOffset.point.pointer) == '\n') {
|
||||
endOffset = (endOffset.point + 1).offset
|
||||
shiftType = LineDeleteShift.NL_ON_END
|
||||
} else if (startOffset.point > 0 && lfMakesNewLine) {
|
||||
startOffset = (startOffset.point - 1).offset
|
||||
shiftType = LineDeleteShift.NL_ON_START
|
||||
}
|
||||
val data = search((startOffset to endOffset), this, shiftType) ?: return null
|
||||
val (newStart, newEnd) = data.first
|
||||
shiftType = data.second
|
||||
val textToDelete = getText(newStart, newEnd)
|
||||
OperatedRange.Lines(
|
||||
textToDelete,
|
||||
EditorLine.Offset.init(lineAbove.line, this),
|
||||
lineBelow.line - lineAbove.line,
|
||||
shiftType
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum class LineDeleteShift {
|
||||
|
@ -9,7 +9,6 @@
|
||||
package com.maddyhome.idea.vim.api
|
||||
|
||||
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||
import com.maddyhome.idea.vim.common.VimMachine
|
||||
import com.maddyhome.idea.vim.diagnostic.VimLogger
|
||||
import com.maddyhome.idea.vim.group.TabService
|
||||
import com.maddyhome.idea.vim.group.VimWindowGroup
|
||||
@ -45,8 +44,6 @@ public interface VimInjector {
|
||||
// [FINISHED] Fully moved to vim-engine except one method that iterates with IJ.
|
||||
// Need to check how it would work in fleet before moving this method.
|
||||
public val digraphGroup: VimDigraphGroup
|
||||
// [FINISHED] Fully moved to vim-engine. Should we remove it from injector?
|
||||
public val vimMachine: VimMachine
|
||||
// [FINISHED] Can't be fully moved to vim-engine.
|
||||
public val enabler: VimEnabler
|
||||
|
||||
|
@ -13,8 +13,6 @@ import com.maddyhome.idea.vim.api.stubs.VimApplicationStub
|
||||
import com.maddyhome.idea.vim.api.stubs.VimEnablerStub
|
||||
import com.maddyhome.idea.vim.api.stubs.VimMessagesStub
|
||||
import com.maddyhome.idea.vim.api.stubs.VimProcessGroupStub
|
||||
import com.maddyhome.idea.vim.common.VimMachine
|
||||
import com.maddyhome.idea.vim.common.VimMachineBase
|
||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||
import com.maddyhome.idea.vim.register.VimRegisterGroup
|
||||
import com.maddyhome.idea.vim.register.VimRegisterGroupBase
|
||||
@ -32,7 +30,6 @@ abstract class VimInjectorBase : VimInjector {
|
||||
}
|
||||
|
||||
override val parser: VimStringParser = object : VimStringParserBase() {}
|
||||
override val vimMachine: VimMachine = object : VimMachineBase() {}
|
||||
override val optionGroup: VimOptionGroup by lazy { object : VimOptionGroupBase() {} }
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated("Use optionGroup")
|
||||
|
@ -20,63 +20,6 @@ import com.maddyhome.idea.vim.mark.VimMarkConstants
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Back direction range is possible. `start` is not lower than `end`.
|
||||
* TODO: How to show it in code and namings?
|
||||
* How to separate methods that return "starting from" line and "the above line"
|
||||
*
|
||||
* TODO: How to represent "till last column"
|
||||
*
|
||||
* [VimRange] includes selection type (line, character, block)
|
||||
*
|
||||
* Range normalizations (check if line and offsets really exist) are performed in editor implementations.
|
||||
*/
|
||||
public sealed class VimRange {
|
||||
public sealed class Line : VimRange() {
|
||||
public class Range(public val startLine: EditorLine.Pointer, public val endLine: EditorLine.Pointer) : Line() {
|
||||
public fun lineAbove(): EditorLine.Pointer = listOf(startLine, endLine).minByOrNull { it.line }!!
|
||||
public fun lineBelow(): EditorLine.Pointer = listOf(startLine, endLine).maxByOrNull { it.line }!!
|
||||
}
|
||||
|
||||
public class Multiple(public val lines: List<Int>) : Line()
|
||||
|
||||
// TODO: 11.01.2022 How converting offsets to lines work?
|
||||
public class Offsets(public val startOffset: Offset, public val endOffset: Offset) : Line() {
|
||||
public fun offsetAbove(): Offset = min(startOffset.point, endOffset.point).offset
|
||||
public fun offsetBelow(): Offset = max(startOffset.point, endOffset.point).offset
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Character : VimRange() {
|
||||
public class Range(public val range: VimTextRange) : Character() {
|
||||
public fun offsetAbove(): Offset = min(range.start.point, range.end.point).offset
|
||||
public fun offsetBelow(): Offset = max(range.start.point, range.end.point).offset
|
||||
}
|
||||
|
||||
public class Multiple(public val ranges: List<VimTextRange>) : Character()
|
||||
}
|
||||
|
||||
public class Block(public val start: Offset, public val end: Offset) : VimRange()
|
||||
}
|
||||
|
||||
/**
|
||||
* `start` is not lower than `end`
|
||||
*/
|
||||
public data class VimTextRange(
|
||||
val start: Offset,
|
||||
val end: Offset,
|
||||
) {
|
||||
init {
|
||||
if (start.point > end.point) {
|
||||
println()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public infix fun Int.including(another: Int): VimTextRange {
|
||||
return VimTextRange(this.offset, another.offset)
|
||||
}
|
||||
|
||||
public data class Offset(val point: Int)
|
||||
public data class Pointer(val point: Int)
|
||||
|
||||
@ -85,47 +28,6 @@ public val Int.offset: Offset
|
||||
public val Int.pointer: Pointer
|
||||
get() = Pointer(this)
|
||||
|
||||
public interface VimMachine {
|
||||
public fun delete(range: VimRange, editor: VimEditor, caret: ImmutableVimCaret): OperatedRange?
|
||||
}
|
||||
|
||||
public abstract class VimMachineBase : VimMachine {
|
||||
/**
|
||||
* The information I'd like to know after the deletion:
|
||||
* - What range is deleted?
|
||||
* - What text is deleted?
|
||||
* - Does text have a new line character at the end?
|
||||
* - At what offset?
|
||||
* - What caret?
|
||||
*/
|
||||
public override fun delete(range: VimRange, editor: VimEditor, caret: ImmutableVimCaret): OperatedRange? {
|
||||
val operatedText = editor.deleteDryRun(range) ?: return null
|
||||
|
||||
val normalizedRange = operatedText.toNormalizedTextRange(editor)
|
||||
caret.registerStorage.storeText(editor, normalizedRange, operatedText.toType(), true)
|
||||
(editor as MutableVimEditor).delete(range)
|
||||
|
||||
val start = normalizedRange.startOffset
|
||||
injector.markService.setMark(caret, VimMarkConstants.MARK_CHANGE_POS, start)
|
||||
injector.markService.setChangeMarks(caret, TextRange(start, start + 1))
|
||||
|
||||
return operatedText
|
||||
}
|
||||
}
|
||||
|
||||
public fun OperatedRange.toNormalizedTextRange(editor: VimEditor): TextRange {
|
||||
return when (this) {
|
||||
is OperatedRange.Block -> TODO()
|
||||
is OperatedRange.Lines -> {
|
||||
// TODO: 11.01.2022 This is unsafe
|
||||
val startOffset = editor.getLineStartOffset(this.lineAbove.line)
|
||||
val endOffset = editor.getLineEndOffset(lineAbove.line + linesOperated, true)
|
||||
TextRange(startOffset, endOffset)
|
||||
}
|
||||
is OperatedRange.Characters -> TextRange(this.leftOffset.point, this.rightOffset.point)
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EditorLine private constructor(public val line: Int) {
|
||||
public class Pointer(line: Int) : EditorLine(line) {
|
||||
public companion object {
|
||||
|
Loading…
Reference in New Issue
Block a user