Support multiple options in one SGR ansi cmd

This commit is contained in:
bloeys
2022-09-25 02:39:50 +04:00
parent 976682d2d2
commit a127b72960
2 changed files with 54 additions and 43 deletions

View File

@ -114,32 +114,33 @@ var (
// AnsiCSIStringBytesLen = len(AnsiCSIStringBytes) // AnsiCSIStringBytesLen = len(AnsiCSIStringBytes)
) )
type AnsiCodeOptions int64 type AnsiCodePayloadType int32
const ( const (
AnsiCodeOptions_ColorFg AnsiCodeOptions = 1 << iota AnsiCodePayloadType_Unknown AnsiCodePayloadType = iota
AnsiCodeOptions_ColorBg AnsiCodePayloadType_ColorFg
AnsiCodeOptions_ColorDefault AnsiCodePayloadType_ColorBg
AnsiCodePayloadType_Reset
AnsiCodeOptions_CursorOffset AnsiCodePayloadType_CursorOffset
AnsiCodeOptions_CursorAbs AnsiCodePayloadType_CursorAbs
AnsiCodeOptions_LineOffset AnsiCodePayloadType_LineOffset
AnsiCodeOptions_LineAbs AnsiCodePayloadType_LineAbs
AnsiCodeOptions_ScrollOffset AnsiCodePayloadType_ScrollOffset
// This is at the bottom so the above iota starts at 0
AnsiCodeOptions_Unknown AnsiCodeOptions = 0
) )
func (a AnsiCodeOptions) HasOptions(opts AnsiCodeOptions) bool { func (a AnsiCodePayloadType) HasOption(opt AnsiCodePayloadType) bool {
return a&opts != 0 return a == opt
}
type AnsiCodeInfoPayload struct {
Info gglm.Vec4
Type AnsiCodePayloadType
} }
type AnsiCodeInfo struct { type AnsiCodeInfo struct {
Type CSIType Type CSIType
// When type is CSIType_SGR and the code is reset info1.X=-1 Payload []AnsiCodeInfoPayload
Info1 gglm.Vec4
Options AnsiCodeOptions
} }
func NextAnsiCode(arr []byte) (index int, code []byte) { func NextAnsiCode(arr []byte) (index int, code []byte) {
@ -232,7 +233,7 @@ func InfoFromAnsiCode(code []byte) (info AnsiCodeInfo) {
case 'm': case 'm':
info.Type = CSIType_SGR info.Type = CSIType_SGR
ParseSGRArgs(&info, args) info.Payload = ParseSGRArgs(args)
case 'A': case 'A':
info.Type = CSIType_CUU info.Type = CSIType_CUU
case 'B': case 'B':
@ -270,32 +271,37 @@ func InfoFromAnsiCode(code []byte) (info AnsiCodeInfo) {
return info return info
} }
func ParseSGRArgs(info *AnsiCodeInfo, args []byte) { func ParseSGRArgs(args []byte) (payload []AnsiCodeInfoPayload) {
payload = make([]AnsiCodeInfoPayload, 0, 1)
// @TODO should we trim spaces? // @TODO should we trim spaces?
splitArgs := bytes.Split(args, []byte{';'}) splitArgs := bytes.Split(args, []byte{';'})
for _, a := range splitArgs { for _, a := range splitArgs {
if len(a) == 0 || a[0] == byte('0') { if len(a) == 0 || a[0] == byte('0') {
info.Info1.SetX(-1) payload = append(payload, AnsiCodeInfoPayload{
info.Options |= AnsiCodeOptions_ColorFg Type: AnsiCodePayloadType_Reset,
continue })
break
} }
// @TODO We can't use this setup of one info field because one ansi code can have many settings. // @TODO We can't use this setup of one info field because one ansi code can have many settings.
// For example, it can set Fg+Bg at once. So we need info per option. // For example, it can set Fg+Bg at once. So we need info per option.
intCode := getSgrIntCodeFromBytes(a) intCode := getSgrIntCodeFromBytes(a)
if intCode >= 30 && intCode <= 37 || intCode >= 90 && intCode <= 97 { if intCode >= 30 && intCode <= 37 || intCode >= 90 && intCode <= 97 {
payload = append(payload, AnsiCodeInfoPayload{
info.Info1 = ColorFromSgrCode(intCode) Info: ColorFromSgrCode(intCode),
info.Options |= AnsiCodeOptions_ColorFg Type: AnsiCodePayloadType_ColorFg,
})
continue continue
} }
if intCode >= 40 && intCode <= 47 || intCode >= 100 && intCode <= 107 { if intCode >= 40 && intCode <= 47 || intCode >= 100 && intCode <= 107 {
payload = append(payload, AnsiCodeInfoPayload{
info.Info1 = ColorFromSgrCode(intCode) Info: ColorFromSgrCode(intCode),
info.Options |= AnsiCodeOptions_ColorBg Type: AnsiCodePayloadType_ColorBg,
})
continue continue
} }
@ -303,6 +309,8 @@ func ParseSGRArgs(info *AnsiCodeInfo, args []byte) {
// @TODO Support 256 and RGB colors // @TODO Support 256 and RGB colors
println("Code not supported yet: " + fmt.Sprint(intCode)) println("Code not supported yet: " + fmt.Sprint(intCode))
} }
return payload
} }
func getSgrIntCodeFromBytes(bs []byte) (code int) { func getSgrIntCodeFromBytes(bs []byte) (code int) {
@ -350,7 +358,7 @@ func ColorFromSgrCode(code int) gglm.Vec4 {
case Ansi_Bg_Black: case Ansi_Bg_Black:
fallthrough fallthrough
case Ansi_Fg_Black: case Ansi_Fg_Black:
return gglm.Vec4{} return gglm.Vec4{Data: [4]float32{0, 0, 0, 1}}
case Ansi_Bg_Red: case Ansi_Bg_Red:
fallthrough fallthrough

29
main.go
View File

@ -444,22 +444,25 @@ func (nt *nterm) DrawTextAnsiCodesOnGlyphGrid(bs []byte) {
before := bytesToRunes(bs[:index]) before := bytesToRunes(bs[:index])
draw(before) draw(before)
//Apply code //Apply codes
info := ansi.InfoFromAnsiCode(code) ansiCodeInfo := ansi.InfoFromAnsiCode(code)
if info.Options.HasOptions(ansi.AnsiCodeOptions_ColorFg) { // fmt.Printf("Info: %+v\n", ansiCodeInfo)
for i := 0; i < len(ansiCodeInfo.Payload); i++ {
if info.Info1.X() == -1 { payload := &ansiCodeInfo.Payload[i]
if payload.Type.HasOption(ansi.AnsiCodePayloadType_Reset) {
currFgColor = nt.Settings.DefaultFgColor currFgColor = nt.Settings.DefaultFgColor
} else {
currFgColor = info.Info1
}
}
if info.Options.HasOptions(ansi.AnsiCodeOptions_ColorBg) {
if info.Info1.X() == -1 {
currBgColor = nt.Settings.DefaultBgColor currBgColor = nt.Settings.DefaultBgColor
} else { break
currBgColor = info.Info1 }
if payload.Type.HasOption(ansi.AnsiCodePayloadType_ColorFg) {
currFgColor = payload.Info
println("settings fg color to", payload.Info.String())
} else if payload.Type.HasOption(ansi.AnsiCodePayloadType_ColorBg) {
currBgColor = payload.Info
println("settings bg color to", payload.Info.String())
} }
} }