mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-03-11 13:23:06 +01:00
lots of changes. new wshrpc implementation. unify websocket, web, blockcontroller, domain sockets, and terminal inputs to all use the new rpc system. lots of moving files around to deal with circular dependencies use new wshrpc as a client in wsh cmd
97 lines
2.3 KiB
Go
97 lines
2.3 KiB
Go
// Copyright 2024, Command Line Inc.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package wshutil
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
// these should both be 5 characters
|
|
const WaveOSC = "23198"
|
|
const WaveServerOSC = "23199"
|
|
const WaveOSCPrefixLen = 5 + 3 // \x1b] + WaveOSC + ; + \x07
|
|
|
|
const WaveOSCPrefix = "\x1b]" + WaveOSC + ";"
|
|
const WaveServerOSCPrefix = "\x1b]" + WaveServerOSC + ";"
|
|
|
|
const HexChars = "0123456789ABCDEF"
|
|
const BEL = 0x07
|
|
const ST = 0x9c
|
|
const ESC = 0x1b
|
|
|
|
// OSC escape types
|
|
// OSC 23198 ; (JSON | base64-JSON) ST
|
|
// JSON = must escape all ASCII control characters ([\x00-\x1F\x7F])
|
|
// we can tell the difference between JSON and base64-JSON by the first character: '{' or not
|
|
|
|
// for responses (terminal -> program), we'll use OSC 23199
|
|
// same json format
|
|
|
|
func copyOscPrefix(dst []byte, oscNum string) {
|
|
dst[0] = ESC
|
|
dst[1] = ']'
|
|
copy(dst[2:], oscNum)
|
|
dst[len(oscNum)+2] = ';'
|
|
}
|
|
|
|
func oscPrefixLen(oscNum string) int {
|
|
return 3 + len(oscNum)
|
|
}
|
|
|
|
func makeOscPrefix(oscNum string) []byte {
|
|
output := make([]byte, oscPrefixLen(oscNum))
|
|
copyOscPrefix(output, oscNum)
|
|
return output
|
|
}
|
|
|
|
func EncodeWaveOSCBytes(oscNum string, barr []byte) []byte {
|
|
if len(oscNum) != 5 {
|
|
panic("oscNum must be 5 characters")
|
|
}
|
|
hasControlChars := false
|
|
for _, b := range barr {
|
|
if b < 0x20 || b == 0x7F {
|
|
hasControlChars = true
|
|
break
|
|
}
|
|
}
|
|
if !hasControlChars {
|
|
// If no control characters, directly construct the output
|
|
// \x1b] (2) + WaveOSC + ; (1) + message + \x07 (1)
|
|
output := make([]byte, oscPrefixLen(oscNum)+len(barr)+1)
|
|
copyOscPrefix(output, oscNum)
|
|
copy(output[oscPrefixLen(oscNum):], barr)
|
|
output[len(output)-1] = BEL
|
|
return output
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
buf.Write(makeOscPrefix(oscNum))
|
|
escSeq := [6]byte{'\\', 'u', '0', '0', '0', '0'}
|
|
for _, b := range barr {
|
|
if b < 0x20 || b == 0x7f {
|
|
escSeq[4] = HexChars[b>>4]
|
|
escSeq[5] = HexChars[b&0x0f]
|
|
buf.Write(escSeq[:])
|
|
} else {
|
|
buf.WriteByte(b)
|
|
}
|
|
}
|
|
buf.WriteByte(BEL)
|
|
return buf.Bytes()
|
|
}
|
|
|
|
func EncodeWaveOSCMessageEx(oscNum string, msg *RpcMessage) ([]byte, error) {
|
|
if msg == nil {
|
|
return nil, fmt.Errorf("nil message")
|
|
}
|
|
barr, err := json.Marshal(msg)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error marshalling message to json: %w", err)
|
|
}
|
|
return EncodeWaveOSCBytes(oscNum, barr), nil
|
|
}
|