Merge "Add looksValidForDictionaryInsertion"

main
Jean Chalard 2013-08-14 09:41:48 +00:00 committed by Android (Google) Code Review
commit 5fd8b7ebd5
4 changed files with 102 additions and 10 deletions

View File

@ -1355,10 +1355,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
} }
private static boolean isAlphabet(final int code) {
return Character.isLetter(code);
}
private void onSettingsKeyPressed() { private void onSettingsKeyPressed() {
if (isShowingOptionDialog()) return; if (isShowingOptionDialog()) return;
showSubtypeSelectorAndSettings(); showSubtypeSelectorAndSettings();
@ -2001,8 +1997,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// NOTE: isCursorTouchingWord() is a blocking IPC call, so it often takes several // NOTE: isCursorTouchingWord() is a blocking IPC call, so it often takes several
// dozen milliseconds. Avoid calling it as much as possible, since we are on the UI // dozen milliseconds. Avoid calling it as much as possible, since we are on the UI
// thread here. // thread here.
if (!isComposingWord && (isAlphabet(primaryCode) if (!isComposingWord && currentSettings.isWordCodePoint(primaryCode)
|| currentSettings.isWordConnector(primaryCode))
&& currentSettings.isSuggestionsRequested(mDisplayOrientation) && && currentSettings.isSuggestionsRequested(mDisplayOrientation) &&
!mConnection.isCursorTouchingWord(currentSettings)) { !mConnection.isCursorTouchingWord(currentSettings)) {
// Reset entirely the composing state anyway, then start composing a new word unless // Reset entirely the composing state anyway, then start composing a new word unless

View File

@ -22,6 +22,7 @@ import android.content.res.Resources;
import android.util.Log; import android.util.Log;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.keyboard.internal.KeySpecParser; import com.android.inputmethod.keyboard.internal.KeySpecParser;
import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.InputAttributes; import com.android.inputmethod.latin.InputAttributes;
@ -170,6 +171,55 @@ public final class SettingsValues {
mIsInternal = Settings.isInternal(prefs); mIsInternal = Settings.isInternal(prefs);
} }
// Only for tests
private SettingsValues(final Locale locale) {
// TODO: locale is saved, but not used yet. May have to change this if tests require.
mLocale = locale;
mDelayUpdateOldSuggestions = 0;
mSymbolsPrecededBySpace = new int[] { '(', '[', '{', '&' };
Arrays.sort(mSymbolsPrecededBySpace);
mSymbolsFollowedBySpace = new int[] { '.', ',', ';', ':', '!', '?', ')', ']', '}', '&' };
Arrays.sort(mSymbolsFollowedBySpace);
mWordConnectors = new int[] { '\'', '-' };
Arrays.sort(mWordConnectors);
final String[] suggestPuncsSpec = new String[] { "!", "?", ",", ":", ";" };
mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec);
mWordSeparators = "&\t \n()[]{}*&<>+=|.,;:!?/_\"";
mHintToSaveText = "Touch again to save";
mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */);
mAutoCap = true;
mVibrateOn = true;
mSoundOn = true;
mKeyPreviewPopupOn = true;
mSlidingKeyInputPreviewEnabled = true;
mVoiceMode = "0";
mIncludesOtherImesInLanguageSwitchList = false;
mShowsLanguageSwitchKey = true;
mUseContactsDict = true;
mUseDoubleSpacePeriod = true;
mBlockPotentiallyOffensive = true;
mAutoCorrectEnabled = true;
mBigramPredictionEnabled = true;
mKeyLongpressTimeout = 300;
mKeypressVibrationDuration = 5;
mKeypressSoundVolume = 1;
mKeyPreviewPopupDismissDelay = 70;
mAutoCorrectionThreshold = 1;
mVoiceKeyEnabled = true;
mVoiceKeyOnMain = true;
mGestureInputEnabled = true;
mGestureTrailEnabled = true;
mGestureFloatingPreviewTextEnabled = true;
mCorrectionEnabled = mAutoCorrectEnabled && !mInputAttributes.mInputTypeNoAutoCorrect;
mSuggestionVisibility = 0;
mIsInternal = false;
}
@UsedForTesting
public static SettingsValues makeDummySettingsValuesForTest(final Locale locale) {
return new SettingsValues(locale);
}
public boolean isApplicationSpecifiedCompletionsOn() { public boolean isApplicationSpecifiedCompletionsOn() {
return mInputAttributes.mApplicationSpecifiedCompletionOn; return mInputAttributes.mApplicationSpecifiedCompletionOn;
} }
@ -194,6 +244,10 @@ public final class SettingsValues {
return Arrays.binarySearch(mWordConnectors, code) >= 0; return Arrays.binarySearch(mWordConnectors, code) >= 0;
} }
public boolean isWordCodePoint(final int code) {
return Character.isLetter(code) || isWordConnector(code);
}
public boolean isUsuallyPrecededBySpace(final int code) { public boolean isUsuallyPrecededBySpace(final int code) {
return Arrays.binarySearch(mSymbolsPrecededBySpace, code) >= 0; return Arrays.binarySearch(mSymbolsPrecededBySpace, code) >= 0;
} }

View File

@ -19,6 +19,7 @@ package com.android.inputmethod.latin.utils;
import android.text.TextUtils; import android.text.TextUtils;
import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.settings.SettingsValues;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Locale; import java.util.Locale;
@ -193,27 +194,55 @@ public final class StringUtils {
} }
public static boolean isIdenticalAfterUpcase(final String text) { public static boolean isIdenticalAfterUpcase(final String text) {
final int len = text.length(); final int length = text.length();
for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) { int i = 0;
while (i < length) {
final int codePoint = text.codePointAt(i); final int codePoint = text.codePointAt(i);
if (Character.isLetter(codePoint) && !Character.isUpperCase(codePoint)) { if (Character.isLetter(codePoint) && !Character.isUpperCase(codePoint)) {
return false; return false;
} }
i += Character.charCount(codePoint);
} }
return true; return true;
} }
public static boolean isIdenticalAfterDowncase(final String text) { public static boolean isIdenticalAfterDowncase(final String text) {
final int len = text.length(); final int length = text.length();
for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) { int i = 0;
while (i < length) {
final int codePoint = text.codePointAt(i); final int codePoint = text.codePointAt(i);
if (Character.isLetter(codePoint) && !Character.isLowerCase(codePoint)) { if (Character.isLetter(codePoint) && !Character.isLowerCase(codePoint)) {
return false; return false;
} }
i += Character.charCount(codePoint);
} }
return true; return true;
} }
public static boolean looksValidForDictionaryInsertion(final CharSequence text,
final SettingsValues settings) {
if (TextUtils.isEmpty(text)) return false;
final int length = text.length();
int i = 0;
int digitCount = 0;
while (i < length) {
final int codePoint = Character.codePointAt(text, i);
final int charCount = Character.charCount(codePoint);
i += charCount;
if (Character.isDigit(codePoint)) {
// Count digits: see below
digitCount += charCount;
continue;
}
if (!settings.isWordCodePoint(codePoint)) return false;
}
// We reject strings entirely comprised of digits to avoid using PIN codes or credit
// card numbers. It would come in handy for word prediction though; a good example is
// when writing one's address where the street number is usually quite discriminative,
// as well as the postal code.
return digitCount < length;
}
public static boolean isIdenticalAfterCapitalizeEachWord(final String text, public static boolean isIdenticalAfterCapitalizeEachWord(final String text,
final String separators) { final String separators) {
boolean needCapsNext = true; boolean needCapsNext = true;

View File

@ -16,6 +16,8 @@
package com.android.inputmethod.latin.utils; package com.android.inputmethod.latin.utils;
import com.android.inputmethod.latin.settings.SettingsValues;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.SmallTest;
@ -183,6 +185,18 @@ public class StringUtilsTests extends AndroidTestCase {
assertTrue(StringUtils.isIdenticalAfterDowncase("")); assertTrue(StringUtils.isIdenticalAfterDowncase(""));
} }
public void testLooksValidForDictionaryInsertion() {
final SettingsValues settings =
SettingsValues.makeDummySettingsValuesForTest(Locale.ENGLISH);
assertTrue(StringUtils.looksValidForDictionaryInsertion("aochaueo", settings));
assertFalse(StringUtils.looksValidForDictionaryInsertion("", settings));
assertTrue(StringUtils.looksValidForDictionaryInsertion("ao-ch'aueo", settings));
assertFalse(StringUtils.looksValidForDictionaryInsertion("2908743256", settings));
assertTrue(StringUtils.looksValidForDictionaryInsertion("31aochaueo", settings));
assertFalse(StringUtils.looksValidForDictionaryInsertion("akeo raeoch oerch .", settings));
assertFalse(StringUtils.looksValidForDictionaryInsertion("!!!", settings));
}
private static void checkCapitalize(final String src, final String dst, final String separators, private static void checkCapitalize(final String src, final String dst, final String separators,
final Locale locale) { final Locale locale) {
assertEquals(dst, StringUtils.capitalizeEachWord(src, separators, locale)); assertEquals(dst, StringUtils.capitalizeEachWord(src, separators, locale));