private static int findNextWordOne( CharSequence chars, int pos, int size, int step, boolean skipPunc, boolean spaceWords) { boolean found = false; pos = pos < size ? pos : size - 1; // For back searches, skip any current whitespace so we start at the end of a word if (step < 0 && pos > 0) { if (CharacterHelper.charType(chars.charAt(pos - 1), skipPunc) == CharacterHelper.TYPE_SPACE && !spaceWords) { pos = skipSpace(chars, pos - 1, step, size) + 1; } if (CharacterHelper.charType(chars.charAt(pos), skipPunc) != CharacterHelper.charType(chars.charAt(pos - 1), skipPunc)) { pos += step; } } int res = pos; if (pos < 0 || pos >= size) { return pos; } int type = CharacterHelper.charType(chars.charAt(pos), skipPunc); if (type == CharacterHelper.TYPE_SPACE && step < 0 && pos > 0 && !spaceWords) { type = CharacterHelper.charType(chars.charAt(pos - 1), skipPunc); } pos += step; while (pos >= 0 && pos < size && !found) { int newType = CharacterHelper.charType(chars.charAt(pos), skipPunc); if (newType != type) { if (newType == CharacterHelper.TYPE_SPACE && step >= 0 && !spaceWords) { pos = skipSpace(chars, pos, step, size); res = pos; } else if (step < 0) { res = pos + 1; } else { res = pos; } type = CharacterHelper.charType(chars.charAt(res), skipPunc); found = true; } pos += step; } if (found) { if (res < 0) // (pos <= 0) { res = 0; } else if (res >= size) // (pos >= size) { res = size - 1; } } else if (pos <= 0) { res = 0; } return res; }
/** * 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 * @return The text range of the found word or null if there is no word under/after the cursor on * the line */ public static TextRange findWordUnderCursor(Editor editor) { CharSequence chars = EditorHelper.getDocumentChars(editor); int stop = EditorHelper.getLineEndOffset(editor, EditorHelper.getCurrentLogicalLine(editor), true); int pos = editor.getCaretModel().getOffset(); int start = pos; int[] types = new int[] {CharacterHelper.TYPE_CHAR, CharacterHelper.TYPE_PUNC}; for (int i = 0; i < 2; i++) { start = pos; int type = CharacterHelper.charType(chars.charAt(start), false); if (type == types[i]) { // Search back for start of word while (start > 0 && CharacterHelper.charType(chars.charAt(start - 1), false) == types[i]) { start--; } } else { // Search forward for start of word while (start < stop && CharacterHelper.charType(chars.charAt(start), false) != types[i]) { start++; } } if (start != stop) { break; } } if (start == stop) { return null; } int end; // Special case 1 character words because 'findNextWordEnd' returns one to many chars if (start < stop && CharacterHelper.charType(chars.charAt(start + 1), false) != CharacterHelper.TYPE_CHAR) { end = start + 1; } else { end = findNextWordEnd(chars, start, stop, 1, false, false, false) + 1; } return new TextRange(start, end); }
/** * This skips whitespace starting with the supplied position. * * @param chars The text as a character array * @param offset The starting position * @param step The direction to move * @param size The size of the document * @return The new position. This will be the first non-whitespace character found */ public static int skipSpace(CharSequence chars, int offset, int step, int size) { while (offset >= 0 && offset < size) { if (CharacterHelper.charType(chars.charAt(offset), false) != CharacterHelper.TYPE_SPACE) { break; } offset += step; } return offset; }
public static TextRange findWordUnderCursor( Editor editor, int count, int dir, boolean isOuter, boolean isBig, boolean hasSelection) { if (logger.isDebugEnabled()) { logger.debug("count=" + count); logger.debug("dir=" + dir); logger.debug("isOuter=" + isOuter); logger.debug("isBig=" + isBig); logger.debug("hasSelection=" + hasSelection); } CharSequence chars = EditorHelper.getDocumentChars(editor); // int min = EditorHelper.getLineStartOffset(editor, // EditorHelper.getCurrentLogicalLine(editor)); // int max = EditorHelper.getLineEndOffset(editor, EditorHelper.getCurrentLogicalLine(editor), // true); int min = 0; int max = EditorHelper.getFileSize(editor); if (logger.isDebugEnabled()) { logger.debug("min=" + min); logger.debug("max=" + max); } int pos = editor.getCaretModel().getOffset(); boolean startSpace = CharacterHelper.charType(chars.charAt(pos), isBig) == CharacterHelper.TYPE_SPACE; // Find word start boolean onWordStart = pos == min || CharacterHelper.charType(chars.charAt(pos - 1), isBig) != CharacterHelper.charType(chars.charAt(pos), isBig); int start = pos; if (logger.isDebugEnabled()) { logger.debug("pos=" + pos); logger.debug("onWordStart=" + onWordStart); } if ((!onWordStart && !(startSpace && isOuter)) || hasSelection || (count > 1 && dir == -1)) { if (dir == 1) { start = findNextWord(chars, pos, max, -1, isBig, !isOuter); } else { start = findNextWord( chars, pos, max, -(count - (onWordStart && !hasSelection ? 1 : 0)), isBig, !isOuter); } start = EditorHelper.normalizeOffset(editor, start, false); } if (logger.isDebugEnabled()) logger.debug("start=" + start); // Find word end boolean onWordEnd = pos == max || CharacterHelper.charType(chars.charAt(pos + 1), isBig) != CharacterHelper.charType(chars.charAt(pos), isBig); if (logger.isDebugEnabled()) logger.debug("onWordEnd=" + onWordEnd); int end = pos; if (!onWordEnd || hasSelection || (count > 1 && dir == 1) || (startSpace && isOuter)) { if (dir == 1) { end = findNextWordEnd( chars, pos, max, count - (onWordEnd && !hasSelection && (!(startSpace && isOuter) || (startSpace && !isOuter)) ? 1 : 0), isBig, true, !isOuter); } else { end = findNextWordEnd(chars, pos, max, 1, isBig, true, !isOuter); } } if (logger.isDebugEnabled()) logger.debug("end=" + end); boolean goBack = (startSpace && !hasSelection) || (!startSpace && hasSelection && !onWordStart); if (dir == 1 && isOuter) { int firstEnd = end; if (count > 1) { firstEnd = findNextWordEnd(chars, pos, max, 1, isBig, true, false); } if (firstEnd < max) { if (CharacterHelper.charType(chars.charAt(firstEnd + 1), false) != CharacterHelper.TYPE_SPACE) { goBack = true; } } } if (dir == -1 && isOuter && startSpace) { if (pos > min) { if (CharacterHelper.charType(chars.charAt(pos - 1), false) != CharacterHelper.TYPE_SPACE) { goBack = true; } } } boolean goForward = (dir == 1 && isOuter && ((!startSpace && !onWordEnd) || (startSpace && onWordEnd && hasSelection))); if (!goForward && dir == 1 && isOuter) { int firstEnd = end; if (count > 1) { firstEnd = findNextWordEnd(chars, pos, max, 1, isBig, true, false); } if (firstEnd < max) { if (CharacterHelper.charType(chars.charAt(firstEnd + 1), false) != CharacterHelper.TYPE_SPACE) { goForward = true; } } } if (!goForward && dir == 1 && isOuter && !startSpace && !hasSelection) { if (end < max) { if (CharacterHelper.charType(chars.charAt(end + 1), !isBig) != CharacterHelper.charType(chars.charAt(end), !isBig)) { goForward = true; } } } if (logger.isDebugEnabled()) { logger.debug("goBack=" + goBack); logger.debug("goForward=" + goForward); } if (goForward) { while (end < max && CharacterHelper.charType(chars.charAt(end + 1), false) == CharacterHelper.TYPE_SPACE) { end++; } } if (goBack) { while (start > min && CharacterHelper.charType(chars.charAt(start - 1), false) == CharacterHelper.TYPE_SPACE) { start--; } } if (logger.isDebugEnabled()) { logger.debug("start=" + start); logger.debug("end=" + end); } return new TextRange(start, end); }