|
|
|
@ -19,7 +19,10 @@ import com.maddyhome.idea.vim.api.getLeadingCharacterOffset
|
|
|
|
|
import com.maddyhome.idea.vim.api.injector
|
|
|
|
|
import com.maddyhome.idea.vim.api.setChangeMarks
|
|
|
|
|
import com.maddyhome.idea.vim.command.MappingMode
|
|
|
|
|
import com.maddyhome.idea.vim.state.mode.Mode
|
|
|
|
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
|
|
|
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
|
|
|
|
import com.maddyhome.idea.vim.state.mode.selectionType
|
|
|
|
|
import com.maddyhome.idea.vim.common.TextRange
|
|
|
|
|
import com.maddyhome.idea.vim.extension.ExtensionHandler
|
|
|
|
|
import com.maddyhome.idea.vim.extension.VimExtension
|
|
|
|
@ -31,6 +34,7 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMa
|
|
|
|
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
|
|
|
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
|
|
|
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegisterForCaret
|
|
|
|
|
import com.maddyhome.idea.vim.state.mode.mode
|
|
|
|
|
import com.maddyhome.idea.vim.helper.runWithEveryCaretAndRestore
|
|
|
|
|
import com.maddyhome.idea.vim.key.OperatorFunction
|
|
|
|
|
import com.maddyhome.idea.vim.newapi.IjVimCaret
|
|
|
|
@ -39,10 +43,6 @@ import com.maddyhome.idea.vim.newapi.ij
|
|
|
|
|
import com.maddyhome.idea.vim.newapi.vim
|
|
|
|
|
import com.maddyhome.idea.vim.options.helpers.ClipboardOptionHelper
|
|
|
|
|
import com.maddyhome.idea.vim.put.PutData
|
|
|
|
|
import com.maddyhome.idea.vim.state.mode.Mode
|
|
|
|
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
|
|
|
|
import com.maddyhome.idea.vim.state.mode.mode
|
|
|
|
|
import com.maddyhome.idea.vim.state.mode.selectionType
|
|
|
|
|
import org.jetbrains.annotations.NonNls
|
|
|
|
|
import java.awt.event.KeyEvent
|
|
|
|
|
import javax.swing.KeyStroke
|
|
|
|
@ -83,7 +83,7 @@ internal class VimSurroundExtension : VimExtension {
|
|
|
|
|
override val isRepeatable = true
|
|
|
|
|
|
|
|
|
|
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
|
|
|
|
setOperatorFunction(Operator(supportsMultipleCursors = false, count = 1)) // TODO
|
|
|
|
|
setOperatorFunction(Operator(supportsMultipleCursors = false)) // TODO
|
|
|
|
|
executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -104,7 +104,7 @@ internal class VimSurroundExtension : VimExtension {
|
|
|
|
|
val lastNonWhiteSpaceOffset = getLastNonWhitespaceCharacterOffset(editor.text(), lineStartOffset, lineEndOffset)
|
|
|
|
|
if (lastNonWhiteSpaceOffset != null) {
|
|
|
|
|
val range = TextRange(lineStartOffset, lastNonWhiteSpaceOffset + 1)
|
|
|
|
|
performSurround(pair, range, it, count = operatorArguments.count1)
|
|
|
|
|
performSurround(pair, range, it)
|
|
|
|
|
}
|
|
|
|
|
// it.moveToOffset(lineStartOffset)
|
|
|
|
|
}
|
|
|
|
@ -125,7 +125,7 @@ internal class VimSurroundExtension : VimExtension {
|
|
|
|
|
private class VSurroundHandler : ExtensionHandler {
|
|
|
|
|
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
|
|
|
|
// NB: Operator ignores SelectionType anyway
|
|
|
|
|
if (!Operator(supportsMultipleCursors = true, count = operatorArguments.count1).apply(editor, context, editor.mode.selectionType)) {
|
|
|
|
|
if (!Operator(supportsMultipleCursors = true).apply(editor, context, editor.mode.selectionType)) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
runWriteAction {
|
|
|
|
@ -261,7 +261,7 @@ internal class VimSurroundExtension : VimExtension {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class Operator(private val supportsMultipleCursors: Boolean, private val count: Int) : OperatorFunction {
|
|
|
|
|
private class Operator(private val supportsMultipleCursors: Boolean) : OperatorFunction {
|
|
|
|
|
override fun apply(vimEditor: VimEditor, context: ExecutionContext, selectionType: SelectionType?): Boolean {
|
|
|
|
|
val editor = vimEditor.ij
|
|
|
|
|
val c = getChar(editor)
|
|
|
|
@ -273,11 +273,11 @@ internal class VimSurroundExtension : VimExtension {
|
|
|
|
|
val change = VimPlugin.getChange()
|
|
|
|
|
if (supportsMultipleCursors) {
|
|
|
|
|
editor.runWithEveryCaretAndRestore {
|
|
|
|
|
applyOnce(editor, change, pair, count)
|
|
|
|
|
applyOnce(editor, change, pair)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
applyOnce(editor, change, pair, count)
|
|
|
|
|
applyOnce(editor, change, pair)
|
|
|
|
|
// Jump back to start
|
|
|
|
|
executeNormalWithoutMapping(injector.parser.parseKeys("`["), editor)
|
|
|
|
|
}
|
|
|
|
@ -285,15 +285,18 @@ internal class VimSurroundExtension : VimExtension {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun applyOnce(editor: Editor, change: VimChangeGroup, pair: Pair<String, String>, count: Int) {
|
|
|
|
|
private fun applyOnce(editor: Editor, change: VimChangeGroup, pair: Pair<String, String>) {
|
|
|
|
|
// XXX: Will it work with line-wise or block-wise selections?
|
|
|
|
|
val primaryCaret = editor.caretModel.primaryCaret
|
|
|
|
|
val range = getSurroundRange(primaryCaret.vim)
|
|
|
|
|
if (range != null) {
|
|
|
|
|
val start = RepeatedCharSequence.of(pair.first, count)
|
|
|
|
|
val end = RepeatedCharSequence.of(pair.second, count)
|
|
|
|
|
change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.startOffset, start)
|
|
|
|
|
change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.endOffset + start.length, end)
|
|
|
|
|
change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.startOffset, pair.first)
|
|
|
|
|
change.insertText(
|
|
|
|
|
IjVimEditor(editor),
|
|
|
|
|
IjVimCaret(primaryCaret),
|
|
|
|
|
range.endOffset + pair.first.length,
|
|
|
|
|
pair.second
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -375,15 +378,15 @@ internal class VimSurroundExtension : VimExtension {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun performSurround(pair: Pair<String, String>, range: TextRange, caret: VimCaret, count: Int, tagsOnNewLines: Boolean = false) {
|
|
|
|
|
private fun performSurround(pair: Pair<String, String>, range: TextRange, caret: VimCaret, tagsOnNewLines: Boolean = false) {
|
|
|
|
|
runWriteAction {
|
|
|
|
|
val editor = caret.editor
|
|
|
|
|
val change = VimPlugin.getChange()
|
|
|
|
|
val leftSurround = RepeatedCharSequence.of(pair.first + if (tagsOnNewLines) "\n" else "", count)
|
|
|
|
|
val leftSurround = pair.first + if (tagsOnNewLines) "\n" else ""
|
|
|
|
|
|
|
|
|
|
val isEOF = range.endOffset == editor.text().length
|
|
|
|
|
val hasNewLine = editor.endsWithNewLine()
|
|
|
|
|
val rightSurround = (if (tagsOnNewLines) {
|
|
|
|
|
val rightSurround = if (tagsOnNewLines) {
|
|
|
|
|
if (isEOF && !hasNewLine) {
|
|
|
|
|
"\n" + pair.second
|
|
|
|
|
} else {
|
|
|
|
@ -391,7 +394,7 @@ internal class VimSurroundExtension : VimExtension {
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
pair.second
|
|
|
|
|
}).let { RepeatedCharSequence.of(it, count) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
change.insertText(editor, caret, range.startOffset, leftSurround)
|
|
|
|
|
change.insertText(editor, caret, range.endOffset + leftSurround.length, rightSurround)
|
|
|
|
|