Skip to content

Commit 4da09ee

Browse files
committed
auto-complete the current word
1 parent 6edbe6b commit 4da09ee

File tree

5 files changed

+66
-39
lines changed

5 files changed

+66
-39
lines changed

app/src/main/java/io/github/sspanak/tt9/db/mindReading/MindReader.java

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,34 @@ public boolean clearContext() {
5353
}
5454

5555

56-
public void guess(@NonNull InputMode inputMode, @NonNull Language language, @NonNull String beforeCursor, @Nullable String lastWord, boolean saveContext, Consumer<ArrayList<String>> onComplete) {
56+
public void guessNext(@NonNull InputMode inputMode, @NonNull Language language, @NonNull String beforeCursor, @Nullable String lastWord, boolean saveContext, Consumer<ArrayList<String>> onComplete) {
5757
final String TIMER_TAG = LOG_TAG + Math.random();
5858
Timer.start(TIMER_TAG);
5959

6060
if (setContextSync(inputMode, language, beforeCursor, lastWord)) {
6161
runInThread(() -> {
6262
processContext(inputMode, language, saveContext);
63-
ArrayList<String> words = dictionary.getAll(ngrams.getAllNextTokens(dictionary, wordContext));
64-
63+
ArrayList<String> words = dictionary.getAll(ngrams.getAllNextTokens(dictionary, wordContext), null);
6564
logState(Timer.stop(TIMER_TAG), words);
65+
onComplete.accept(words);
66+
});
67+
}
68+
}
69+
6670

71+
/**
72+
* Given the current context, and that the next words starts with firstLetter, guess what the word
73+
* might be.
74+
*/
75+
public void guessCurrent(@NonNull InputMode inputMode, @NonNull Language language, @NonNull String beforeCursor, @NonNull String firstLetter, Consumer<ArrayList<String>> onComplete) {
76+
final String TIMER_TAG = LOG_TAG + Math.random();
77+
Timer.start(TIMER_TAG);
78+
79+
if (setContextSync(inputMode, language, beforeCursor, null)) {
80+
runInThread(() -> {
81+
processContext(inputMode, language, false);
82+
ArrayList<String> words = dictionary.getAll(ngrams.getAllNextTokens(dictionary, wordContext), firstLetter);
83+
logState(Timer.stop(TIMER_TAG), null);
6784
onComplete.accept(words);
6885
});
6986
}
@@ -135,14 +152,16 @@ private boolean isOff() {
135152

136153

137154
private void logState(long processingTime, @Nullable ArrayList<String> words) {
155+
if (!Logger.isDebugLevel()) {
156+
return;
157+
}
158+
138159
StringBuilder log = new StringBuilder();
139160
log.append("===== Mind Reading Summary =====");
140161

141-
if (Logger.isDebugLevel()) {
142-
log
143-
.append("\ncontext: ").append(wordContext)
144-
.append("\nN-grams: ").append(ngrams);
145-
}
162+
log
163+
.append("\ncontext: ").append(wordContext)
164+
.append("\nN-grams: ").append(ngrams);
146165

147166
log.append("\nMagic Word Count: ").append(words != null ? words.size() : 0);
148167

app/src/main/java/io/github/sspanak/tt9/db/mindReading/MindReaderDictionary.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@ void addAll(@NonNull String[] tokens) {
9494

9595

9696
@NonNull
97-
public ArrayList<String> getAll(Set<Integer> tokenIds) {
97+
public ArrayList<String> getAll(@NonNull Set<Integer> tokenIds, @Nullable String startsWith) {
9898
final ArrayList<String> results = new ArrayList<>(tokenIds.size());
9999

100100
for (final int tokenId : tokenIds) {
101-
if (isWord(tokenId) && tokenId < tokens.length) {
101+
if (isWord(tokenId) && tokenId < tokens.length && (startsWith == null || tokens[tokenId].toLowerCase(locale).startsWith(startsWith.toLowerCase(locale)))) {
102102
results.add(tokens[tokenId]);
103103
}
104104
}

app/src/main/java/io/github/sspanak/tt9/ime/HotkeyHandler.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ public boolean onKeyFilterClear(boolean validateOnly) {
360360

361361

362362
public boolean onKeyFilterSuggestions(boolean validateOnly, boolean repeat) {
363-
if (suggestionOps.isEmpty() && !settings.getAutoMindReading()) {
363+
if (suggestionOps.isEmpty()) {
364364
return false;
365365
}
366366

@@ -384,7 +384,6 @@ public boolean onKeyFilterSuggestions(boolean validateOnly, boolean repeat) {
384384

385385
if (filter.isEmpty()) {
386386
mInputMode.reset();
387-
getMagicSuggestions(textField.getSurroundingStringForAutoAssistance(settings, mInputMode)[0], null, true);
388387
} else if (mInputMode.setWordStem(filter, repeat)) {
389388
mInputMode
390389
.setOnSuggestionsUpdated(super::handleSuggestionsFromThread)

app/src/main/java/io/github/sspanak/tt9/ime/SuggestionHandler.java

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ protected void onAcceptSuggestionManually(String word, int fromKey) {
8686
)[0];
8787
updateShiftState(beforeCursor, true, false);
8888
resetKeyRepeat();
89-
getMagicSuggestions(beforeCursor, word, true);
89+
guessNextWord(beforeCursor, word, true);
9090
}
9191

9292
if (!Characters.getSpace(mLanguage).equals(word)) {
@@ -147,7 +147,6 @@ protected void handleSuggestions(@Nullable Runnable onComplete) {
147147
}
148148

149149
final ArrayList<String> suggestions = mInputMode.getSuggestions();
150-
final boolean noSuggestionsBefore = suggestionOps.isEmpty();
151150
suggestionOps.set(suggestions, mInputMode.getRecommendedSuggestionIdx(), mInputMode.containsGeneratedSuggestions());
152151

153152
// either accept the first one automatically (when switching from punctuation to text
@@ -171,11 +170,11 @@ protected void handleSuggestions(@Nullable Runnable onComplete) {
171170
appHacks.setComposingTextWithHighlightedStem(trimmedWord, mInputMode.getWordStem(), mInputMode.isStemFilterFuzzy());
172171
}
173172

174-
onAfterSuggestionsHandled(onComplete, beforeCursor, trimmedWord, suggestions.isEmpty(), noSuggestionsBefore);
173+
onAfterSuggestionsHandled(onComplete, beforeCursor, trimmedWord, suggestions.isEmpty());
175174
}
176175

177176

178-
private void onAfterSuggestionsHandled(@Nullable Runnable callback, @Nullable String beforeCursor, @Nullable String trimmedWord, boolean noSuggestions, boolean noSuggestionsBefore) {
177+
private void onAfterSuggestionsHandled(@Nullable Runnable callback, @Nullable String beforeCursor, @Nullable String trimmedWord, boolean noSuggestions) {
179178
final String shiftStateContext = beforeCursor != null ? beforeCursor + trimmedWord : trimmedWord;
180179
if (noSuggestions) {
181180
updateShiftStateDebounced(shiftStateContext, true, false);
@@ -185,15 +184,11 @@ private void onAfterSuggestionsHandled(@Nullable Runnable callback, @Nullable St
185184

186185
forceShowWindow();
187186

188-
// @todo: here get completions for the current word, instead of the next words for it.
189-
// if (noSuggestionsBefore && !noSuggestions && !mInputMode.containsSpecialChars()) {
190-
191-
// mindReader.guess(
192-
// mLanguage,
193-
// beforeCursor == null ? textField.getSurroundingStringForAutoAssistance(settings, mInputMode)[0] : beforeCursor + trimmedWord,
194-
// false
195-
// );
196-
// }
187+
// if this is the first letter of a word, and not punctuation, guess what the word might be
188+
// we also check if mind-reading is on to prevent expensive getSurroundingStringForAutoAssistance()
189+
if (!noSuggestions && settings.getAutoMindReading() && mInputMode.getSequenceLength() == 1 && !mInputMode.containsSpecialChars()) {
190+
guessCurrentWord(beforeCursor, trimmedWord);
191+
}
197192

198193
if (callback != null) {
199194
callback.run();
@@ -202,24 +197,38 @@ private void onAfterSuggestionsHandled(@Nullable Runnable callback, @Nullable St
202197

203198

204199
@Override
205-
protected boolean clearMagicContext() {
200+
protected boolean clearGuessingContext() {
206201
return mindReader.clearContext();
207202
}
208203

209204

210205
@Override
211-
protected void setMagicContext(@NonNull String beforeCursor, @Nullable String lastWord) {
206+
protected void setGuessingContext(@NonNull String beforeCursor, @Nullable String lastWord) {
212207
mindReader.setContext(mInputMode, mLanguage, beforeCursor, lastWord);
213208
}
214209

215210

211+
private void guessCurrentWord(@Nullable String beforeCursor, @Nullable String trimmedWord) {
212+
String beforeWithoutTrimmed = beforeCursor;
213+
if (beforeWithoutTrimmed == null) {
214+
beforeWithoutTrimmed = textField.getSurroundingStringForAutoAssistance(settings, mInputMode)[0];
215+
if (trimmedWord != null && beforeWithoutTrimmed.endsWith(" " + trimmedWord)) {
216+
beforeWithoutTrimmed = beforeWithoutTrimmed.substring(0, beforeWithoutTrimmed.length() - trimmedWord.length() - 1);
217+
}
218+
}
219+
220+
mindReader.guessCurrent(mInputMode, mLanguage, beforeWithoutTrimmed, trimmedWord, this::handleGuesses);
221+
}
222+
223+
216224
@Override
217-
protected void getMagicSuggestions(@NonNull String beforeCursor, @Nullable String lastWord, boolean saveContext) {
218-
mindReader.guess(mInputMode, mLanguage, beforeCursor, lastWord, saveContext, this::handleMagicSuggestions);
225+
protected void guessNextWord(@NonNull String beforeCursor, @Nullable String lastWord, boolean saveContext) {
226+
mindReader.guessNext(mInputMode, mLanguage, beforeCursor, lastWord, saveContext, this::handleGuesses);
219227
}
220228

221229

222-
private void handleMagicSuggestions(ArrayList<String> suggestions) {
230+
private void handleGuesses(ArrayList<String> suggestions) {
231+
// @todo: suggestionOps.addGuesses(suggestions);
223232
Logger.d("LOG", "=========> " + suggestions);
224233
}
225234
}

app/src/main/java/io/github/sspanak/tt9/ime/TypingHandler.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ public abstract class TypingHandler extends KeyPadHandler {
4747

4848
abstract protected void onAcceptSuggestionsDelayed(String s);
4949
abstract protected void getSuggestions(@Nullable String currentWord, @Nullable Runnable onComplete);
50-
abstract protected void getMagicSuggestions(@NonNull String beforeCurso, @Nullable String currentWord, boolean saveContext);
51-
abstract protected boolean clearMagicContext();
52-
abstract protected void setMagicContext(@NonNull String beforeCursor, @Nullable String currentWord);
50+
abstract protected void guessNextWord(@NonNull String beforeCurso, @Nullable String currentWord, boolean saveContext);
51+
abstract protected boolean clearGuessingContext();
52+
abstract protected void setGuessingContext(@NonNull String beforeCursor, @Nullable String currentWord);
5353

5454

5555
protected void createSuggestionBar() {
@@ -87,7 +87,7 @@ protected boolean onStart(EditorInfo field, boolean restarting) {
8787
// don't use beforeCursor cache on start up
8888
final String beforeCursor = textField.getSurroundingStringForAutoAssistance(settings, mInputMode)[0];
8989
updateShiftState(beforeCursor, true, false);
90-
getMagicSuggestions(beforeCursor, null, false);
90+
guessNextWord(beforeCursor, null, false);
9191

9292
return true;
9393
}
@@ -143,7 +143,7 @@ public boolean onBackspace(int repeat) {
143143
return false;
144144
}
145145

146-
if (clearMagicContext()) { // @todo: instead: if (suggestionOps contains only suggestions from mind reader)
146+
if (clearGuessingContext()) { // @todo: instead: if (suggestionOps contains only suggestions from mind reader)
147147
return true;
148148
}
149149

@@ -205,9 +205,9 @@ protected boolean onNumber(int key, boolean hold, int repeat) {
205205
surroundingChars = autoCorrectSpace(lastWord, surroundingChars, false, key);
206206

207207
if (mLanguage.hasSpaceBetweenWords()) {
208-
setMagicContext(surroundingChars[0], lastWord);
208+
setGuessingContext(surroundingChars[0], lastWord);
209209
} else {
210-
getMagicSuggestions(surroundingChars[0], lastWord, true);
210+
guessNextWord(surroundingChars[0], lastWord, true);
211211
}
212212
}
213213

@@ -269,7 +269,7 @@ public boolean onText(String text, boolean validateOnly) {
269269

270270
forceShowWindow();
271271
updateShiftState(beforeCursor, true, false);
272-
getMagicSuggestions(beforeCursor, lastWord, true);
272+
guessNextWord(beforeCursor, lastWord, true);
273273

274274
return true;
275275
}
@@ -448,7 +448,7 @@ public void onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, i
448448
// location. This prevents undesired deletion of the space, in the middle of the text.
449449
if (CursorOps.isMovedFar(newSelStart, newSelEnd, oldSelStart, oldSelEnd)) {
450450
stopWaitingForSpaceTrimKey();
451-
clearMagicContext();
451+
clearGuessingContext();
452452
}
453453
}
454454

0 commit comments

Comments
 (0)