List<TextRange> (@NotNull String text, @NotNull TextRange range) { //System.out.println("text = " + text + " range = " + range); List<TextRange> result = new ArrayList<>(); int i = range.getStartOffset(); int s = -1; int prevType = Character.MATH_SYMBOL; while (i < range.getEndOffset()) { final char ch = text.charAt(i); if (ch >= '\u3040' && ch <= '\u309f' || // Hiragana ch >= '\u30A0' && ch <= '\u30ff' || // Katakana ch >= '\u4E00' && ch <= '\u9FFF' || // CJK Unified ideographs ch >= '\uF900' && ch <= '\uFAFF' || // CJK Compatibility Ideographs ch >= '\uFF00' && ch <= '\uFFEF' //Halfwidth and Fullwidth Forms of Katakana & Fullwidth ASCII variants ) { if (s >= 0) { add(text, result, i, s); s = -1; } prevType = Character.MATH_SYMBOL; ++i; continue; } final int type = Character.getType(ch); if (type == Character.LOWERCASE_LETTER || type == Character.UPPERCASE_LETTER || type == Character.TITLECASE_LETTER || type == Character.OTHER_LETTER || type == Character.MODIFIER_LETTER || type == Character.NON_SPACING_MARK || type == Character.OTHER_PUNCTUATION ) { //letter if (s < 0) { //start s = i; } else if (type == Character.UPPERCASE_LETTER && prevType == Character.LOWERCASE_LETTER) { //a|Camel add(text, result, i, s); s = i; } else if (i - s >= 1 && type == Character.LOWERCASE_LETTER && prevType == Character.UPPERCASE_LETTER) { //CAPITALN|ext add(text, result, i - 1, s); s = i - 1; } } else if (s >= 0) { //non-letter add(text, result, i, s); s = -1; } prevType = type; i++; } //remainder if (s >= 0) { add(text, result, i, s); } return result; }