Introduce clustering punctuation

Bug: 10081730
Change-Id: If198fa3df68ecb267da0a278da41fd509d6165f1
main
Jean Chalard 2014-05-01 12:33:59 +09:00
parent 879629af3c
commit 29c00ff538
6 changed files with 49 additions and 10 deletions

View File

@ -22,6 +22,8 @@
<string name="symbols_preceded_by_space">([{&amp;;:!?</string>
<!-- Symbols that are normally followed by a space (used to add an auto-space after these) -->
<string name="symbols_followed_by_space">.,;:!?)]}&amp;</string>
<!-- Symbols that behave like a single punctuation when typed next to each other -->
<string name="symbols_clustering_together">!?</string>
<!-- Symbols that separate words -->
<!-- Don't remove the enclosing double quotes, they protect whitespace (not just U+0020) -->
<string name="symbols_word_separators">"&#x0009;&#x0020;&#x000A;&#x00A0;"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"</string>

View File

@ -26,6 +26,8 @@
<string name="symbols_preceded_by_space">([{&amp;</string>
<!-- Symbols that are normally followed by a space (used to add an auto-space after these) -->
<string name="symbols_followed_by_space">.,;:!?)]}&amp;</string>
<!-- Symbols that behave like a single punctuation when typed next to each other -->
<string name="symbols_clustering_together"></string>
<!-- Symbols that separate words -->
<!-- Don't remove the enclosing double quotes, they protect whitespace (not just U+0020) -->
<string name="symbols_word_separators">"&#x0009;&#x0020;&#x000A;&#x00A0;"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"</string>

View File

@ -784,11 +784,11 @@ public final class InputLogic {
// TODO: remove this argument
final LatinIME.UIHandler handler) {
final int codePoint = inputTransaction.mEvent.mCodePoint;
final SettingsValues settingsValues = inputTransaction.mSettingsValues;
boolean didAutoCorrect = false;
// We avoid sending spaces in languages without spaces if we were composing.
final boolean shouldAvoidSendingCode = Constants.CODE_SPACE == codePoint
&& !inputTransaction.mSettingsValues.mSpacingAndPunctuations
.mCurrentLanguageHasSpaces
&& !settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces
&& mWordComposer.isComposingWord();
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// If we are in the middle of a recorrection, we need to commit the recorrection
@ -798,13 +798,13 @@ public final class InputLogic {
}
// isComposingWord() may have changed since we stored wasComposing
if (mWordComposer.isComposingWord()) {
if (inputTransaction.mSettingsValues.mCorrectionEnabled) {
if (settingsValues.mCorrectionEnabled) {
final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR
: StringUtils.newSingleCodePointString(codePoint);
commitCurrentAutoCorrection(inputTransaction.mSettingsValues, separator, handler);
commitCurrentAutoCorrection(settingsValues, separator, handler);
didAutoCorrect = true;
} else {
commitTyped(inputTransaction.mSettingsValues,
commitTyped(settingsValues,
StringUtils.newSingleCodePointString(codePoint));
}
}
@ -821,20 +821,23 @@ public final class InputLogic {
// Double quotes behave like they are usually preceded by space iff we are
// not inside a double quote or after a digit.
needsPrecedingSpace = !isInsideDoubleQuoteOrAfterDigit;
} else if (settingsValues.mSpacingAndPunctuations.isClusteringSymbol(codePoint)
&& settingsValues.mSpacingAndPunctuations.isClusteringSymbol(
mConnection.getCodePointBeforeCursor())) {
needsPrecedingSpace = false;
} else {
needsPrecedingSpace = inputTransaction.mSettingsValues.isUsuallyPrecededBySpace(
codePoint);
needsPrecedingSpace = settingsValues.isUsuallyPrecededBySpace(codePoint);
}
if (needsPrecedingSpace) {
promotePhantomSpace(inputTransaction.mSettingsValues);
promotePhantomSpace(settingsValues);
}
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_handleSeparator(codePoint, mWordComposer.isComposingWord());
}
if (!shouldAvoidSendingCode) {
sendKeyCodePoint(inputTransaction.mSettingsValues, codePoint);
sendKeyCodePoint(settingsValues, codePoint);
}
if (Constants.CODE_SPACE == codePoint) {
@ -852,7 +855,7 @@ public final class InputLogic {
swapSwapperAndSpace(inputTransaction);
mSpaceState = SpaceState.SWAP_PUNCTUATION;
} else if ((SpaceState.PHANTOM == inputTransaction.mSpaceState
&& inputTransaction.mSettingsValues.isUsuallyFollowedBySpace(codePoint))
&& settingsValues.isUsuallyFollowedBySpace(codePoint))
|| (Constants.CODE_DOUBLE_QUOTE == codePoint
&& isInsideDoubleQuoteOrAfterDigit)) {
// If we are in phantom space state, and the user presses a separator, we want to

View File

@ -30,6 +30,7 @@ import java.util.Locale;
public final class SpacingAndPunctuations {
private final int[] mSortedSymbolsPrecededBySpace;
private final int[] mSortedSymbolsFollowedBySpace;
private final int[] mSortedSymbolsClusteringTogether;
private final int[] mSortedWordConnectors;
public final int[] mSortedWordSeparators;
public final PunctuationSuggestions mSuggestPuncList;
@ -46,6 +47,8 @@ public final class SpacingAndPunctuations {
// To be able to binary search the code point. See {@link #isUsuallyFollowedBySpace(int)}.
mSortedSymbolsFollowedBySpace = StringUtils.toSortedCodePointArray(
res.getString(R.string.symbols_followed_by_space));
mSortedSymbolsClusteringTogether = StringUtils.toSortedCodePointArray(
res.getString(R.string.symbols_clustering_together));
// To be able to binary search the code point. See {@link #isWordConnector(int)}.
mSortedWordConnectors = StringUtils.toSortedCodePointArray(
res.getString(R.string.symbols_word_connectors));
@ -85,6 +88,10 @@ public final class SpacingAndPunctuations {
return Arrays.binarySearch(mSortedSymbolsFollowedBySpace, code) >= 0;
}
public boolean isClusteringSymbol(final int code) {
return Arrays.binarySearch(mSortedSymbolsClusteringTogether, code) >= 0;
}
public boolean isSentenceSeparator(final int code) {
return code == mSentenceSeparator;
}

View File

@ -334,6 +334,18 @@ public class InputLogicTests extends InputTestsBase {
assertEquals("manual pick then separator", EXPECTED_RESULT, mEditText.getText().toString());
}
// This test matches the one in InputLogicTestsNonEnglish. In some non-English languages,
// ! and ? are clustering punctuation signs.
public void testClusteringPunctuation() {
final String WORD1_TO_TYPE = "test";
final String WORD2_TO_TYPE = "!!?!:!";
final String EXPECTED_RESULT = "test!!?!:!";
type(WORD1_TO_TYPE);
pickSuggestionManually(0, WORD1_TO_TYPE);
type(WORD2_TO_TYPE);
assertEquals("clustering punctuation", EXPECTED_RESULT, mEditText.getText().toString());
}
public void testManualPickThenStripperThenPick() {
final String WORD_TO_TYPE = "this";
final String STRIPPER = "\n";

View File

@ -45,6 +45,19 @@ public class InputLogicTestsNonEnglish extends InputTestsBase {
mEditText.getText().toString());
}
public void testClusteringPunctuationForFrench() {
final String WORD1_TO_TYPE = "test";
final String WORD2_TO_TYPE = "!!?!:!";
// In English, the expected result would be "test!!?!:!"
final String EXPECTED_RESULT = "test !!?! : !";
changeLanguage("fr");
type(WORD1_TO_TYPE);
pickSuggestionManually(0, WORD1_TO_TYPE);
type(WORD2_TO_TYPE);
assertEquals("clustering punctuation for French", EXPECTED_RESULT,
mEditText.getText().toString());
}
public void testWordThenSpaceThenPunctuationFromStripTwiceForFrench() {
final String WORD_TO_TYPE = "test ";
final String PUNCTUATION_FROM_STRIP = "!";