Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d1c8b2c authored by Jean Chalard's avatar Jean Chalard Committed by Android (Google) Code Review
Browse files

Merge "Try to figure out whether d.quotes open or close."

parents b084da2a c7ef305b
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -814,6 +814,17 @@ public final class RichInputConnection {
        return StringUtils.lastPartLooksLikeURL(mCommittedTextBeforeComposingText);
    }

    /**
     * Looks at the text just before the cursor to find out if we are inside a double quote.
     *
     * As with #textBeforeCursorLooksLikeURL, this is dependent on how much text we have cached.
     * However this won't be a concrete problem in most situations, as the cache is almost always
     * long enough for this use.
     */
    public boolean isInsideDoubleQuoteOrAfterDigit() {
        return StringUtils.isInsideDoubleQuoteOrAfterDigit(mCommittedTextBeforeComposingText);
    }

    /**
     * Try to get the text from the editor to expose lies the framework may have been
     * telling us. Concretely, when the device rotates, the frameworks tells us about where the
+21 −5
Original line number Diff line number Diff line
@@ -670,8 +670,21 @@ public final class InputLogic {
        final boolean swapWeakSpace = maybeStripSpace(settingsValues, codePoint, spaceState,
                isFromSuggestionStrip);

        if (SpaceState.PHANTOM == spaceState &&
                settingsValues.isUsuallyPrecededBySpace(codePoint)) {
        final boolean isInsideDoubleQuoteOrAfterDigit = Constants.CODE_DOUBLE_QUOTE == codePoint
                && mConnection.isInsideDoubleQuoteOrAfterDigit();

        final boolean needsPrecedingSpace;
        if (SpaceState.PHANTOM != spaceState) {
            needsPrecedingSpace = false;
        } else if (Constants.CODE_DOUBLE_QUOTE == codePoint) {
            // 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 {
            needsPrecedingSpace = settingsValues.isUsuallyPrecededBySpace(codePoint);
        }

        if (needsPrecedingSpace) {
            promotePhantomSpace(settingsValues);
        }
        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
@@ -698,14 +711,17 @@ public final class InputLogic {
            if (swapWeakSpace) {
                swapSwapperAndSpace(keyboardSwitcher);
                mSpaceState = SpaceState.SWAP_PUNCTUATION;
            } else if (SpaceState.PHANTOM == spaceState
                    && settingsValues.isUsuallyFollowedBySpace(codePoint)) {
            } else if ((SpaceState.PHANTOM == spaceState
                    && 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
                // stay in phantom space state so that the next keypress has a chance to add the
                // space. For example, if I type "Good dat", pick "day" from the suggestion strip
                // then insert a comma and go on to typing the next word, I want the space to be
                // inserted automatically before the next word, the same way it is when I don't
                // input the comma.
                // input the comma. A double quote behaves like it's usually followed by space if
                // we're inside a double quote.
                // The case is a little different if the separator is a space stripper. Such a
                // separator does not normally need a space on the right (that's the difference
                // between swappers and strippers), so we should not stay in phantom space state if
+43 −1
Original line number Diff line number Diff line
@@ -387,6 +387,48 @@ public final class StringUtils {
        return false;
    }

    /**
     * Examines the string and returns whether we're inside a double quote.
     *
     * This is used to decide whether we should put an automatic space before or after a double
     * quote character. If we're inside a quotation, then we want to close it, so we want a space
     * after and not before. Otherwise, we want to open the quotation, so we want a space before
     * and not after. Exception: after a digit, we never want a space because the "inch" or
     * "minutes" use cases is dominant after digits.
     * In the practice, we determine whether we are in a quotation or not by finding the previous
     * double quote character, and looking at whether it's followed by whitespace. If so, that
     * was a closing quotation mark, so we're not inside a double quote. If it's not followed
     * by whitespace, then it was an opening quotation mark, and we're inside a quotation.
     *
     * @param text the text to examine.
     * @return whether we're inside a double quote.
     */
    public static boolean isInsideDoubleQuoteOrAfterDigit(final CharSequence text) {
        int i = text.length();
        if (0 == i) return false;
        int codePoint = Character.codePointBefore(text, i);
        if (Character.isDigit(codePoint)) return true;
        int prevCodePoint = 0;
        while (i > 0) {
            codePoint = Character.codePointBefore(text, i);
            if (Constants.CODE_DOUBLE_QUOTE == codePoint) {
                // If we see a double quote followed by whitespace, then that
                // was a closing quote.
                if (Character.isWhitespace(prevCodePoint)) return false;
            }
            if (Character.isWhitespace(codePoint) && Constants.CODE_DOUBLE_QUOTE == prevCodePoint) {
                // If we see a double quote preceded by whitespace, then that
                // was an opening quote. No need to continue seeking.
                return true;
            }
            i -= Character.charCount(codePoint);
            prevCodePoint = codePoint;
        }
        // We reached the start of text. If the first char is a double quote, then we're inside
        // a double quote. Otherwise we're not.
        return Constants.CODE_DOUBLE_QUOTE == codePoint;
    }

    public static boolean isEmptyStringOrWhiteSpaces(final String s) {
        final int N = codePointCount(s);
        for (int i = 0; i < N; ++i) {
+28 −0
Original line number Diff line number Diff line
@@ -169,4 +169,32 @@ public class PunctuationTests extends InputTestsBase {
                + " ; Suggestions = " + mLatinIME.getSuggestedWords(),
                EXPECTED_RESULT, mEditText.getText().toString());
    }

    public void testAutoSpaceWithDoubleQuotes() {
        final String STRING_TO_TYPE = "He said\"hello\"to me. I replied,\"hi\"."
                + "Then, 5\"passed. He said\"bye\"and left.";
        final String EXPECTED_RESULT = "He said \"hello\" to me. I replied, \"hi\". "
                + "Then, 5\" passed. He said \"bye\" and left. \"";
        // Split by double quote, so that we can type the double quotes individually.
        for (final String partToType : STRING_TO_TYPE.split("\"")) {
            // Split at word boundaries. This regexp means "anywhere that is preceded
            // by a word character but not followed by a word character, OR that is not
            // preceded by a word character but followed by a word character".
            // We need to input word by word because auto-spaces are only active when
            // manually picking or gesturing (which we can't simulate yet), but only words
            // can be picked.
            final String[] wordsToType = partToType.split("(?<=\\w)(?!\\w)|(?<!\\w)(?=\\w)");
            for (final String wordToType : wordsToType) {
                type(wordToType);
                if (wordToType.matches("^\\w+$")) {
                    // Only pick selection if that was a word, because if that was not a word,
                    // then we don't have a composition.
                    pickSuggestionManually(0, wordToType);
                }
            }
            type("\"");
        }
        assertEquals("auto-space with double quotes",
                EXPECTED_RESULT, mEditText.getText().toString());
    }
}