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.UpdateOps;
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.Language;
import io.github.sspanak.tt9.languages.Text;
@ -138,7 +137,7 @@ public class WordStore {
return AddWordDialog.CODE_GENERAL_ERROR;
}
language = Characters.isGraphic(word) ? new EmojiLanguage() : language;
language = Text.isGraphic(word) ? new EmojiLanguage() : language;
try {
if (readOps.exists(sqlite.getDb(), language, word)) {

View file

@ -13,8 +13,6 @@ import android.view.inputmethod.InputConnection;
import androidx.annotation.NonNull;
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.ime.modes.InputMode;
@ -24,12 +22,6 @@ import io.github.sspanak.tt9.languages.Text;
public class TextField {
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 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.
*/
@NonNull public String getSurroundingWord(Language language) {
Matcher before;
Matcher after;
Text before = getTextBeforeCursor();
Text after = getTextAfterCursor(50);
if (language != null && (language.isHebrew() || language.isUkrainian())) {
// Hebrew and Ukrainian use apostrophes as letters
before = beforeCursorUkrainianRegex.matcher(getStringBeforeCursor());
after = afterCursorUkrainianRegex.matcher(getStringAfterCursor());
} else {
// In other languages, special characters in words will cause automatic word break to fail,
// resulting in unexpected suggestions. Therefore, they are not allowed.
before = beforeCursorWordRegex.matcher(getStringBeforeCursor());
after = afterCursorWordRegex.matcher(getStringAfterCursor());
// emoji
boolean beforeEndsWithGraphics = before.endsWithGraphic();
boolean afterStartsWithGraphics = after.startsWithGraphic();
if (beforeEndsWithGraphics && afterStartsWithGraphics) {
return before.leaveEndingGraphics() + after.leaveStartingGraphics();
}
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++) {
char ch = str.charAt(i);
if (ch < 256 || Character.isLetterOrDigit(ch) || Character.isAlphabetic(ch)) {
return false;
}
}
return true;
public static boolean isGraphic(char ch) {
return !(ch < 256 || Character.isLetterOrDigit(ch) || Character.isAlphabetic(ch));
}
public static boolean noEmojiSupported() {

View file

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

View file

@ -45,10 +45,28 @@ public class Text {
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() {
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() {
return
language != null
@ -69,6 +87,46 @@ public class 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() {
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));
}
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() {
if (text == null) {
return "";