mirror of
https://github.com/TermoraDev/termora.git
synced 2026-01-16 02:12:58 +08:00
feat: xterm DCS
This commit is contained in:
@@ -1,36 +0,0 @@
|
||||
package app.termora.terminal
|
||||
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class DeviceControlProcessor(private val terminal: Terminal) : Processor {
|
||||
private val args = StringBuilder()
|
||||
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(DeviceControlProcessor::class.java)
|
||||
}
|
||||
|
||||
|
||||
override fun process(ch: Char): ProcessorState {
|
||||
val state = when (ch) {
|
||||
ControlCharacters.ST -> {
|
||||
if (log.isWarnEnabled) {
|
||||
log.warn("Ignore DCS: {}", args)
|
||||
}
|
||||
TerminalState.READY
|
||||
}
|
||||
|
||||
else -> {
|
||||
args.append(ch)
|
||||
TerminalState.DCS
|
||||
}
|
||||
}
|
||||
|
||||
if (state == TerminalState.READY) {
|
||||
args.clear()
|
||||
}
|
||||
|
||||
return state
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package app.termora.terminal
|
||||
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class DeviceControlStringProcessor(terminal: Terminal, reader: TerminalReader) : AbstractProcessor(terminal, reader) {
|
||||
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(DeviceControlStringProcessor::class.java)
|
||||
}
|
||||
|
||||
private val systemCommandSequence = SystemCommandSequence()
|
||||
|
||||
override fun process(ch: Char): ProcessorState {
|
||||
// 回退回去,然后重新读取出来
|
||||
reader.addFirst(ch)
|
||||
|
||||
do {
|
||||
|
||||
if (systemCommandSequence.process(reader.read())) {
|
||||
break
|
||||
}
|
||||
|
||||
// 如果没有检测到结束,那么退出重新来
|
||||
if (reader.isEmpty()) {
|
||||
return TerminalState.DCS
|
||||
}
|
||||
|
||||
} while (reader.isNotEmpty())
|
||||
|
||||
processCommand(systemCommandSequence.getCommand())
|
||||
|
||||
systemCommandSequence.reset()
|
||||
|
||||
return TerminalState.READY
|
||||
}
|
||||
|
||||
|
||||
private fun processCommand(command: String) {
|
||||
if (command.isEmpty()) {
|
||||
return
|
||||
}
|
||||
if (log.isWarnEnabled) {
|
||||
log.warn("Cannot process command: {}", command)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,9 +128,9 @@ class EscapeSequenceProcessor(terminal: Terminal, reader: TerminalReader) : Abst
|
||||
|
||||
}
|
||||
|
||||
// TODO Device Control String (DCS is 0x90).
|
||||
// Device Control String (DCS is 0x90).
|
||||
'P' -> {
|
||||
|
||||
state = TerminalState.DCS
|
||||
}
|
||||
|
||||
// Start of Guarded Area (SPA is 0x96).
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.awt.datatransfer.StringSelection
|
||||
|
||||
class OperatingSystemCommandProcessor(terminal: Terminal, reader: TerminalReader) :
|
||||
AbstractProcessor(terminal, reader) {
|
||||
private val args = StringBuilder()
|
||||
private val systemCommandSequence = SystemCommandSequence()
|
||||
private val colorPalette get() = terminal.getTerminalModel().getColorPalette()
|
||||
|
||||
companion object {
|
||||
@@ -20,14 +20,7 @@ class OperatingSystemCommandProcessor(terminal: Terminal, reader: TerminalReader
|
||||
|
||||
do {
|
||||
|
||||
val c = reader.read()
|
||||
args.append(c)
|
||||
if (c == ControlCharacters.BEL || c == ControlCharacters.ST) {
|
||||
args.deleteAt(args.lastIndex)
|
||||
break
|
||||
} else if (c == '\\' && args.length >= 2 && args[args.length - 2] == ControlCharacters.ESC) {
|
||||
args.deleteAt(args.lastIndex)
|
||||
args.deleteAt(args.lastIndex)
|
||||
if (systemCommandSequence.process(reader.read())) {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -42,7 +35,7 @@ class OperatingSystemCommandProcessor(terminal: Terminal, reader: TerminalReader
|
||||
// process osc
|
||||
processOperatingSystemCommandProcessor()
|
||||
|
||||
args.clear()
|
||||
systemCommandSequence.reset()
|
||||
|
||||
return TerminalState.READY
|
||||
}
|
||||
@@ -52,6 +45,7 @@ class OperatingSystemCommandProcessor(terminal: Terminal, reader: TerminalReader
|
||||
* https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands
|
||||
*/
|
||||
private fun processOperatingSystemCommandProcessor() {
|
||||
val args = systemCommandSequence.getCommand()
|
||||
val idx = args.indexOfFirst { it == ';' }
|
||||
if (idx == -1) {
|
||||
return
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package app.termora.terminal
|
||||
|
||||
class SystemCommandSequence {
|
||||
private var isTerminated = false
|
||||
private val command = StringBuilder()
|
||||
|
||||
/**
|
||||
* @return 返回 true 表示处理完毕
|
||||
*/
|
||||
fun process(c: Char): Boolean {
|
||||
|
||||
if (isTerminated) {
|
||||
throw UnsupportedOperationException("Cannot be processed, call the reset method")
|
||||
}
|
||||
|
||||
command.append(c)
|
||||
if (c == ControlCharacters.BEL || c == ControlCharacters.ST) {
|
||||
command.deleteAt(command.lastIndex)
|
||||
isTerminated = true
|
||||
} else if (c == '\\' && command.length >= 2 && command[command.length - 2] == ControlCharacters.ESC) {
|
||||
command.deleteAt(command.lastIndex)
|
||||
command.deleteAt(command.lastIndex)
|
||||
isTerminated = true
|
||||
}
|
||||
|
||||
return isTerminated
|
||||
}
|
||||
|
||||
fun getCommand(): String {
|
||||
return command.toString()
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
isTerminated = false
|
||||
command.clear()
|
||||
}
|
||||
}
|
||||
@@ -129,7 +129,7 @@ private class MyProcessor(private val terminal: Terminal, reader: TerminalReader
|
||||
TerminalState.CSI to ControlSequenceIntroducerProcessor(terminal, reader),
|
||||
TerminalState.OSC to OperatingSystemCommandProcessor(terminal, reader),
|
||||
TerminalState.ESC_LPAREN to EscapeDesignateCharacterSetProcessor(terminal, reader),
|
||||
TerminalState.DCS to DeviceControlProcessor(terminal),
|
||||
TerminalState.DCS to DeviceControlStringProcessor(terminal, reader),
|
||||
TerminalState.Text to TextProcessor(terminal, reader),
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user