diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 62d47783924ab604e414aed0e2f4fca80d5f1c12..ae0923182c0fe544cc84c15fad9e1e25b4810447 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1695,7 +1695,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private SuggestedWords updateSuggestions(final CharSequence typedWord) { // TODO: May need a better way of retrieving previous word - final CharSequence prevWord = mConnection.getPreviousWord(mCurrentSettings.mWordSeparators); + final CharSequence prevWord = + mConnection.getNthPreviousWord(mCurrentSettings.mWordSeparators, 2); // getSuggestedWords handles gracefully a null value of prevWord final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer, prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), @@ -1889,7 +1890,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } private SuggestedWords updateBigramPredictions() { - final CharSequence prevWord = mConnection.getThisWord(mCurrentSettings.mWordSeparators); + final CharSequence prevWord = + mConnection.getNthPreviousWord(mCurrentSettings.mWordSeparators, 1); return mSuggest.getSuggestedWords(mWordComposer, prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), mCurrentSettings.mCorrectionEnabled, true); @@ -1916,7 +1918,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final UserHistoryDictionary userHistoryDictionary = mUserHistoryDictionary; if (userHistoryDictionary != null) { final CharSequence prevWord - = mConnection.getPreviousWord(mCurrentSettings.mWordSeparators); + = mConnection.getNthPreviousWord(mCurrentSettings.mWordSeparators, 2); final String secondWord; if (mWordComposer.isAutoCapitalized() && !mWordComposer.isMostlyCaps()) { secondWord = suggestion.toString().toLowerCase( diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index a37f480b711d7675ff2cd0e5595d40d563ec8fe7..5786978a837183398a3a537d0dd53d8c5f12bde6 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -139,12 +139,11 @@ public class RichInputConnection { if (null != mIC) mIC.commitCompletion(completionInfo); } - public CharSequence getPreviousWord(final String sentenceSeperators) { + public CharSequence getNthPreviousWord(final String sentenceSeperators, final int n) { mIC = mParent.getCurrentInputConnection(); - //TODO: Should fix this. This could be slow! if (null == mIC) return null; - CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); - return getPreviousWord(prev, sentenceSeperators); + final CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); + return getNthPreviousWord(prev, sentenceSeperators, n); } /** @@ -177,56 +176,35 @@ public class RichInputConnection { return sep.indexOf(code) != -1; } - // 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 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; - - return w[w.length - 2]; - } - - public CharSequence getThisWord(String sentenceSeperators) { - mIC = mParent.getCurrentInputConnection(); - if (null == mIC) return null; - final CharSequence prev = mIC.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. + // Get the nth word before cursor. n = 1 retrieves the word immediately before the cursor, + // n = 2 retrieves the word before that, and so on. This splits on whitespace only. + // Also, it won't return words that end in a separator (if the nth word before the cursor + // ends in a separator, it returns null). // Example : - // "abc def|" -> def - // "abc def |" -> def - // "abc def. |" -> null - // "abc def . |" -> null - public static CharSequence getThisWord(CharSequence prev, String sentenceSeperators) { + // (n = 1) "abc def|" -> def + // (n = 1) "abc def |" -> def + // (n = 1) "abc def. |" -> null + // (n = 1) "abc def . |" -> null + // (n = 2) "abc def|" -> abc + // (n = 2) "abc def |" -> abc + // (n = 2) "abc def. |" -> abc + // (n = 2) "abc def . |" -> def + // (n = 2) "abc|" -> null + // (n = 2) "abc |" -> null + // (n = 2) "abc. def|" -> null + public static CharSequence getNthPreviousWord(final CharSequence prev, + final String sentenceSeperators, final int n) { 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 we can't find n words, or we found an empty word, return null. + if (w.length < n || w[w.length - n].length() <= 0) return null; // If ends in a separator, return null - char lastChar = w[w.length - 1].charAt(w[w.length - 1].length() - 1); + char lastChar = w[w.length - n].charAt(w[w.length - n].length() - 1); if (sentenceSeperators.contains(String.valueOf(lastChar))) return null; - return w[w.length - 1]; + return w[w.length - n]; } /** diff --git a/tests/src/com/android/inputmethod/latin/RichInputConnectionTests.java b/tests/src/com/android/inputmethod/latin/RichInputConnectionTests.java index 7bd7b0e5a9da00ede5f806618b67f817c560a79c..ad99379409ad3e4c7d664b0a62c91f9e2ac0078a 100644 --- a/tests/src/com/android/inputmethod/latin/RichInputConnectionTests.java +++ b/tests/src/com/android/inputmethod/latin/RichInputConnectionTests.java @@ -102,31 +102,26 @@ public class RichInputConnectionTests extends AndroidTestCase { */ public void testGetPreviousWord() { // If one of the following cases breaks, the bigram suggestions won't work. - assertEquals(RichInputConnection.getPreviousWord("abc def", sSeparators), "abc"); - assertNull(RichInputConnection.getPreviousWord("abc", sSeparators)); - assertNull(RichInputConnection.getPreviousWord("abc. def", sSeparators)); + assertEquals(RichInputConnection.getNthPreviousWord("abc def", sSeparators, 2), "abc"); + assertNull(RichInputConnection.getNthPreviousWord("abc", sSeparators, 2)); + assertNull(RichInputConnection.getNthPreviousWord("abc. def", sSeparators, 2)); // The following tests reflect the current behavior of the function - // RichInputConnection#getPreviousWord. + // RichInputConnection#getNthPreviousWord. // TODO: However at this time, the code does never go // into such a path, so it should be safe to change the behavior of // this function if needed - especially since it does not seem very // logical. These tests are just there to catch any unintentional // changes in the behavior of the RichInputConnection#getPreviousWord method. - assertEquals(RichInputConnection.getPreviousWord("abc def ", sSeparators), "abc"); - assertEquals(RichInputConnection.getPreviousWord("abc def.", sSeparators), "abc"); - assertEquals(RichInputConnection.getPreviousWord("abc def .", sSeparators), "def"); - assertNull(RichInputConnection.getPreviousWord("abc ", sSeparators)); - } - - /** - * Test for getting the word before the cursor (for bigram) - */ - public void testGetThisWord() { - assertEquals(RichInputConnection.getThisWord("abc def", sSeparators), "def"); - assertEquals(RichInputConnection.getThisWord("abc def ", sSeparators), "def"); - assertNull(RichInputConnection.getThisWord("abc def.", sSeparators)); - assertNull(RichInputConnection.getThisWord("abc def .", sSeparators)); + assertEquals(RichInputConnection.getNthPreviousWord("abc def ", sSeparators, 2), "abc"); + assertEquals(RichInputConnection.getNthPreviousWord("abc def.", sSeparators, 2), "abc"); + assertEquals(RichInputConnection.getNthPreviousWord("abc def .", sSeparators, 2), "def"); + assertNull(RichInputConnection.getNthPreviousWord("abc ", sSeparators, 2)); + + assertEquals(RichInputConnection.getNthPreviousWord("abc def", sSeparators, 1), "def"); + assertEquals(RichInputConnection.getNthPreviousWord("abc def ", sSeparators, 1), "def"); + assertNull(RichInputConnection.getNthPreviousWord("abc def.", sSeparators, 1)); + assertNull(RichInputConnection.getNthPreviousWord("abc def .", sSeparators, 1)); } /**