1
0
Fork 0

fixed adding words in Ukrainian, Hebrew and Yiddish

This commit is contained in:
sspanak 2024-02-28 12:28:06 +02:00 committed by Dimo Karaivanov
parent 3f22d45a3f
commit 2c1ea9c411
5 changed files with 132 additions and 36 deletions

View file

@ -15,7 +15,6 @@ import io.github.sspanak.tt9.db.sqlite.ReadOps;
import io.github.sspanak.tt9.db.sqlite.SQLiteOpener; import io.github.sspanak.tt9.db.sqlite.SQLiteOpener;
import io.github.sspanak.tt9.db.sqlite.UpdateOps; import io.github.sspanak.tt9.db.sqlite.UpdateOps;
import io.github.sspanak.tt9.ime.TraditionalT9; import io.github.sspanak.tt9.ime.TraditionalT9;
import io.github.sspanak.tt9.languages.Characters;
import io.github.sspanak.tt9.languages.EmojiLanguage; import io.github.sspanak.tt9.languages.EmojiLanguage;
import io.github.sspanak.tt9.languages.Language; import io.github.sspanak.tt9.languages.Language;
import io.github.sspanak.tt9.languages.Text; import io.github.sspanak.tt9.languages.Text;
@ -138,7 +137,7 @@ public class WordStore {
return AddWordDialog.CODE_GENERAL_ERROR; return AddWordDialog.CODE_GENERAL_ERROR;
} }
language = Characters.isGraphic(word) ? new EmojiLanguage() : language; language = Text.isGraphic(word) ? new EmojiLanguage() : language;
try { try {
if (readOps.exists(sqlite.getDb(), language, word)) { if (readOps.exists(sqlite.getDb(), language, word)) {

View file

@ -13,8 +13,6 @@ import android.view.inputmethod.InputConnection;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import io.github.sspanak.tt9.Logger; import io.github.sspanak.tt9.Logger;
import io.github.sspanak.tt9.ime.modes.InputMode; import io.github.sspanak.tt9.ime.modes.InputMode;
@ -24,12 +22,6 @@ import io.github.sspanak.tt9.languages.Text;
public class TextField { public class TextField {
public static final int IME_ACTION_ENTER = EditorInfo.IME_MASK_ACTION + 1; public static final int IME_ACTION_ENTER = EditorInfo.IME_MASK_ACTION + 1;
private static final Pattern beforeCursorWordRegex = Pattern.compile("([^\\s\\d\\p{P}]+)(?!\n)$");
private static final Pattern afterCursorWordRegex = Pattern.compile("^(?<!\n)([^\\s\\d\\p{P}]+)");
private static final Pattern beforeCursorUkrainianRegex = Pattern.compile("([(?:^\\s\\d\\p{P}|')]+)(?!\n)$");
private static final Pattern afterCursorUkrainianRegex = Pattern.compile("^(?<!\n)([(?:^\\s\\d\\p{P}|')]+)");
public final InputConnection connection; public final InputConnection connection;
public final EditorInfo field; public final EditorInfo field;
@ -175,21 +167,35 @@ public class TextField {
* Returns the word next or around the cursor. Scanning length is up to 50 chars in each direction. * Returns the word next or around the cursor. Scanning length is up to 50 chars in each direction.
*/ */
@NonNull public String getSurroundingWord(Language language) { @NonNull public String getSurroundingWord(Language language) {
Matcher before; Text before = getTextBeforeCursor();
Matcher after; Text after = getTextAfterCursor(50);
if (language != null && (language.isHebrew() || language.isUkrainian())) { // emoji
// Hebrew and Ukrainian use apostrophes as letters boolean beforeEndsWithGraphics = before.endsWithGraphic();
before = beforeCursorUkrainianRegex.matcher(getStringBeforeCursor()); boolean afterStartsWithGraphics = after.startsWithGraphic();
after = afterCursorUkrainianRegex.matcher(getStringAfterCursor());
} else { if (beforeEndsWithGraphics && afterStartsWithGraphics) {
// In other languages, special characters in words will cause automatic word break to fail, return before.leaveEndingGraphics() + after.leaveStartingGraphics();
// resulting in unexpected suggestions. Therefore, they are not allowed.
before = beforeCursorWordRegex.matcher(getStringBeforeCursor());
after = afterCursorWordRegex.matcher(getStringAfterCursor());
} }
return (before.find() ? before.group(1) : "") + (after.find() ? after.group(1) : ""); if (afterStartsWithGraphics) {
return after.leaveStartingGraphics();
}
if (beforeEndsWithGraphics) {
return before.leaveEndingGraphics();
}
// text
boolean keepApostrophe = false;
boolean keepQuote = false;
if (language != null) {
// Hebrew and Ukrainian use the respective special characters as letters
keepApostrophe = language.isHebrew() || language.isUkrainian();
keepQuote = language.isHebrew();
}
return before.subStringEndingWord(keepApostrophe, keepQuote) + after.subStringStartingWord(keepApostrophe, keepQuote);
} }

View file

@ -58,20 +58,9 @@ public class Characters {
)) ))
)); ));
public static boolean isGraphic(String str) {
if (str == null) {
return false;
}
for (int i = 0, end = str.length(); i < end; i++) { public static boolean isGraphic(char ch) {
char ch = str.charAt(i); return !(ch < 256 || Character.isLetterOrDigit(ch) || Character.isAlphabetic(ch));
if (ch < 256 || Character.isLetterOrDigit(ch) || Character.isAlphabetic(ch)) {
return false;
}
}
return true;
} }
public static boolean noEmojiSupported() { public static boolean noEmojiSupported() {

View file

@ -16,7 +16,7 @@ public class EmojiLanguage extends Language {
@Override @Override
public String getDigitSequenceForWord(String word) { public String getDigitSequenceForWord(String word) {
return Characters.isGraphic(word) ? CUSTOM_EMOJI_SEQUENCE : null; return Text.isGraphic(word) ? CUSTOM_EMOJI_SEQUENCE : null;
} }
@Override @Override

View file

@ -45,10 +45,28 @@ public class Text {
return str != null && containsOtherThan1.matcher(str).find(); return str != null && containsOtherThan1.matcher(str).find();
} }
public boolean endsWithGraphic() {
return text != null && !text.isEmpty() && Characters.isGraphic(text.charAt(text.length() - 1));
}
public boolean isEmpty() { public boolean isEmpty() {
return text == null || text.isEmpty(); return text == null || text.isEmpty();
} }
public static boolean isGraphic(String str) {
if (str == null || str.isEmpty()) {
return false;
}
for (int i = 0, end = str.length(); i < end; i++) {
if (!Characters.isGraphic(str.charAt(i))) {
return false;
}
}
return true;
}
public boolean isMixedCase() { public boolean isMixedCase() {
return return
language != null language != null
@ -69,6 +87,46 @@ public class Text {
return language != null && text != null && text.toUpperCase(language.getLocale()).equals(text); return language != null && text != null && text.toUpperCase(language.getLocale()).equals(text);
} }
public String leaveEndingGraphics() {
if (text == null) {
return "";
}
StringBuilder sb = new StringBuilder(text.length());
for (int i = text.length() - 1; i >= 0; i--) {
char ch = text.charAt(i);
if (Characters.isGraphic(ch)) {
sb.insert(0, ch);
} else {
break;
}
}
return sb.toString();
}
public String leaveStartingGraphics() {
if (text == null) {
return "";
}
StringBuilder sb = new StringBuilder(text.length());
for (int i = 0, end = text.length(); i < end; i++) {
char ch = text.charAt(i);
if (Characters.isGraphic(ch)) {
sb.append(ch);
} else {
break;
}
}
return sb.toString();
}
public boolean nextIsPunctuation() { public boolean nextIsPunctuation() {
return text != null && !text.isEmpty() && nextIsPunctuation.matcher(text).find(); return text != null && !text.isEmpty() && nextIsPunctuation.matcher(text).find();
} }
@ -85,6 +143,50 @@ public class Text {
return text != null && !text.isEmpty() && Character.isDigit(text.charAt(0)); return text != null && !text.isEmpty() && Character.isDigit(text.charAt(0));
} }
public boolean startsWithGraphic() {
return text != null && !text.isEmpty() && Characters.isGraphic(text.charAt(0));
}
public String subStringEndingWord(boolean keepApostrophe, boolean keepQuote) {
if (text == null) {
return "";
}
StringBuilder sub = new StringBuilder();
for (int i = text.length() - 1; i >= 0; i--) {
char ch = text.charAt(i);
if (Character.isAlphabetic(ch) || (keepApostrophe && ch == '\'') || (keepQuote && ch == '"')) {
sub.insert(0, ch);
} else {
break;
}
}
return sub.toString();
}
public String subStringStartingWord(boolean keepApostrophe, boolean keepQuote) {
if (text == null) {
return "";
}
StringBuilder sub = new StringBuilder();
for (int i = 0, end = text.length(); i < end; i++) {
char ch = text.charAt(i);
if (Character.isAlphabetic(ch) || (keepApostrophe && ch == '\'') || (keepQuote && ch == '"')) {
sub.append(ch);
} else {
break;
}
}
return sub.toString();
}
public String toLowerCase() { public String toLowerCase() {
if (text == null) { if (text == null) {
return ""; return "";