Skip to content

Commit 582b474

Browse files
committed
feat: add wrapper of native config parser
1 parent be66f30 commit 582b474

8 files changed

Lines changed: 340 additions & 36 deletions

File tree

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2015 - 2025 Rime community
3+
* SPDX-License-Identifier: GPL-3.0-or-later
4+
*/
5+
6+
package com.osfans.trime.core
7+
8+
class RimeConfig private constructor(
9+
private val ptr: Long,
10+
) : AutoCloseable {
11+
fun getString(
12+
key: String,
13+
defaultValue: String = "",
14+
): String {
15+
check(ptr != 0L)
16+
return getRimeConfigString(ptr, key) ?: defaultValue
17+
}
18+
19+
fun getBool(
20+
key: String,
21+
defaultValue: Boolean = false,
22+
): Boolean {
23+
check(ptr != 0L)
24+
return getRimeConfigBool(ptr, key) ?: defaultValue
25+
}
26+
27+
fun getDouble(
28+
key: String,
29+
defaultValue: Double = 0.0,
30+
): Double {
31+
check(ptr != 0L)
32+
return getRimeConfigDouble(ptr, key) ?: defaultValue
33+
}
34+
35+
fun getInt(
36+
key: String,
37+
defaultValue: Int = 0,
38+
): Int {
39+
check(ptr != 0L)
40+
return getRimeConfigInt(ptr, key) ?: defaultValue
41+
}
42+
43+
fun getList(key: String): List<RimeConfig> {
44+
check(ptr != 0L)
45+
val array = getRimeConfigList(ptr, key) ?: return emptyList()
46+
return array.map { RimeConfig(it) }
47+
}
48+
49+
fun getStringList(key: String): List<String> {
50+
check(ptr != 0L)
51+
return getRimeConfigList(ptr, key)?.map {
52+
getRimeConfigString(it, "") ?: ""
53+
} ?: emptyList()
54+
}
55+
56+
fun getMap(key: String): Map<String, RimeConfig> {
57+
check(ptr != 0L)
58+
val map = getRimeConfigMap(ptr, key) ?: return emptyMap()
59+
return map.mapValues { RimeConfig(it.value) }
60+
}
61+
62+
fun getStringValueMap(key: String): Map<String, String> {
63+
check(ptr != 0L)
64+
val map = getRimeConfigMap(ptr, key) ?: return emptyMap()
65+
return map.mapValues { getRimeConfigString(ptr, key) ?: "" }
66+
}
67+
68+
fun getItem(key: String): RimeConfig {
69+
check(ptr != 0L)
70+
return RimeConfig(getRimeConfigItem(ptr, key))
71+
}
72+
73+
override fun close() {
74+
if (ptr != 0L) {
75+
closeRimeConfig(ptr)
76+
}
77+
}
78+
79+
companion object {
80+
@JvmStatic
81+
private external fun openRimeSchema(schemaId: String): Long
82+
83+
@JvmStatic
84+
private external fun openRimeConfig(configId: String): Long
85+
86+
@JvmStatic
87+
private external fun openRimeUserConfig(configId: String): Long
88+
89+
@JvmStatic
90+
private external fun getRimeConfigString(
91+
ptr: Long,
92+
key: String,
93+
): String?
94+
95+
@JvmStatic
96+
private external fun getRimeConfigBool(
97+
ptr: Long,
98+
key: String,
99+
): Boolean?
100+
101+
@JvmStatic
102+
private external fun getRimeConfigDouble(
103+
ptr: Long,
104+
key: String,
105+
): Double?
106+
107+
@JvmStatic
108+
private external fun getRimeConfigInt(
109+
ptr: Long,
110+
key: String,
111+
): Int?
112+
113+
@JvmStatic
114+
private external fun getRimeConfigList(
115+
ptr: Long,
116+
key: String,
117+
): LongArray?
118+
119+
@JvmStatic
120+
private external fun getRimeConfigMap(
121+
ptr: Long,
122+
key: String,
123+
): Map<String, Long>?
124+
125+
@JvmStatic
126+
private external fun getRimeConfigItem(
127+
ptr: Long,
128+
key: String,
129+
): Long
130+
131+
@JvmStatic
132+
private external fun closeRimeConfig(ptr: Long)
133+
134+
fun openSchema(schemaId: String) = RimeConfig(openRimeSchema(schemaId))
135+
136+
fun openConfig(configId: String) = RimeConfig(openRimeConfig(configId))
137+
138+
fun openUserConfig(configId: String) = RimeConfig(openRimeUserConfig(configId))
139+
}
140+
}

app/src/main/java/com/osfans/trime/data/base/DataManager.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ object DataManager {
5353
val userDataDir
5454
get() = File(prefs.profile.userDataDir).also { it.mkdirs() }
5555

56+
val prebuiltDataDir = File(sharedDataDir, "build")
57+
val stagingDir get() = File(userDataDir, "build")
58+
5659
/**
5760
* Return the absolute path of the compiled config file
5861
* based on given resource id.
@@ -62,9 +65,6 @@ object DataManager {
6265
*/
6366
@JvmStatic
6467
fun resolveDeployedResourcePath(resourceId: String): String {
65-
val stagingDir = File(userDataDir, "build")
66-
val prebuiltDataDir = File(sharedDataDir, "build")
67-
6868
val defaultPath = File(stagingDir, "$resourceId.yaml")
6969
if (!defaultPath.exists()) {
7070
val fallbackPath = File(prebuiltDataDir, "$resourceId.yaml")

app/src/main/java/com/osfans/trime/data/schema/Schema.kt

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,44 @@
44

55
package com.osfans.trime.data.schema
66

7-
import com.osfans.trime.util.config.Config
8-
import kotlinx.serialization.Serializable
9-
import kotlinx.serialization.Transient
7+
import com.osfans.trime.core.RimeConfig
8+
import timber.log.Timber
109

1110
class Schema(
12-
schemaId: String = ".default",
11+
schemaId: String,
1312
) {
14-
private val config =
15-
if (schemaId == ".default") {
16-
Config.create("default")
17-
} else {
18-
Config.create("$schemaId.schema")
19-
}
13+
val switches: List<Switch>
2014

21-
val switches get() =
22-
config?.getList("switches")
15+
val symbols: Map<String, RimeConfig>
2316

24-
val symbols get() =
25-
config?.getMap("punctuator/symbols")
17+
val alphabet: String
2618

27-
val alphabet get() = config?.getString("speller/alphabet")
19+
init {
20+
RimeConfig.openSchema(schemaId).use { c ->
21+
switches =
22+
c.getList("switches").mapNotNull decode@{ e ->
23+
try {
24+
Switch(
25+
name = e.getString("name"),
26+
options = e.getStringList("options"),
27+
reset = e.getInt("reset", -1),
28+
states = e.getStringList("states"),
29+
)
30+
} catch (e: Exception) {
31+
Timber.e(e, "Failed to decode switches of schema '$schemaId'")
32+
null
33+
}
34+
}
35+
symbols = c.getMap("punctuator/symbols")
36+
alphabet = c.getString("speller/alphabet")
37+
}
38+
}
2839

29-
@Serializable
3040
data class Switch(
3141
val name: String = "",
3242
val options: List<String> = listOf(),
3343
val reset: Int = -1,
3444
val states: List<String> = listOf(),
35-
@Transient var enabled: Int = 0,
45+
var enabled: Int = 0,
3646
)
3747
}

app/src/main/java/com/osfans/trime/data/schema/SchemaManager.kt

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,22 @@
55
package com.osfans.trime.data.schema
66

77
import com.osfans.trime.core.Rime
8-
import kotlinx.serialization.builtins.ListSerializer
98

109
object SchemaManager {
1110
private lateinit var currentSchema: Schema
1211
var visibleSwitches: List<Schema.Switch> = listOf()
1312

14-
private val defaultSchema = Schema()
15-
1613
@JvmStatic
1714
fun init(schemaId: String) {
18-
currentSchema = runCatching { Schema(schemaId) }.getOrDefault(defaultSchema)
19-
visibleSwitches = currentSchema.switches
20-
?.decode(ListSerializer(Schema.Switch.serializer()))
21-
?.filter { it.states.isNotEmpty() } ?: listOf() // 剔除没有 states 条目项的值,它们不作为开关使用
15+
currentSchema = Schema(schemaId)
16+
visibleSwitches =
17+
currentSchema.switches
18+
.filter { it.states.isNotEmpty() } // 剔除没有 states 条目项的值,它们不作为开关使用
2219
updateSwitchOptions()
2320
}
2421

2522
val activeSchema: Schema
26-
get() = runCatching { currentSchema }.getOrDefault(defaultSchema)
23+
get() = currentSchema
2724

2825
@JvmStatic
2926
fun updateSwitchOptions() {

app/src/main/java/com/osfans/trime/data/theme/ThemeFilesManager.kt

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ package com.osfans.trime.data.theme
88
import com.charleskorn.kaml.AnchorsAndAliases
99
import com.charleskorn.kaml.Yaml
1010
import com.charleskorn.kaml.YamlConfiguration
11-
import com.charleskorn.kaml.YamlScalar
12-
import com.charleskorn.kaml.yamlMap
11+
import com.osfans.trime.core.RimeConfig
12+
import com.osfans.trime.data.base.DataManager
1313
import timber.log.Timber
1414
import java.io.File
1515

@@ -25,17 +25,27 @@ object ThemeFilesManager {
2525

2626
fun listThemes(dir: File): MutableList<ThemeItem> {
2727
val files = dir.listFiles { _, name -> name.endsWith("trime.yaml") } ?: return mutableListOf()
28+
val deployedMap = hashMapOf<String, String>()
29+
DataManager.stagingDir.list()?.forEach {
30+
deployedMap[it] = it
31+
}
32+
DataManager.prebuiltDataDir.list()?.forEach {
33+
deployedMap[it] = it
34+
}
2835
return files
2936
.sortedByDescending { it.lastModified() }
3037
.mapNotNull decode@{
3138
val item =
3239
runCatching {
33-
val map =
34-
yaml
35-
.parseToYamlNode(it.bufferedReader().readText())
36-
.yamlMap
3740
val configId = it.nameWithoutExtension
38-
val name = map.get<YamlScalar>("name")?.content ?: ""
41+
val name =
42+
if (deployedMap[it.name] != null) {
43+
RimeConfig.openConfig(configId).use {
44+
it.getString("name")
45+
}
46+
} else {
47+
configId.removeSuffix(".trime")
48+
}
3949
ThemeItem(configId, name)
4050
}.getOrElse { e ->
4151
Timber.w("Failed to decode theme file ${it.absolutePath}: ${e.message}")

app/src/main/java/com/osfans/trime/ime/symbol/TabManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ object TabManager {
8888

8989
val symbolMaps = SchemaManager.activeSchema.symbols
9090
for ((key, value) in p) {
91-
if (symbolMaps?.containsKey(value) == true) {
91+
if (symbolMaps.containsKey(value)) {
9292
keysList.add(SimpleKeyBean(value, key))
9393
}
9494
}

0 commit comments

Comments
 (0)