aboutsummaryrefslogtreecommitdiff
path: root/runtime/src/main/java
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2022-12-10 21:14:41 +0800
committershedaniel <daniel@shedaniel.me>2023-05-29 21:21:01 +0800
commit6392e728e1543530f6e0b950c27f415170875856 (patch)
tree79337b8c7c70dce539470cbf72292b3b3aca8f11 /runtime/src/main/java
parent28d0237f31891b40118d118e186a2cd43321b36b (diff)
downloadRoughlyEnoughItems-6392e728e1543530f6e0b950c27f415170875856.tar.gz
RoughlyEnoughItems-6392e728e1543530f6e0b950c27f415170875856.tar.bz2
RoughlyEnoughItems-6392e728e1543530f6e0b950c27f415170875856.zip
Add Fuzzy Pinyin
Diffstat (limited to 'runtime/src/main/java')
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/BomopofoInputMethod.java10
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/DoublePinyinInputMethod.java64
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/PinyinInputMethod.java209
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/UniHanInputMethod.java6
4 files changed, 213 insertions, 76 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/BomopofoInputMethod.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/BomopofoInputMethod.java
index 0054c2bc7..df69d71b7 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/BomopofoInputMethod.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/BomopofoInputMethod.java
@@ -25,6 +25,7 @@ package me.shedaniel.rei.impl.client.search.method.unihan;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
+import me.shedaniel.rei.api.client.favorites.FavoriteMenuEntry;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
@@ -90,7 +91,12 @@ public class BomopofoInputMethod extends PinyinInputMethod {
}
@Override
- protected ExpendedChar asExpendedChar(String string) {
+ public List<FavoriteMenuEntry> getOptionsMenuEntries() {
+ return List.of();
+ }
+
+ @Override
+ protected List<ExpendedChar> asExpendedChars(String string) {
IntList codepoints = new IntArrayList(string.length() + 1);
int[] tone = {-1};
string.codePoints().forEach(codepoint -> {
@@ -110,7 +116,7 @@ public class BomopofoInputMethod extends PinyinInputMethod {
codepoints.add(Character.forDigit(tone[0], 10));
}
List<IntList> phonemes = standard(codepoints).stream().map(str -> CONVERSION.getOrDefault(str, str)).toList();
- return new ExpendedChar(phonemes);
+ return List.of(new ExpendedChar(phonemes));
}
private static List<IntList> standard(IntList s) {
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/DoublePinyinInputMethod.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/DoublePinyinInputMethod.java
index 7f6124379..370974851 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/DoublePinyinInputMethod.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/DoublePinyinInputMethod.java
@@ -9,8 +9,6 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntMaps;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import me.shedaniel.rei.api.client.favorites.FavoriteMenuEntry;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
@@ -27,10 +25,10 @@ public class DoublePinyinInputMethod extends PinyinInputMethod {
public DoublePinyinInputMethod(UniHanManager manager) {
super(manager);
- this.read();
}
- private void read() {
+ @Override
+ protected void read() {
Path path = Platform.getConfigFolder().resolve("roughlyenoughitems/pinyin_double.properties");
this.converter = Converters.SOUGOU;
if (Files.exists(path)) {
@@ -52,7 +50,8 @@ public class DoublePinyinInputMethod extends PinyinInputMethod {
this.write();
}
- private void write() {
+ @Override
+ protected void write() {
Path path = Platform.getConfigFolder().resolve("roughlyenoughitems/pinyin_double.properties");
Properties properties = new Properties();
properties.put("Converter", Converters.CONVERTERS.inverse().get(this.converter));
@@ -98,54 +97,17 @@ public class DoublePinyinInputMethod extends PinyinInputMethod {
}
@Override
- protected ExpendedChar asExpendedChar(String string) {
- IntList[] codepoints = new IntList[3];
- int skip = 2;
- int tone = -1;
- char[] chars = string.toCharArray();
- if (chars[0] == 's' && chars[1] == 'h') {
- codepoints[0] = this.converter.convert("sh");
- } else if (chars[0] == 'c' && chars[1] == 'h') {
- codepoints[0] = this.converter.convert("ch");
- } else if (chars[0] == 'z' && chars[1] == 'h') {
- codepoints[0] = this.converter.convert("zh");
- } else {
- skip = 1;
- ToneEntry toneEntry = toneMap.get(chars[0]);
- if (toneEntry == null) {
- codepoints[0] = this.converter.convert(chars[0] + "");
- } else {
- codepoints[0] = this.converter.convert(((char) toneEntry.codepoint()) + "");
- tone = toneEntry.tone();
- }
- }
- StringBuilder builder = new StringBuilder();
- for (int i = skip; i < chars.length; i++) {
- char c = chars[i];
- if (c == 'ü') {
- builder.append('v');
- } else {
- ToneEntry toneEntry = toneMap.get(c);
- if (toneEntry == null) {
- builder.append(c);
- } else {
- builder.append((char) toneEntry.codepoint());
- tone = toneEntry.tone();
- }
- }
- }
- if (builder.isEmpty()) {
- codepoints[1] = codepoints[0];
- if (this.converter == Converters.SOUGOU || this.converter == Converters.MICROSOFT) {
- codepoints[0] = IntList.of('o');
- }
+ protected List<IntList> expendSimple(String string) {
+ return List.of(this.converter.convert(string));
+ }
+
+ @Override
+ protected List<IntList>[] expendSingles(List<IntList> codepoint) {
+ if (this.converter == Converters.SOUGOU || this.converter == Converters.MICROSOFT) {
+ return new List[]{List.of(IntList.of('o')), codepoint};
} else {
- codepoints[1] = this.converter.convert(builder.toString());
- }
- if (tone != -1) {
- codepoints[2] = IntList.of(Character.forDigit(tone, 10));
+ return new List[]{codepoint, codepoint};
}
- return new ExpendedChar(Arrays.asList(codepoints).subList(0, tone == -1 ? 2 : 3));
}
public interface Converter {
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/PinyinInputMethod.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/PinyinInputMethod.java
index 6c317e0dd..f6f9c486f 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/PinyinInputMethod.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/PinyinInputMethod.java
@@ -23,21 +23,31 @@
package me.shedaniel.rei.impl.client.search.method.unihan;
+import dev.architectury.platform.Platform;
+import dev.architectury.utils.value.BooleanValue;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntList;
+import me.shedaniel.rei.api.client.favorites.FavoriteMenuEntry;
import me.shedaniel.rei.api.client.search.method.CharacterUnpackingInputMethod;
import me.shedaniel.rei.api.client.search.method.InputMethod;
import me.shedaniel.rei.api.common.util.CollectionUtils;
import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.*;
public class PinyinInputMethod extends UniHanInputMethod implements CharacterUnpackingInputMethod {
+ protected final Map<IntList, IntList> fuzzyMap = new LinkedHashMap<>();
protected final Int2ObjectMap<ToneEntry> toneMap;
+ protected final Set<IntList> fuzzySet = new HashSet<>();
protected record ToneEntry(int codepoint, int tone) {}
@@ -68,10 +78,67 @@ public class PinyinInputMethod extends UniHanInputMethod implements CharacterUnp
addTone('ǘ', "v2");
addTone('ǚ', "v3");
addTone('ǜ', "v4");
+ addFuzzy("z", "zh");
+ addFuzzy("s", "sh");
+ addFuzzy("c", "ch");
+ addFuzzy("an", "ang");
+ addFuzzy("en", "eng");
+ addFuzzy("in", "ing");
+ addFuzzy("ian", "iang");
+ addFuzzy("uan", "uang");
+ addFuzzy("n", "l");
+ addFuzzy("r", "l");
+ addFuzzy("h", "f");
+ read();
+ }
+
+ private void addFuzzy(String original, String to) {
+ this.fuzzyMap.put(IntList.of(original.codePoints().toArray()), IntList.of(to.codePoints().toArray()));
}
private void addTone(char c, String s) {
- toneMap.put(c, new ToneEntry(s.charAt(0), Character.digit(s.charAt(1), 10)));
+ this.toneMap.put(c, new ToneEntry(s.charAt(0), Character.digit(s.charAt(1), 10)));
+ }
+
+ protected void read() {
+ Path path = Platform.getConfigFolder().resolve("roughlyenoughitems/pinyin.properties");
+ this.fuzzySet.clear();
+ if (Files.exists(path)) {
+ try {
+ Properties properties = new Properties();
+ try (InputStream stream = Files.newInputStream(path)) {
+ properties.load(stream);
+ }
+ for (IntList key : this.fuzzyMap.keySet()) {
+ if (properties.getOrDefault("Fuzzy:" + new String(key.toIntArray(), 0, key.size()), "false").equals("true")) {
+ this.fuzzySet.add(key);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ try {
+ Files.deleteIfExists(path);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+ this.write();
+ }
+
+ protected void write() {
+ Path path = Platform.getConfigFolder().resolve("roughlyenoughitems/pinyin.properties");
+ Properties properties = new Properties();
+ for (IntList key : this.fuzzyMap.keySet()) {
+ if (this.fuzzySet.contains(key)) {
+ properties.put("Fuzzy_" + new String(key.toIntArray(), 0, key.size()), "true");
+ }
+ }
+ try (OutputStream stream = Files.newOutputStream(path, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE)) {
+ properties.store(stream, "Pinyin Options");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
@Override
@@ -112,25 +179,127 @@ public class PinyinInputMethod extends UniHanInputMethod implements CharacterUnp
}
@Override
- protected ExpendedChar asExpendedChar(String string) {
- List<IntList> codepoints = new ArrayList<>(string.length() + 1);
- int[] tone = {-1};
- string.codePoints().forEach(codepoint -> {
- if (codepoint == 'ü') {
- codepoints.add(IntList.of('v'));
- return;
- }
- ToneEntry toneEntry = toneMap.get(codepoint);
+ public List<FavoriteMenuEntry> getOptionsMenuEntries() {
+ List<FavoriteMenuEntry> innerEntries = new ArrayList<>();
+ this.fuzzyMap.forEach((from, to) -> {
+ innerEntries.add(FavoriteMenuEntry.createToggle(new TextComponent("%s -> %s".formatted(new String(from.toIntArray(), 0, from.size()), new String(to.toIntArray(), 0, to.size()))),
+ new BooleanValue() {
+ @Override
+ public boolean getAsBoolean() {
+ return PinyinInputMethod.this.fuzzySet.contains(from);
+ }
+
+ @Override
+ public void accept(boolean t) {
+ if (t) {
+ PinyinInputMethod.this.fuzzySet.add(from);
+ } else {
+ PinyinInputMethod.this.fuzzySet.remove(from);
+ }
+ PinyinInputMethod.this.write();
+ PinyinInputMethod.this.dataMap.clear();
+ PinyinInputMethod.this.load();
+ }
+ }));
+ });
+ return List.of(FavoriteMenuEntry.createSubMenu(new TranslatableComponent("text.rei.input.methods.pinyin.fuzzy.matching"),
+ innerEntries));
+ }
+
+ @Override
+ protected List<ExpendedChar> asExpendedChars(String string) {
+ List<IntList>[] codepoints = new List[3];
+ int skip = 2;
+ int tone = -1;
+ char[] chars = string.toCharArray();
+ if (chars[0] == 's' && chars[1] == 'h') {
+ codepoints[0] = this.expendInitials("sh");
+ } else if (chars[0] == 'c' && chars[1] == 'h') {
+ codepoints[0] = this.expendInitials("ch");
+ } else if (chars[0] == 'z' && chars[1] == 'h') {
+ codepoints[0] = this.expendInitials("zh");
+ } else {
+ skip = 1;
+ ToneEntry toneEntry = toneMap.get(chars[0]);
if (toneEntry == null) {
- codepoints.add(IntList.of(codepoint));
+ codepoints[0] = this.expendInitials(chars[0] + "");
} else {
- codepoints.add(IntList.of(toneEntry.codepoint));
- tone[0] = toneEntry.tone;
+ codepoints[0] = this.expendInitials(((char) toneEntry.codepoint()) + "");
+ tone = toneEntry.tone();
}
- });
- if (tone[0] != -1) {
- codepoints.add(IntList.of(Character.forDigit(tone[0], 10)));
}
- return new ExpendedChar(codepoints);
+ StringBuilder builder = new StringBuilder();
+ for (int i = skip; i < chars.length; i++) {
+ char c = chars[i];
+ if (c == 'ü') {
+ builder.append('v');
+ } else {
+ ToneEntry toneEntry = toneMap.get(c);
+ if (toneEntry == null) {
+ builder.append(c);
+ } else {
+ builder.append((char) toneEntry.codepoint());
+ tone = toneEntry.tone();
+ }
+ }
+ }
+ int length = 2;
+ if (builder.isEmpty()) {
+ List<IntList>[] expendSingles = this.expendSingles(codepoints[0]);
+ codepoints[0] = expendSingles[0];
+ if (expendSingles.length > 1) {
+ codepoints[1] = expendSingles[1];
+ } else {
+ length = 1;
+ }
+ } else {
+ codepoints[1] = this.expendFinals(builder.toString());
+ }
+ if (tone != -1) {
+ codepoints[++length - 1] = List.of(IntList.of(Character.forDigit(tone, 10)));
+ }
+ int combinations = 1;
+ for (int i = 0; i < length; i++) {
+ combinations *= codepoints[i].size();
+ }
+ List<IntList>[] results = new List[combinations];
+ int[] current = new int[length];
+ for (int i = 0; i < combinations; i++) {
+ results[i] = new ArrayList<>();
+ for (int k = 0; k < length; k++) {
+ results[i].add(codepoints[k].get(current[k]));
+ }
+
+ for (int k = 0; k < length; k++) {
+ if (current[k] + 1 < codepoints[k].size()) {
+ current[k]++;
+ break;
+ } else {
+ current[k] = 0;
+ }
+ }
+ }
+
+ return CollectionUtils.map(results, ExpendedChar::new);
+ }
+
+ protected List<IntList>[] expendSingles(List<IntList> codepoint) {
+ return new List[]{codepoint};
+ }
+
+ protected List<IntList> expendSimple(String string) {
+ IntList codepoints = IntList.of(string.codePoints().toArray());
+ if (this.fuzzySet.contains(codepoints)) {
+ return List.of(codepoints, this.fuzzyMap.get(codepoints));
+ }
+ return List.of(codepoints);
+ }
+
+ protected List<IntList> expendInitials(String string) {
+ return this.expendSimple(string);
+ }
+
+ protected List<IntList> expendFinals(String string) {
+ return this.expendSimple(string);
}
}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/UniHanInputMethod.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/UniHanInputMethod.java
index 91619f644..c9819c107 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/UniHanInputMethod.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/method/unihan/UniHanInputMethod.java
@@ -68,7 +68,7 @@ public abstract class UniHanInputMethod implements InputMethod<IntList> {
String[] strings = data.split(getFieldDelimiter());
List<ExpendedChar> sequences = dataMap.computeIfAbsent(codepoint, value -> new ArrayList<>(strings.length));
for (String string : strings) {
- sequences.add(asExpendedChar(string));
+ sequences.addAll(asExpendedChars(string));
}
}
});
@@ -77,8 +77,8 @@ public abstract class UniHanInputMethod implements InputMethod<IntList> {
}
}
- protected ExpendedChar asExpendedChar(String string) {
- return new ExpendedChar(CollectionUtils.map(IntList.of(string.codePoints().toArray()), IntList::of));
+ protected List<ExpendedChar> asExpendedChars(String string) {
+ return List.of(new ExpendedChar(CollectionUtils.map(IntList.of(string.codePoints().toArray()), IntList::of)));
}
@Override