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

Commit 89bd776c authored by Jean Chalard's avatar Jean Chalard
Browse files

Use user-history bigrams when no input if available.

This also fixes a small inconsistency upon clicking on whitespace
twice in a row.
Also add some unit tests for an introduced and an existing method.

Change-Id: I1be2fb53c9624f4d0f5299009632cb4384fdfc15
parent 6c10cf6b
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -197,6 +197,11 @@ public class BinaryDictionary extends Dictionary {
        Arrays.fill(mBigramScores, 0);

        int codesSize = codes.size();
        if (codesSize <= 0) {
            // Do not return bigrams from BinaryDictionary when nothing was typed.
            // Only use user-history bigrams (or whatever other bigram dictionaries decide).
            return;
        }
        Arrays.fill(mInputCodes, -1);
        int[] alternatives = codes.getCodesAt(0);
        System.arraycopy(alternatives, 0, mInputCodes, 0,
+51 −12
Original line number Diff line number Diff line
@@ -161,23 +161,62 @@ public class EditingUtils {

    private static final Pattern spaceRegex = Pattern.compile("\\s+");


    public static CharSequence getPreviousWord(InputConnection connection,
            String sentenceSeperators) {
        //TODO: Should fix this. This could be slow!
        CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
        if (prev == null) {
            return null;
        }
        return getPreviousWord(prev, sentenceSeperators);
    }

    // Get the word before the whitespace preceding the non-whitespace preceding the cursor.
    // Also, it won't return words that end in a separator.
    // Example :
    // "abc def|" -> abc
    // "abc def |" -> abc
    // "abc def. |" -> abc
    // "abc def . |" -> def
    // "abc|" -> null
    // "abc |" -> null
    // "abc. def|" -> null
    public static CharSequence getPreviousWord(CharSequence prev, String sentenceSeperators) {
        if (prev == null) return null;
        String[] w = spaceRegex.split(prev);
        if (w.length >= 2 && w[w.length-2].length() > 0) {

        // If we can't find two words, or we found an empty word, return null.
        if (w.length < 2 || w[w.length - 2].length() <= 0) return null;

        // If ends in a separator, return null
        char lastChar = w[w.length - 2].charAt(w[w.length - 2].length() - 1);
            if (sentenceSeperators.contains(String.valueOf(lastChar))) {
                return null;
            }
        if (sentenceSeperators.contains(String.valueOf(lastChar))) return null;

        return w[w.length - 2];
        } else {
            return null;
    }

    public static CharSequence getThisWord(InputConnection connection, String sentenceSeperators) {
        final CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
        return getThisWord(prev, sentenceSeperators);
    }

    // Get the word immediately before the cursor, even if there is whitespace between it and
    // the cursor - but not if there is punctuation.
    // Example :
    // "abc def|" -> def
    // "abc def |" -> def
    // "abc def. |" -> null
    // "abc def . |" -> null
    public static CharSequence getThisWord(CharSequence prev, String sentenceSeperators) {
        if (prev == null) return null;
        String[] w = spaceRegex.split(prev);

        // No word : return null
        if (w.length < 1 || w[w.length - 1].length() <= 0) return null;

        // If ends in a separator, return null
        char lastChar = w[w.length - 1].charAt(w[w.length - 1].length() - 1);
        if (sentenceSeperators.contains(String.valueOf(lastChar))) return null;

        return w[w.length - 1];
    }

    public static class SelectedWord {
+77 −9
Original line number Diff line number Diff line
@@ -266,6 +266,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
        private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 4;
        private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5;
        private static final int MSG_SPACE_TYPED = 6;
        private static final int MSG_SET_BIGRAM_SUGGESTIONS = 7;

        @Override
        public void handleMessage(Message msg) {
@@ -281,6 +282,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
            case MSG_UPDATE_SHIFT_STATE:
                switcher.updateShiftState();
                break;
            case MSG_SET_BIGRAM_SUGGESTIONS:
                updateBigramSuggestions();
                break;
            case MSG_VOICE_RESULTS:
                mVoiceProxy.handleVoiceResults(preferCapitalization()
                        || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked()));
@@ -333,6 +337,15 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
            removeMessages(MSG_UPDATE_SHIFT_STATE);
        }

        public void postSetBigramSuggestions() {
            removeMessages(MSG_SET_BIGRAM_SUGGESTIONS);
            sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_SUGGESTIONS), DELAY_UPDATE_SUGGESTIONS);
        }

        public void cancelSetBigramSuggestions() {
            removeMessages(MSG_SET_BIGRAM_SUGGESTIONS);
        }

        public void updateVoiceResults() {
            sendMessage(obtainMessage(MSG_VOICE_RESULTS));
        }
@@ -754,7 +767,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
            }
            mComposing.setLength(0);
            mHasValidSuggestions = false;
            if (isCursorTouchingWord()) {
                mHandler.cancelSetBigramSuggestions();
                mHandler.postUpdateSuggestions();
            } else {
                setPunctuationSuggestions();
            }
            TextEntryState.reset();
            InputConnection ic = getCurrentInputConnection();
            if (ic != null) {
@@ -784,14 +802,20 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
                                || TextEntryState.isRecorrecting())
                                && (newSelStart < newSelEnd - 1 || !mHasValidSuggestions)) {
                    if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) {
                        mHandler.cancelSetBigramSuggestions();
                        mHandler.postUpdateOldSuggestions();
                    } else {
                        abortRecorrection(false);
                        // Show the punctuation suggestions list if the current one is not
                        // and if not showing "Touch again to save".
                        if (mCandidateView != null && !isShowingPunctuationList()
                        // If showing the "touch again to save" hint, do not replace it. Else,
                        // show the bigrams if we are at the end of the text, punctuation otherwise.
                        if (mCandidateView != null
                                && !mCandidateView.isShowingAddToDictionaryHint()) {
                            setPunctuationSuggestions();
                            InputConnection ic = getCurrentInputConnection();
                            if (null == ic || !TextUtils.isEmpty(ic.getTextAfterCursor(1, 0))) {
                                if (!isShowingPunctuationList()) setPunctuationSuggestions();
                            } else {
                                mHandler.postSetBigramSuggestions();
                            }
                        }
                    }
                }
@@ -1231,7 +1255,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
                if (mComposing.length() == 0) {
                    mHasValidSuggestions = false;
                }
                if (1 == length) {
                    // 1 == length means we are about to erase the last character of the word,
                    // so we can show bigrams.
                    mHandler.postSetBigramSuggestions();
                } else {
                    // length > 1, so we still have letters to deduce a suggestion from.
                    mHandler.postUpdateSuggestions();
                }
            } else {
                ic.deleteSurroundingText(1, 0);
            }
@@ -1367,6 +1398,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar

        // Should dismiss the "Touch again to save" message when handling separator
        if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) {
            mHandler.cancelSetBigramSuggestions();
            mHandler.postUpdateSuggestions();
        }

@@ -1406,6 +1438,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
        }

        TextEntryState.typedCharacter((char) primaryCode, true, x, y);

        if (TextEntryState.isPunctuationAfterAccepted() && primaryCode != Keyboard.CODE_ENTER) {
            swapPunctuationAndSpace();
        } else if (isSuggestionsRequested() && primaryCode == Keyboard.CODE_SPACE) {
@@ -1420,6 +1453,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
                if (mCandidateView != null)
                    mCandidateView.onAutoCorrectionInverted(mBestWord);
            }
        }
        if (Keyboard.CODE_SPACE == primaryCode) {
            if (!isCursorTouchingWord()) {
                mHandler.cancelUpdateSuggestions();
                mHandler.cancelUpdateOldSuggestions();
                mHandler.postSetBigramSuggestions();
            }
        } else {
            // Set punctuation right away. onUpdateSelection will fire but tests whether it is
            // already displayed or not, so it's okay.
            setPunctuationSuggestions();
        }
        mKeyboardSwitcher.updateShiftState();
@@ -1654,6 +1697,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
            }
            return;
        }
        if (!mHasValidSuggestions) {
            // If we are not composing a word, then it was a suggestion inferred from
            // context - no user input. We should reset the word composer.
            mWord.reset();
        }
        mJustAccepted = true;
        pickSuggestion(suggestion);
        // Add the word to the auto dictionary if it's not a known word
@@ -1692,7 +1740,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
            // TextEntryState.State.PICKED_SUGGESTION state.
            TextEntryState.typedCharacter((char) Keyboard.CODE_SPACE, true,
                    WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
            setPunctuationSuggestions();
            // From there on onUpdateSelection() will fire so suggestions will be updated
        } else if (!showingAddToDictionaryHint) {
            // If we're not showing the "Touch again to save", then show corrections again.
            // In case the cursor position doesn't change, make sure we show the suggestions again.
@@ -1807,6 +1855,25 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
        }
    }

    private static final WordComposer sEmptyWordComposer = new WordComposer();
    private void updateBigramSuggestions() {
        if (mSuggest == null || !isSuggestionsRequested())
            return;

        final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(),
                mWordSeparators);
        SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(
                mKeyboardSwitcher.getInputView(), sEmptyWordComposer, prevWord);

        if (builder.size() > 0) {
            // Explicitly supply an empty typed word (the no-second-arg version of
            // showSuggestions will retrieve the word near the cursor, we don't want that here)
            showSuggestions(builder.build(), "");
        } else {
            if (!isShowingPunctuationList()) setPunctuationSuggestions();
        }
    }

    private void setPunctuationSuggestions() {
        setSuggestions(mSuggestPuncList);
        setCandidatesViewShown(isCandidateStripVisible());
@@ -1907,6 +1974,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
                ic.setComposingText(mComposing, 1);
                TextEntryState.backspace();
            }
            mHandler.cancelSetBigramSuggestions();
            mHandler.postUpdateSuggestions();
        } else {
            sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
+31 −16
Original line number Diff line number Diff line
@@ -265,6 +265,16 @@ public class Suggest implements Dictionary.WordCallback {
        return sb;
    }

    protected void addBigramToSuggestions(CharSequence bigram) {
        final int poolSize = mStringPool.size();
        final StringBuilder sb = poolSize > 0 ?
                (StringBuilder) mStringPool.remove(poolSize - 1)
                        : new StringBuilder(getApproxMaxWordLength());
        sb.setLength(0);
        sb.append(bigram);
        mSuggestions.add(sb);
    }

    // TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder
    public SuggestedWords.Builder getSuggestedWordBuilder(View view, WordComposer wordComposer,
            CharSequence prevWordForBigram) {
@@ -286,7 +296,7 @@ public class Suggest implements Dictionary.WordCallback {
        }
        mTypedWord = typedWord;

        if (wordComposer.size() == 1 && (mCorrectionMode == CORRECTION_FULL_BIGRAM
        if (wordComposer.size() <= 1 && (mCorrectionMode == CORRECTION_FULL_BIGRAM
                || mCorrectionMode == CORRECTION_BASIC)) {
            // At first character typed, search only the bigrams
            Arrays.fill(mBigramScores, 0);
@@ -300,21 +310,26 @@ public class Suggest implements Dictionary.WordCallback {
                for (final Dictionary dictionary : mBigramDictionaries.values()) {
                    dictionary.getBigrams(wordComposer, prevWordForBigram, this);
                }
                char currentChar = wordComposer.getTypedWord().charAt(0);
                char currentCharUpper = Character.toUpperCase(currentChar);
                if (TextUtils.isEmpty(typedWord)) {
                    // Nothing entered: return all bigrams for the previous word
                    int insertCount = Math.min(mBigramSuggestions.size(), mPrefMaxSuggestions);
                    for (int i = 0; i < insertCount; ++i) {
                        addBigramToSuggestions(mBigramSuggestions.get(i));
                    }
                } else {
                    // Word entered: return only bigrams that match the first char of the typed word
                    final char currentChar = typedWord.charAt(0);
                    final char currentCharUpper = Character.toUpperCase(currentChar);
                    int count = 0;
                int bigramSuggestionSize = mBigramSuggestions.size();
                    final int bigramSuggestionSize = mBigramSuggestions.size();
                    for (int i = 0; i < bigramSuggestionSize; i++) {
                    if (mBigramSuggestions.get(i).charAt(0) == currentChar
                            || mBigramSuggestions.get(i).charAt(0) == currentCharUpper) {
                        int poolSize = mStringPool.size();
                        StringBuilder sb = poolSize > 0 ?
                                (StringBuilder) mStringPool.remove(poolSize - 1)
                                : new StringBuilder(getApproxMaxWordLength());
                        sb.setLength(0);
                        sb.append(mBigramSuggestions.get(i));
                        mSuggestions.add(count++, sb);
                        if (count > mPrefMaxSuggestions) break;
                        final CharSequence bigramSuggestion = mBigramSuggestions.get(i);
                        final char bigramSuggestionFirstChar = bigramSuggestion.charAt(0);
                        if (bigramSuggestionFirstChar == currentChar
                                || bigramSuggestionFirstChar == currentCharUpper) {
                            addBigramToSuggestions(bigramSuggestion);
                            if (++count > mPrefMaxSuggestions) break;
                        }
                    }
                }
            }
+4 −0
Original line number Diff line number Diff line
@@ -162,6 +162,10 @@ public class UserBigramDictionary extends ExpandableDictionary {
        if (mIme != null && mIme.getCurrentWord().isAutoCapitalized()) {
            word2 = Character.toLowerCase(word2.charAt(0)) + word2.substring(1);
        }
        // Do not insert a word as a bigram of itself
        if (word1.equals(word2)) {
            return 0;
        }

        int freq = super.addBigram(word1, word2, FREQUENCY_FOR_TYPED);
        if (freq > FREQUENCY_MAX) freq = FREQUENCY_MAX;
Loading