Skip to content

Commit 3128121

Browse files
committed
refactor: make clear how to get and expand active text for command express
1 parent 3b59952 commit 3128121

File tree

4 files changed

+74
-46
lines changed

4 files changed

+74
-46
lines changed

app/src/main/java/com/osfans/trime/core/Rime.kt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow
1515
import kotlinx.coroutines.flow.asSharedFlow
1616
import kotlinx.coroutines.withContext
1717
import timber.log.Timber
18-
import kotlin.system.measureTimeMillis
1918

2019
/**
2120
* Rime JNI and instance methods
@@ -41,6 +40,15 @@ class Rime :
4140
override var inputStatusCached = InputStatus()
4241
private set
4342

43+
override var compositionCached = RimeProto.Context.Composition()
44+
private set
45+
46+
override var menuCached = RimeProto.Context.Menu()
47+
private set
48+
49+
override var rawInputCached = ""
50+
private set
51+
4452
private val dispatcher =
4553
RimeDispatcher(
4654
object : RimeDispatcher.RimeLooper {
@@ -206,6 +214,9 @@ class Rime :
206214
}
207215
}
208216
inputContext = data.context // for compatibility
217+
compositionCached = data.context.composition
218+
menuCached = data.context.menu
219+
rawInputCached = data.context.input
209220
}
210221
else -> {}
211222
}
@@ -272,10 +283,6 @@ class Rime :
272283
@JvmStatic
273284
fun showAsciiPunch(): Boolean = inputStatus?.isAsciiPunch == true || inputStatus?.isAsciiMode == true
274285

275-
@JvmStatic
276-
val composingText: String
277-
get() = inputContext?.composition?.commitTextPreview ?: ""
278-
279286
@JvmStatic
280287
fun simulateKeySequence(sequence: CharSequence): Boolean {
281288
if (!sequence.first().isAsciiPrintable()) return false

app/src/main/java/com/osfans/trime/core/RimeApi.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ interface RimeApi {
1717

1818
val inputStatusCached: InputStatus
1919

20+
val compositionCached: RimeProto.Context.Composition
21+
22+
val menuCached: RimeProto.Context.Menu
23+
24+
val rawInputCached: String
25+
2026
suspend fun isEmpty(): Boolean
2127

2228
suspend fun processKey(

app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@ import android.view.inputmethod.InlineSuggestionsResponse
3131
import android.widget.FrameLayout
3232
import androidx.annotation.Keep
3333
import androidx.core.content.ContextCompat
34+
import androidx.core.view.inputmethod.EditorInfoCompat
3435
import androidx.core.view.isVisible
3536
import androidx.core.view.updateLayoutParams
3637
import androidx.lifecycle.lifecycleScope
3738
import com.osfans.trime.BuildConfig
3839
import com.osfans.trime.R
3940
import com.osfans.trime.core.KeyModifiers
4041
import com.osfans.trime.core.KeyValue
41-
import com.osfans.trime.core.Rime
4242
import com.osfans.trime.core.RimeApi
4343
import com.osfans.trime.core.RimeKeyMapping
4444
import com.osfans.trime.core.RimeMessage
@@ -736,22 +736,6 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
736736
return true
737737
}
738738

739-
fun getActiveText(type: Int): String {
740-
if (type == 2) return Rime.getRimeRawInput() ?: "" // 當前編碼
741-
var s = Rime.composingText // 當前候選
742-
if (s.isEmpty()) {
743-
val ic = currentInputConnection
744-
var cs = ic?.getSelectedText(0) // 選中字
745-
if (type == 1 && cs.isNullOrEmpty()) cs = lastCommittedText // 剛上屏字
746-
if (cs.isNullOrEmpty() && ic != null) {
747-
cs = ic.getTextBeforeCursor(if (type == 4) 1024 else 1, 0) // 光標前字
748-
}
749-
if (cs.isNullOrEmpty() && ic != null) cs = ic.getTextAfterCursor(1024, 0) // 光標後面所有字
750-
if (cs != null) s = cs.toString()
751-
}
752-
return s
753-
}
754-
755739
private fun forwardKeyEvent(event: KeyEvent): Boolean {
756740
val modifiers = KeyModifiers.fromKeyEvent(event)
757741
val charCode = event.unicodeChar
@@ -976,6 +960,46 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
976960
}
977961
}
978962

963+
fun getActiveText(type: Int): String {
964+
if (type == 2) return rime.run { rawInputCached } // 當前編碼
965+
var text: CharSequence? = rime.run { compositionCached }.commitTextPreview // 當前候選
966+
if (text.isNullOrEmpty()) {
967+
val info = currentInputEditorInfo
968+
text = EditorInfoCompat.getInitialSelectedText(info, 0) // 選中字
969+
}
970+
if (text.isNullOrEmpty()) {
971+
if (type == 1) text = lastCommittedText // 剛上屏字
972+
}
973+
if (text.isNullOrEmpty()) {
974+
val step = if (type == 4) 1024 else 1
975+
text = getTextAroundCursor(step, before = true)
976+
}
977+
if (text.isNullOrEmpty()) {
978+
text = getTextAroundCursor(before = false)
979+
}
980+
return text.toString()
981+
}
982+
983+
private fun getTextAroundCursor(
984+
initialStep: Int = 1024,
985+
before: Boolean,
986+
): String? {
987+
val info = currentInputEditorInfo ?: return null
988+
var step = initialStep
989+
while (true) {
990+
val text =
991+
if (before) {
992+
EditorInfoCompat.getInitialTextBeforeCursor(info, step, 0)
993+
} else {
994+
EditorInfoCompat.getInitialTextAfterCursor(info, step, 0)
995+
} ?: return null
996+
if (text.length < step) {
997+
return text.toString()
998+
}
999+
step *= 2
1000+
}
1001+
}
1002+
9791003
override fun onEvaluateFullscreenMode(): Boolean = false
9801004

9811005
private var showingDialog: Dialog? = null

app/src/main/java/com/osfans/trime/ime/keyboard/CommonKeyboardActionListener.kt

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ class CommonKeyboardActionListener(
6060

6161
/** Pattern for braced key event to capture `{Escape}` as group 2 */
6262
private val BRACED_KEY_EVENT_WITH_ESCAPE = """^((\{Escape\})?[^{}]+).*$""".toRegex()
63+
64+
private val PLACEHOLDER_PATTERN = Regex(".*(%([1-4]\\$)?s).*")
6365
}
6466

6567
private val prefs = AppPrefs.defaultInstance()
@@ -115,6 +117,18 @@ class CommonKeyboardActionListener(
115117
}
116118
}
117119

120+
private fun expandActiveText(input: String): String =
121+
if (input.matches(PLACEHOLDER_PATTERN)) {
122+
input.format(
123+
service.getActiveText(1),
124+
service.getActiveText(2),
125+
service.getActiveText(3),
126+
service.getActiveText(4),
127+
)
128+
} else {
129+
input
130+
}
131+
118132
val listener by lazy {
119133
object : KeyboardActionListener {
120134
override fun onPress(keyEventCode: Int) {
@@ -160,30 +174,7 @@ class CommonKeyboardActionListener(
160174
}
161175
}
162176
KeyEvent.KEYCODE_FUNCTION -> { // Command Express
163-
// Comments from trime.yaml:
164-
// %s或者%1$s爲當前字符
165-
// %2$s爲當前輸入的編碼
166-
// %3$s爲光標前字符
167-
// %4$s爲光標前所有字符
168-
var arg = action.option
169-
val activeTextRegex = Regex(".*%(\\d*)\\$" + "s.*")
170-
if (arg.matches(activeTextRegex)) {
171-
var activeTextMode =
172-
arg.replaceFirst(activeTextRegex, "$1").toDouble().toInt()
173-
if (activeTextMode < 1) {
174-
activeTextMode = 1
175-
}
176-
val activeText = service.getActiveText(activeTextMode)
177-
arg =
178-
String.format(
179-
arg,
180-
service.lastCommittedText,
181-
Rime.getRimeRawInput() ?: "",
182-
activeText,
183-
activeText,
184-
)
185-
}
186-
177+
val arg = expandActiveText(action.option)
187178
when (action.command) {
188179
"liquid_keyboard" -> {
189180
val target =

0 commit comments

Comments
 (0)