oh-my-posh/src/config/migrate_glyphs.go
2024-07-04 11:05:24 +02:00

141 lines
2.7 KiB
Go

package config
import (
"context"
"fmt"
"io"
httplib "net/http"
"strconv"
"strings"
"time"
"github.com/jandedobbeleer/oh-my-posh/src/runtime/http"
)
type ConnectionError struct {
reason string
}
func (f *ConnectionError) Error() string {
return f.reason
}
type codePoints map[uint64]uint64
func getGlyphCodePoints() (codePoints, error) {
var codePoints = make(codePoints)
ctx, cncl := context.WithTimeout(context.Background(), time.Millisecond*time.Duration(5000))
defer cncl()
request, err := httplib.NewRequestWithContext(ctx, httplib.MethodGet, "https://ohmyposh.dev/codepoints.csv", nil)
if err != nil {
return codePoints, &ConnectionError{reason: err.Error()}
}
response, err := http.HTTPClient.Do(request)
if err != nil {
return codePoints, err
}
defer response.Body.Close()
bytes, err := io.ReadAll(response.Body)
if err != nil {
return codePoints, err
}
lines := strings.Split(string(bytes), "\n")
for _, line := range lines {
fields := strings.Split(line, ",")
if len(fields) < 2 {
continue
}
oldGlyph, err := strconv.ParseUint(fields[0], 16, 32)
if err != nil {
continue
}
newGlyph, err := strconv.ParseUint(fields[1], 16, 32)
if err != nil {
continue
}
codePoints[oldGlyph] = newGlyph
}
return codePoints, nil
}
func escapeGlyphs(s string, migrate bool) string {
shouldExclude := func(r rune) bool {
if r < 0x1000 { // Basic Multilingual Plane
return true
}
if r > 0x1F600 && r < 0x1F64F { // Emoticons
return true
}
if r > 0x1F300 && r < 0x1F5FF { // Misc Symbols and Pictographs
return true
}
if r > 0x1F680 && r < 0x1F6FF { // Transport and Map
return true
}
if r > 0x2600 && r < 0x26FF { // Misc symbols
return true
}
if r > 0x2700 && r < 0x27BF { // Dingbats
return true
}
if r > 0xFE00 && r < 0xFE0F { // Variation Selectors
return true
}
if r > 0x1F900 && r < 0x1F9FF { // Supplemental Symbols and Pictographs
return true
}
if r > 0x1F1E6 && r < 0x1F1FF { // Flags
return true
}
return false
}
var cp codePoints
var err error
if migrate {
cp, err = getGlyphCodePoints()
if err != nil {
migrate = false
}
}
var builder strings.Builder
for _, r := range s {
// exclude regular characters and emojis
if shouldExclude(r) {
builder.WriteRune(r)
continue
}
if migrate {
if val, OK := cp[uint64(r)]; OK {
r = rune(val)
}
}
if r > 0x10000 {
// calculate surrogate pairs
one := 0xd800 + (((r - 0x10000) >> 10) & 0x3ff)
two := 0xdc00 + ((r - 0x10000) & 0x3ff)
quoted := fmt.Sprintf("\\u%04x\\u%04x", one, two)
builder.WriteString(quoted)
continue
}
quoted := fmt.Sprintf("\\u%04x", r)
builder.WriteString(quoted)
}
return builder.String()
}