mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-05-08 06:34:08 +02:00
Reduce multiple implementations to one
This commit is contained in:
parent
c4f56c40fd
commit
43a2bd98db
src/main/java/com/maddyhome/idea/vim
vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api
@ -34,7 +34,6 @@ import com.maddyhome.idea.vim.helper.SearchOptions
|
||||
import com.maddyhome.idea.vim.helper.endOffsetInclusive
|
||||
import com.maddyhome.idea.vim.helper.enumSetOf
|
||||
import com.maddyhome.idea.vim.helper.exitVisualMode
|
||||
import com.maddyhome.idea.vim.helper.findWordUnderCursor
|
||||
import com.maddyhome.idea.vim.helper.inVisualMode
|
||||
import com.maddyhome.idea.vim.helper.updateCaretsVisualAttributes
|
||||
import com.maddyhome.idea.vim.helper.userData
|
||||
@ -235,7 +234,7 @@ internal class VimMultipleCursorsExtension : VimExtension {
|
||||
val text = if (editor.inVisualMode) {
|
||||
primaryCaret.selectedText ?: return
|
||||
} else {
|
||||
val range = findWordUnderCursor(editor, primaryCaret) ?: return
|
||||
val range = injector.searchHelper.findWordNearestCursor(editor.vim, primaryCaret.vim) ?: return
|
||||
if (range.startOffset > primaryCaret.offset) return
|
||||
IjVimEditor(editor).getText(range)
|
||||
}
|
||||
@ -300,7 +299,8 @@ internal class VimMultipleCursorsExtension : VimExtension {
|
||||
}
|
||||
|
||||
private fun selectWordUnderCaret(editor: Editor, caret: Caret): TextRange? {
|
||||
val range = findWordUnderCursor(editor, caret) ?: return null
|
||||
// TODO: I think vim-multiple-cursors uses a text object rather than the star operator
|
||||
val range = injector.searchHelper.findWordNearestCursor(editor.vim, caret.vim) ?: return null
|
||||
if (range.startOffset > caret.offset) return null
|
||||
|
||||
enterVisualMode(editor.vim)
|
||||
|
@ -10,15 +10,10 @@ package com.maddyhome.idea.vim.helper
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
||||
import com.intellij.openapi.editor.Caret
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.spellchecker.SpellCheckerSeveritiesProvider
|
||||
import com.maddyhome.idea.vim.api.getLineEndOffset
|
||||
import com.maddyhome.idea.vim.api.globalOptions
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.common.TextRange
|
||||
import com.maddyhome.idea.vim.helper.CharacterHelper.charType
|
||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||
import it.unimi.dsi.fastutil.ints.IntComparator
|
||||
import it.unimi.dsi.fastutil.ints.IntIterator
|
||||
import it.unimi.dsi.fastutil.ints.IntRBTreeSet
|
||||
@ -50,64 +45,6 @@ private fun containsUpperCase(pattern: String): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the word under the cursor or the next word to the right of the cursor on the current line.
|
||||
*
|
||||
* @param editor The editor to find the word in
|
||||
* @param caret The caret to find word under
|
||||
* @return The text range of the found word or null if there is no word under/after the cursor on the line
|
||||
*/
|
||||
fun findWordUnderCursor(editor: Editor, caret: Caret): TextRange? {
|
||||
val vimEditor = IjVimEditor(editor)
|
||||
val chars = editor.document.charsSequence
|
||||
val stop = vimEditor.getLineEndOffset(caret.logicalPosition.line, true)
|
||||
|
||||
val pos = caret.offset
|
||||
// Technically the first condition is covered by the second one, but let it be
|
||||
if (chars.length == 0 || chars.length <= pos) return null
|
||||
|
||||
//if (pos == chars.length() - 1) return new TextRange(chars.length() - 1, chars.length());
|
||||
var start = pos
|
||||
val types = arrayOf(
|
||||
CharacterHelper.CharacterType.KEYWORD,
|
||||
CharacterHelper.CharacterType.PUNCTUATION
|
||||
)
|
||||
for (i in 0..1) {
|
||||
start = pos
|
||||
val type = charType(vimEditor, chars[start], false)
|
||||
if (type == types[i]) {
|
||||
// Search back for start of word
|
||||
while (start > 0 && charType(vimEditor, chars[start - 1], false) == types[i]) {
|
||||
start--
|
||||
}
|
||||
} else {
|
||||
// Search forward for start of word
|
||||
while (start < stop && charType(vimEditor, chars[start], false) != types[i]) {
|
||||
start++
|
||||
}
|
||||
}
|
||||
|
||||
if (start != stop) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (start == stop) {
|
||||
return null
|
||||
}
|
||||
// Special case 1 character words because 'findNextWordEnd' returns one to many chars
|
||||
val end = if (start < stop &&
|
||||
(start >= chars.length - 1 ||
|
||||
charType(vimEditor, chars[start + 1], false) != CharacterHelper.CharacterType.KEYWORD)
|
||||
) {
|
||||
start + 1
|
||||
} else {
|
||||
injector.searchHelper.findNextWordEnd(vimEditor, start, 1, false, false) + 1
|
||||
}
|
||||
|
||||
return TextRange(start, end)
|
||||
}
|
||||
|
||||
fun findMisspelledWords(
|
||||
editor: Editor,
|
||||
startOffset: Int,
|
||||
|
@ -13,7 +13,6 @@ import com.maddyhome.idea.vim.common.Direction
|
||||
import com.maddyhome.idea.vim.common.TextRange
|
||||
import com.maddyhome.idea.vim.ex.ExException
|
||||
import com.maddyhome.idea.vim.ex.ranges.LineRange
|
||||
import com.maddyhome.idea.vim.helper.CharacterHelper
|
||||
import com.maddyhome.idea.vim.helper.Msg
|
||||
import com.maddyhome.idea.vim.helper.SearchOptions
|
||||
import com.maddyhome.idea.vim.helper.enumSetOf
|
||||
@ -427,7 +426,7 @@ abstract class VimSearchGroupBase : VimSearchGroup {
|
||||
whole: Boolean,
|
||||
dir: Direction,
|
||||
): Int {
|
||||
val range: TextRange = findWordUnderCursor(editor, caret) ?: return -1
|
||||
val range = injector.searchHelper.findWordNearestCursor(editor, caret) ?: return -1
|
||||
|
||||
val start = range.startOffset
|
||||
val end = range.endOffset
|
||||
@ -571,62 +570,6 @@ abstract class VimSearchGroupBase : VimSearchGroup {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the word under the cursor or the next word to the right of the cursor on the current line.
|
||||
*
|
||||
* @param editor The editor to find the word in
|
||||
* @param caret The caret to find word under
|
||||
* @return The text range of the found word or null if there is no word under/after the cursor on the line
|
||||
*/
|
||||
private fun findWordUnderCursor(
|
||||
editor: VimEditor,
|
||||
caret: ImmutableVimCaret,
|
||||
): TextRange? {
|
||||
|
||||
val stop: Int = editor.getLineEndOffset(caret.getBufferPosition().line, true)
|
||||
val pos: Int = caret.offset
|
||||
|
||||
// Technically the first condition is covered by the second one, but let it be
|
||||
if (editor.text().isEmpty() || editor.text().length <= pos) return null
|
||||
//if (pos == chars.length() - 1) return new TextRange(chars.length() - 1, chars.length());
|
||||
var start = pos
|
||||
val types = arrayOf(
|
||||
CharacterHelper.CharacterType.KEYWORD,
|
||||
CharacterHelper.CharacterType.PUNCTUATION
|
||||
)
|
||||
for (i in 0..1) {
|
||||
start = pos
|
||||
val type = CharacterHelper.charType(editor, editor.text()[start], false)
|
||||
if (type === types[i]) {
|
||||
// Search back for start of word
|
||||
while (start > 0 && CharacterHelper.charType(editor, editor.text()[start - 1], false) === types[i]) {
|
||||
start--
|
||||
}
|
||||
} else {
|
||||
// Search forward for start of word
|
||||
while (start < stop && CharacterHelper.charType(editor, editor.text()[start], false) !== types[i]) {
|
||||
start++
|
||||
}
|
||||
}
|
||||
if (start != stop) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (start == stop) {
|
||||
return null
|
||||
}
|
||||
// Special case 1 character words because 'findNextWordEnd' returns one to many chars
|
||||
val end: Int = if (start < stop &&
|
||||
(start >= editor.text().length - 1 ||
|
||||
CharacterHelper.charType(editor, editor.text()[start + 1], false) !== CharacterHelper.CharacterType.KEYWORD)
|
||||
) {
|
||||
start + 1
|
||||
} else {
|
||||
injector.searchHelper.findNextWordEnd(editor, start, 1, bigWord = false) + 1
|
||||
}
|
||||
return TextRange(start, end)
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Substitute related methods */
|
||||
/****************************************************************************/
|
||||
|
@ -195,6 +195,20 @@ interface VimSearchHelper {
|
||||
ch: Char,
|
||||
): Int
|
||||
|
||||
/**
|
||||
* Find the word at or nearest to the current caret offset
|
||||
*
|
||||
* Note that this is not a word text object!
|
||||
*
|
||||
* This function is used to get the word to search for using the `*`/`#` and `g*`/`g#` operators. It will return:
|
||||
* * the range of the keyword under the cursor
|
||||
* * or the first keyword after the cursor on the current line,
|
||||
* * or the non-blank word under the cursor,
|
||||
* * or the first non-blank word after the cursor on the current line
|
||||
* * or null, if none of the above are found
|
||||
*/
|
||||
fun findWordNearestCursor(editor: VimEditor, caret: ImmutableVimCaret): TextRange?
|
||||
|
||||
/**
|
||||
* Find the range of the word text object at the location of the caret
|
||||
*/
|
||||
|
@ -94,6 +94,56 @@ abstract class VimSearchHelperBase : VimSearchHelper {
|
||||
}
|
||||
}
|
||||
|
||||
override fun findWordNearestCursor(editor: VimEditor, caret: ImmutableVimCaret): TextRange? {
|
||||
val chars = editor.text()
|
||||
val stop = editor.getLineEndOffset(caret.getBufferPosition().line, true)
|
||||
|
||||
val pos = caret.offset
|
||||
|
||||
if (chars.isEmpty() || chars.length <= pos) return null
|
||||
|
||||
var start = pos
|
||||
val types = arrayOf(
|
||||
CharacterHelper.CharacterType.KEYWORD,
|
||||
CharacterHelper.CharacterType.PUNCTUATION
|
||||
)
|
||||
for (i in 0..1) {
|
||||
start = pos
|
||||
val type = charType(editor, chars[start], false)
|
||||
if (type == types[i]) {
|
||||
// Search back for start of word
|
||||
while (start > 0 && charType(editor, chars[start - 1], false) == types[i]) {
|
||||
start--
|
||||
}
|
||||
} else {
|
||||
// Search forward for start of word
|
||||
while (start < stop && charType(editor, chars[start], false) != types[i]) {
|
||||
start++
|
||||
}
|
||||
}
|
||||
|
||||
if (start != stop) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (start == stop) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Special case 1 character words because 'findNextWordEnd' returns one to many chars
|
||||
val end = if (start < stop &&
|
||||
(start >= chars.length - 1 ||
|
||||
charType(editor, chars[start + 1], false) != CharacterHelper.CharacterType.KEYWORD)
|
||||
) {
|
||||
start + 1
|
||||
} else {
|
||||
injector.searchHelper.findNextWordEnd(editor, start, 1, false, false) + 1
|
||||
}
|
||||
|
||||
return TextRange(start, end)
|
||||
}
|
||||
|
||||
override fun findNextWord(
|
||||
editor: VimEditor,
|
||||
searchFrom: Int,
|
||||
|
Loading…
Reference in New Issue
Block a user