ircfmt: Allow unicode characters

This commit is contained in:
Daniel Oaks 2017-10-09 07:29:36 +10:00
parent a5eafb7ec8
commit 3a2b80af9b
2 changed files with 75 additions and 32 deletions

@ -3,7 +3,9 @@
package ircfmt package ircfmt
import "strings" import (
"strings"
)
const ( const (
// raw bytes and strings to do replacing with // raw bytes and strings to do replacing with
@ -13,7 +15,7 @@ const (
underline string = "\x1f" underline string = "\x1f"
reset string = "\x0f" reset string = "\x0f"
bytecolour byte = '\x03' runecolour rune = '\x03'
// valid characters for an initial colour code, for speed // valid characters for an initial colour code, for speed
colours1 string = "0123456789" colours1 string = "0123456789"
@ -112,32 +114,44 @@ func Escape(in string) string {
// replace colour codes // replace colour codes
out := "" out := ""
for len(in) > 0 { var skip int
if in[0] == bytecolour { for i, x := range in {
out += "$c" // skip chars if necessary
in = in[1:] if 0 < skip {
skip--
continue
}
if len(in) < 1 || !strings.Contains(colours1, string(in[0])) { if x == runecolour {
out += "$c"
i++ // to refer to color code
if len(in) < i+2 || !strings.Contains(colours1, string(in[i])) {
out += "[]" out += "[]"
continue continue
} }
out += "[" out += "["
in = in[i:]
for _, vals := range numtocolour { for _, vals := range numtocolour {
code, name := vals[0], vals[1] code, name := vals[0], vals[1]
if strings.HasPrefix(in, code) { if strings.HasPrefix(in, code) {
in = strings.TrimPrefix(in, code) in = strings.TrimPrefix(in, code)
out += name out += name
i = 0 // refer to char after colour code
skip += len(code)
if len(in) > 1 && in[0] == ',' { if i+2 < len(in) && in[i] == ',' {
searchin := in[1:] i++ // refer to colour code after comma
skip++
in := in[i:]
for _, vals = range numtocolour { for _, vals = range numtocolour {
code, name = vals[0], vals[1] code, name = vals[0], vals[1]
if strings.HasPrefix(searchin, code) { if strings.HasPrefix(in, code) {
out += "," out += ","
out += name out += name
in = strings.TrimPrefix(in[1:], code) skip += len(code)
break break
} }
} }
@ -148,8 +162,7 @@ func Escape(in string) string {
out += "]" out += "]"
} else { } else {
out += string(in[0]) out += string(x)
in = in[1:]
} }
} }
@ -163,51 +176,80 @@ func Escape(in string) string {
func Unescape(in string) string { func Unescape(in string) string {
out := "" out := ""
for len(in) > 0 { var skip int
if in[0] == '$' && len(in) > 1 { for i, x := range in {
val, exists := escapetoval[in[1]] // skip if necessary
if 0 < skip {
skip--
continue
}
// chars exist and formatting code thrown our way
i++ // to now refer to the formatting code character
if x == '$' && 0 < len(in)-i {
val, exists := escapetoval[in[i]]
if exists == true { if exists == true {
out += string(val) skip++ // to skip the formatting code character
in = in[2:] out += val
} else if in[1] == 'c' { } else if in[i] == 'c' {
skip++ // to skip the formatting code character
out += colour out += colour
in = in[2:]
// ensure '[' follows before doing further processing // ensure '[' follows before doing further processing
if len(in) < 1 || in[0] != '[' { i++ // refer to the opening bracket
if (len(in)-i) < 1 || in[i] != '[' {
continue continue
} else { } else {
// strip leading '[' // strip leading '['
in = in[1:] skip++
} }
splitin := strings.SplitN(in, "]", 2) var buffer string
colournames := strings.Split(splitin[0], ",") var colournames []string
in = splitin[1] for j, y := range in {
// get to color names and all
if j <= i {
continue
}
// skip this character in the real loop as well
skip++
// so we can refer to the char after the loop as well
i = j
// record color names
if y == ']' {
i++
break
} else if y == ',' {
colournames = append(colournames, buffer)
buffer = ""
} else {
buffer += string(y)
}
}
colournames = append(colournames, buffer)
if len(colournames) > 1 { if len(colournames) > 1 {
out += colourcodesTruncated[colournames[0]] out += colourcodesTruncated[colournames[0]]
out += "," out += ","
if len(in) > 0 && strings.Contains(colours1, string(in[0])) { if i < len(in) && strings.Contains(colours1, string(in[i])) {
out += colourcodesFull[colournames[1]] out += colourcodesFull[colournames[1]]
} else { } else {
out += colourcodesTruncated[colournames[1]] out += colourcodesTruncated[colournames[1]]
} }
} else { } else {
if len(in) > 0 && strings.Contains(colours1, string(in[0])) { if i < len(in) && strings.Contains(colours1, string(in[i])) {
out += colourcodesFull[colournames[0]] out += colourcodesFull[colournames[0]]
} else { } else {
out += colourcodesTruncated[colournames[0]] out += colourcodesTruncated[colournames[0]]
} }
} }
} else { } else {
out += string(in[1]) // unknown formatting character, intentionally fall-through
in = in[2:]
} }
} else { } else {
out += string(in[0]) out += string(x)
in = in[1:]
} }
} }

@ -13,6 +13,7 @@ var tests = []testcase{
{"te$c[red,green]st", "te\x034,3st"}, {"te$c[red,green]st", "te\x034,3st"},
{"te$c[green]4st", "te\x03034st"}, {"te$c[green]4st", "te\x03034st"},
{"te$c[red,green]9st", "te\x034,039st"}, {"te$c[red,green]9st", "te\x034,039st"},
{" ▀█▄▀▪.▀ ▀ ▀ ▀ ·▀▀▀▀ ▀█▄▀ ▀▀ █▪ ▀█▄▀▪", " ▀█▄▀▪.▀ ▀ ▀ ▀ ·▀▀▀▀ ▀█▄▀ ▀▀ █▪ ▀█▄▀▪"},
} }
var escapetests = []testcase{ var escapetests = []testcase{