From 713f66beaa6e0c1ffc2481fe0bed3f60e45dead1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 14:45:42 +0000 Subject: [PATCH] build(deps): bump github.com/olekukonko/tablewriter from 1.1.2 to 1.1.3 Bumps [github.com/olekukonko/tablewriter](https://github.com/olekukonko/tablewriter) from 1.1.2 to 1.1.3. - [Release notes](https://github.com/olekukonko/tablewriter/releases) - [Commits](https://github.com/olekukonko/tablewriter/compare/v1.1.2...v1.1.3) --- updated-dependencies: - dependency-name: github.com/olekukonko/tablewriter dependency-version: 1.1.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 6 +- go.sum | 12 +- .../clipperhouse/displaywidth/CHANGELOG.md | 10 + .../clipperhouse/displaywidth/README.md | 114 ++-- .../clipperhouse/displaywidth/tables.go | 91 ---- .../clipperhouse/displaywidth/trie.go | 502 +++++++++--------- .../clipperhouse/displaywidth/width.go | 120 ++--- vendor/github.com/olekukonko/ll/global.go | 5 + .../github.com/olekukonko/ll/lh/colorized.go | 20 +- vendor/github.com/olekukonko/ll/lh/multi.go | 13 + vendor/github.com/olekukonko/ll/lh/slog.go | 5 +- vendor/github.com/olekukonko/ll/ll.go | 128 ++--- vendor/github.com/olekukonko/ll/lx/lx.go | 7 +- vendor/github.com/olekukonko/ll/options.go | 67 +++ .../olekukonko/tablewriter/README.md | 6 +- .../olekukonko/tablewriter/pkg/twwidth/ea.go | 424 +++++++++++++++ .../tablewriter/pkg/twwidth/width.go | 225 +++++--- .../tablewriter/renderer/colorized.go | 23 - .../olekukonko/tablewriter/renderer/tint.go | 25 + .../olekukonko/tablewriter/tablewriter.go | 25 +- .../github.com/olekukonko/tablewriter/zoo.go | 22 +- vendor/modules.txt | 6 +- 22 files changed, 1176 insertions(+), 680 deletions(-) delete mode 100644 vendor/github.com/clipperhouse/displaywidth/tables.go create mode 100644 vendor/github.com/olekukonko/ll/options.go create mode 100644 vendor/github.com/olekukonko/tablewriter/pkg/twwidth/ea.go create mode 100644 vendor/github.com/olekukonko/tablewriter/renderer/tint.go diff --git a/go.mod b/go.mod index e1c945f868..6e8ca23b6f 100644 --- a/go.mod +++ b/go.mod @@ -57,7 +57,7 @@ require ( github.com/nats-io/nats-server/v2 v2.12.3 github.com/nats-io/nats.go v1.48.0 github.com/oklog/run v1.2.0 - github.com/olekukonko/tablewriter v1.1.2 + github.com/olekukonko/tablewriter v1.1.3 github.com/onsi/ginkgo v1.16.5 github.com/onsi/ginkgo/v2 v2.27.5 github.com/onsi/gomega v1.39.0 @@ -165,7 +165,7 @@ require ( github.com/ceph/go-ceph v0.37.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cevaris/ordered_map v0.0.0-20190319150403-3adeae072e73 // indirect - github.com/clipperhouse/displaywidth v0.6.0 // indirect + github.com/clipperhouse/displaywidth v0.6.2 // indirect github.com/clipperhouse/stringish v0.1.1 // indirect github.com/clipperhouse/uax29/v2 v2.3.0 // indirect github.com/cloudflare/circl v1.6.1 // indirect @@ -312,7 +312,7 @@ require ( github.com/nxadm/tail v1.4.8 // indirect github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect github.com/olekukonko/errors v1.1.0 // indirect - github.com/olekukonko/ll v0.1.3 // indirect + github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect diff --git a/go.sum b/go.sum index b73161bc65..e3def257c4 100644 --- a/go.sum +++ b/go.sum @@ -223,8 +223,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/clipperhouse/displaywidth v0.6.0 h1:k32vueaksef9WIKCNcoqRNyKbyvkvkysNYnAWz2fN4s= -github.com/clipperhouse/displaywidth v0.6.0/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o= +github.com/clipperhouse/displaywidth v0.6.2 h1:ZDpTkFfpHOKte4RG5O/BOyf3ysnvFswpyYrV7z2uAKo= +github.com/clipperhouse/displaywidth v0.6.2/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o= github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4= @@ -940,11 +940,11 @@ github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0= github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= -github.com/olekukonko/ll v0.1.3 h1:sV2jrhQGq5B3W0nENUISCR6azIPf7UBUpVq0x/y70Fg= -github.com/olekukonko/ll v0.1.3/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew= +github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0 h1:jrYnow5+hy3WRDCBypUFvVKNSPPCdqgSXIE9eJDD8LM= +github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/olekukonko/tablewriter v1.1.2 h1:L2kI1Y5tZBct/O/TyZK1zIE9GlBj/TVs+AY5tZDCDSc= -github.com/olekukonko/tablewriter v1.1.2/go.mod h1:z7SYPugVqGVavWoA2sGsFIoOVNmEHxUAAMrhXONtfkg= +github.com/olekukonko/tablewriter v1.1.3 h1:VSHhghXxrP0JHl+0NnKid7WoEmd9/urKRJLysb70nnA= +github.com/olekukonko/tablewriter v1.1.3/go.mod h1:9VU0knjhmMkXjnMKrZ3+L2JhhtsQ/L38BbL3CRNE8tM= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= diff --git a/vendor/github.com/clipperhouse/displaywidth/CHANGELOG.md b/vendor/github.com/clipperhouse/displaywidth/CHANGELOG.md index ae1919a867..c97ce3b813 100644 --- a/vendor/github.com/clipperhouse/displaywidth/CHANGELOG.md +++ b/vendor/github.com/clipperhouse/displaywidth/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [0.6.1] + +[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.6.0...v0.6.1) + +### Changed +- Perf improvements: replaced the ASCII lookup table with a simple + function. A bit more cache-friendly. More inlining. +- Bug fix: single regional indicators are now treated as width 2, since that + is what actual terminals do. + ## [0.6.0] [Compare](https://github.com/clipperhouse/displaywidth/compare/v0.5.0...v0.6.0) diff --git a/vendor/github.com/clipperhouse/displaywidth/README.md b/vendor/github.com/clipperhouse/displaywidth/README.md index c423b99524..e9a513cae9 100644 --- a/vendor/github.com/clipperhouse/displaywidth/README.md +++ b/vendor/github.com/clipperhouse/displaywidth/README.md @@ -33,42 +33,82 @@ func main() { } ``` -For most purposes, you should use the `String` or `Bytes` methods. +For most purposes, you should use the `String` or `Bytes` methods. They sum +the widths of grapheme clusters in the string or byte slice. +> Note: in your application, iterating over runes to measure width is likely incorrect; +the smallest unit of display is a grapheme, not a rune. + +### Iterating over graphemes + +If you need the individual graphemes: + +```go +import ( + "fmt" + "github.com/clipperhouse/displaywidth" +) + +func main() { + g := displaywidth.StringGraphemes("Hello, 世界!") + for g.Next() { + width := g.Width() + value := g.Value() + // do something with the width or value + } +} +``` ### Options -You can specify East Asian Width settings. When false (default), -[East Asian Ambiguous characters](https://www.unicode.org/reports/tr11/#Ambiguous) -are treated as width 1. When true, East Asian Ambiguous characters are treated -as width 2. +There is one option, `displaywidth.Options.EastAsianWidth`, which defines +how [East Asian Ambiguous characters](https://www.unicode.org/reports/tr11/#Ambiguous) +are treated. + +When `false` (default), East Asian Ambiguous characters are treated as width 1. +When `true`, they are treated as width 2. + +You may wish to configure this based on environment variables or locale. + `go-runewidth`, for example, does so + [during package initialization](https://github.com/mattn/go-runewidth/blob/master/runewidth.go#L26C1-L45C2). + +`displaywidth` does not do this automatically, we prefer to leave it to you. +You might do something like: ```go -myOptions := displaywidth.Options{ - EastAsianWidth: true, +var width displaywidth.Options // zero value is default + +func init() { + if os.Getenv("EAST_ASIAN_WIDTH") == "true" { + width = displaywidth.Options{EastAsianWidth: true} + } + // or check locale, or any other logic you want } -width := myOptions.String("Hello, 世界!") -fmt.Println(width) +// use it in your logic +func myApp() { + fmt.Println(width.String("Hello, 世界!")) +} ``` -## Technical details +## Technical standards and compatibility This package implements the Unicode East Asian Width standard -([UAX #11](https://www.unicode.org/reports/tr11/)), and handles +([UAX #11](https://www.unicode.org/reports/tr11/tr11-43.html)), and handles [version selectors](https://en.wikipedia.org/wiki/Variation_Selectors_(Unicode_block)), and [regional indicator pairs](https://en.wikipedia.org/wiki/Regional_indicator_symbol) -(flags). We implement [Unicode TR51](https://unicode.org/reports/tr51/). +(flags). We implement [Unicode TR51](https://www.unicode.org/reports/tr51/tr51-27.html). We are keeping +an eye on [emerging standards](https://www.jeffquast.com/post/state-of-terminal-emulation-2025/). + `clipperhouse/displaywidth`, `mattn/go-runewidth`, and `rivo/uniseg` will -give the same outputs for most real-world text. See extensive details in the +give the same outputs for most real-world text. Extensive details are in the [compatibility analysis](comparison/COMPATIBILITY_ANALYSIS.md). If you wish to investigate the core logic, see the `lookupProperties` and `width` -functions in [width.go](width.go#L135). The essential trie generation logic is in -`buildPropertyBitmap` in [unicode.go](internal/gen/unicode.go#L317). +functions in [width.go](width.go#L139). The essential trie generation logic is in +`buildPropertyBitmap` in [unicode.go](internal/gen/unicode.go#L316). -I (@clipperhouse) am keeping an eye on [emerging standards and test suites](https://www.jeffquast.com/post/state-of-terminal-emulation-2025/). ## Prior Art @@ -93,31 +133,33 @@ goarch: arm64 pkg: github.com/clipperhouse/displaywidth/comparison cpu: Apple M2 -BenchmarkString_Mixed/clipperhouse/displaywidth-8 10469 ns/op 161.15 MB/s 0 B/op 0 allocs/op -BenchmarkString_Mixed/mattn/go-runewidth-8 14250 ns/op 118.39 MB/s 0 B/op 0 allocs/op -BenchmarkString_Mixed/rivo/uniseg-8 19258 ns/op 87.60 MB/s 0 B/op 0 allocs/op +BenchmarkString_Mixed/clipperhouse/displaywidth-8 10326 ns/op 163.37 MB/s 0 B/op 0 allocs/op +BenchmarkString_Mixed/mattn/go-runewidth-8 14415 ns/op 117.03 MB/s 0 B/op 0 allocs/op +BenchmarkString_Mixed/rivo/uniseg-8 19343 ns/op 87.21 MB/s 0 B/op 0 allocs/op -BenchmarkString_EastAsian/clipperhouse/displaywidth-8 10518 ns/op 160.39 MB/s 0 B/op 0 allocs/op -BenchmarkString_EastAsian/mattn/go-runewidth-8 23827 ns/op 70.80 MB/s 0 B/op 0 allocs/op -BenchmarkString_EastAsian/rivo/uniseg-8 19537 ns/op 86.35 MB/s 0 B/op 0 allocs/op +BenchmarkString_EastAsian/clipperhouse/displaywidth-8 10561 ns/op 159.74 MB/s 0 B/op 0 allocs/op +BenchmarkString_EastAsian/mattn/go-runewidth-8 23790 ns/op 70.91 MB/s 0 B/op 0 allocs/op +BenchmarkString_EastAsian/rivo/uniseg-8 19322 ns/op 87.31 MB/s 0 B/op 0 allocs/op -BenchmarkString_ASCII/clipperhouse/displaywidth-8 1027 ns/op 124.61 MB/s 0 B/op 0 allocs/op -BenchmarkString_ASCII/mattn/go-runewidth-8 1166 ns/op 109.78 MB/s 0 B/op 0 allocs/op -BenchmarkString_ASCII/rivo/uniseg-8 1551 ns/op 82.52 MB/s 0 B/op 0 allocs/op +BenchmarkString_ASCII/clipperhouse/displaywidth-8 1033 ns/op 123.88 MB/s 0 B/op 0 allocs/op +BenchmarkString_ASCII/mattn/go-runewidth-8 1168 ns/op 109.59 MB/s 0 B/op 0 allocs/op +BenchmarkString_ASCII/rivo/uniseg-8 1585 ns/op 80.74 MB/s 0 B/op 0 allocs/op -BenchmarkString_Emoji/clipperhouse/displaywidth-8 3164 ns/op 228.84 MB/s 0 B/op 0 allocs/op -BenchmarkString_Emoji/mattn/go-runewidth-8 4728 ns/op 153.13 MB/s 0 B/op 0 allocs/op -BenchmarkString_Emoji/rivo/uniseg-8 6489 ns/op 111.57 MB/s 0 B/op 0 allocs/op +BenchmarkString_Emoji/clipperhouse/displaywidth-8 3034 ns/op 238.61 MB/s 0 B/op 0 allocs/op +BenchmarkString_Emoji/mattn/go-runewidth-8 4797 ns/op 150.94 MB/s 0 B/op 0 allocs/op +BenchmarkString_Emoji/rivo/uniseg-8 6612 ns/op 109.50 MB/s 0 B/op 0 allocs/op -BenchmarkRune_Mixed/clipperhouse/displaywidth-8 3429 ns/op 491.96 MB/s 0 B/op 0 allocs/op -BenchmarkRune_Mixed/mattn/go-runewidth-8 5308 ns/op 317.81 MB/s 0 B/op 0 allocs/op +BenchmarkRune_Mixed/clipperhouse/displaywidth-8 3343 ns/op 504.67 MB/s 0 B/op 0 allocs/op +BenchmarkRune_Mixed/mattn/go-runewidth-8 5414 ns/op 311.62 MB/s 0 B/op 0 allocs/op -BenchmarkRune_EastAsian/clipperhouse/displaywidth-8 3419 ns/op 493.49 MB/s 0 B/op 0 allocs/op -BenchmarkRune_EastAsian/mattn/go-runewidth-8 15321 ns/op 110.11 MB/s 0 B/op 0 allocs/op +BenchmarkRune_EastAsian/clipperhouse/displaywidth-8 3393 ns/op 497.17 MB/s 0 B/op 0 allocs/op +BenchmarkRune_EastAsian/mattn/go-runewidth-8 15312 ns/op 110.17 MB/s 0 B/op 0 allocs/op -BenchmarkRune_ASCII/clipperhouse/displaywidth-8 254.4 ns/op 503.19 MB/s 0 B/op 0 allocs/op -BenchmarkRune_ASCII/mattn/go-runewidth-8 264.3 ns/op 484.31 MB/s 0 B/op 0 allocs/op +BenchmarkRune_ASCII/clipperhouse/displaywidth-8 256.9 ns/op 498.32 MB/s 0 B/op 0 allocs/op +BenchmarkRune_ASCII/mattn/go-runewidth-8 265.7 ns/op 481.75 MB/s 0 B/op 0 allocs/op -BenchmarkRune_Emoji/clipperhouse/displaywidth-8 1374 ns/op 527.02 MB/s 0 B/op 0 allocs/op -BenchmarkRune_Emoji/mattn/go-runewidth-8 2210 ns/op 327.66 MB/s 0 B/op 0 allocs/op +BenchmarkRune_Emoji/clipperhouse/displaywidth-8 1336 ns/op 541.96 MB/s 0 B/op 0 allocs/op +BenchmarkRune_Emoji/mattn/go-runewidth-8 2304 ns/op 314.23 MB/s 0 B/op 0 allocs/op ``` + +Here are some notes on [how to make Unicode things fast](https://clipperhouse.com/go-unicode/). diff --git a/vendor/github.com/clipperhouse/displaywidth/tables.go b/vendor/github.com/clipperhouse/displaywidth/tables.go deleted file mode 100644 index 40cf596680..0000000000 --- a/vendor/github.com/clipperhouse/displaywidth/tables.go +++ /dev/null @@ -1,91 +0,0 @@ -package displaywidth - -// propertyWidths is a jump table of sorts, instead of a switch -var propertyWidths = [5]int{ - _Default: 1, - _Zero_Width: 0, - _East_Asian_Wide: 2, - _East_Asian_Ambiguous: 1, - _Emoji: 2, -} - -// asciiWidths is a lookup table for single-byte character widths. Printable -// ASCII characters have width 1, control characters have width 0. -// -// It is intended for valid single-byte UTF-8, which means <128. -// -// If you look up an index >= 128, that is either: -// - invalid UTF-8, or -// - a multi-byte UTF-8 sequence, in which case you should be operating on -// the grapheme cluster, and not using this table -// -// We will return a default value of 1 in those cases, so as not to panic. -var asciiWidths = [256]int8{ - // Control characters (0x00-0x1F): width 0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - // Printable ASCII (0x20-0x7E): width 1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - // DEL (0x7F): width 0 - 0, - // >= 128 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -} - -// asciiProperties is a lookup table for single-byte character properties. -// It is intended for valid single-byte UTF-8, which means <128. -// -// If you look up an index >= 128, that is either: -// - invalid UTF-8, or -// - a multi-byte UTF-8 sequence, in which case you should be operating on -// the grapheme cluster, and not using this table -// -// We will return a default value of _Default in those cases, so as not to -// panic. -var asciiProperties = [256]property{ - // Control characters (0x00-0x1F): _Zero_Width - _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, - _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, - _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, - _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, _Zero_Width, - // Printable ASCII (0x20-0x7E): _Default - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, - // DEL (0x7F): _Zero_Width - _Zero_Width, - // >= 128 - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, - _Default, _Default, _Default, _Default, _Default, _Default, _Default, _Default, -} diff --git a/vendor/github.com/clipperhouse/displaywidth/trie.go b/vendor/github.com/clipperhouse/displaywidth/trie.go index e98c3695c4..b03f882811 100644 --- a/vendor/github.com/clipperhouse/displaywidth/trie.go +++ b/vendor/github.com/clipperhouse/displaywidth/trie.go @@ -10,12 +10,10 @@ type property uint8 const ( // Always 0 width, includes combining marks, control characters, non-printable, etc _Zero_Width property = iota + 1 - // Always 2 wide (East Asian Wide F/W) - _East_Asian_Wide + // Always 2 wide (East Asian Wide F/W, Emoji, Regional Indicator) + _Wide // Width depends on EastAsianWidth option _East_Asian_Ambiguous - // Extended_Pictographic + Emoji_Presentation - _Emoji ) // lookup returns the trie value for the first UTF-8 encoding in s and @@ -81,7 +79,7 @@ func lookup[T stringish.Interface](s T) (v uint8, sz int) { return 0, 1 } -// stringWidthTrie. Total size: 17728 bytes (17.31 KiB). Checksum: b4b51ae347944fdb. +// stringWidthTrie. Total size: 17664 bytes (17.25 KiB). Checksum: c77d82ff2d69f0d2. // type stringWidthTrie struct { } // func newStringWidthTrie(i int) *stringWidthTrie { @@ -96,9 +94,9 @@ func lookupValue(n uint32, b byte) uint8 { } } -// stringWidthValues: 247 blocks, 15808 entries, 15808 bytes +// stringWidthValues: 246 blocks, 15744 entries, 15744 bytes // The third block is the zero block. -var stringWidthValues = [15808]uint8{ +var stringWidthValues = [15744]uint8{ // Block 0x0, offset 0x0 // Block 0x1, offset 0x40 // Block 0x2, offset 0x80 @@ -577,13 +575,13 @@ var stringWidthValues = [15808]uint8{ 0x167f: 0x0003, // Block 0x5a, offset 0x1680 0x1692: 0x0003, - 0x169a: 0x0004, 0x169b: 0x0004, + 0x169a: 0x0002, 0x169b: 0x0002, 0x16a9: 0x0002, 0x16aa: 0x0002, // Block 0x5b, offset 0x16c0 - 0x16e9: 0x0004, - 0x16ea: 0x0004, 0x16eb: 0x0004, 0x16ec: 0x0004, - 0x16f0: 0x0004, 0x16f3: 0x0004, + 0x16e9: 0x0002, + 0x16ea: 0x0002, 0x16eb: 0x0002, 0x16ec: 0x0002, + 0x16f0: 0x0002, 0x16f3: 0x0002, // Block 0x5c, offset 0x1700 0x1720: 0x0003, 0x1721: 0x0003, 0x1722: 0x0003, 0x1723: 0x0003, 0x1724: 0x0003, 0x1725: 0x0003, 0x1726: 0x0003, 0x1727: 0x0003, 0x1728: 0x0003, 0x1729: 0x0003, @@ -642,63 +640,63 @@ var stringWidthValues = [15808]uint8{ 0x1862: 0x0003, 0x1863: 0x0003, 0x1864: 0x0003, 0x1865: 0x0003, 0x186f: 0x0003, - 0x187d: 0x0004, 0x187e: 0x0004, + 0x187d: 0x0002, 0x187e: 0x0002, // Block 0x62, offset 0x1880 0x1885: 0x0003, 0x1886: 0x0003, 0x1889: 0x0003, 0x188e: 0x0003, 0x188f: 0x0003, - 0x1894: 0x0004, 0x1895: 0x0004, + 0x1894: 0x0002, 0x1895: 0x0002, 0x189c: 0x0003, 0x189e: 0x0003, 0x18b0: 0x0002, 0x18b1: 0x0002, 0x18b2: 0x0002, 0x18b3: 0x0002, 0x18b4: 0x0002, 0x18b5: 0x0002, 0x18b6: 0x0002, 0x18b7: 0x0002, // Block 0x63, offset 0x18c0 0x18c0: 0x0003, 0x18c2: 0x0003, - 0x18c8: 0x0004, 0x18c9: 0x0004, 0x18ca: 0x0004, 0x18cb: 0x0004, - 0x18cc: 0x0004, 0x18cd: 0x0004, 0x18ce: 0x0004, 0x18cf: 0x0004, 0x18d0: 0x0004, 0x18d1: 0x0004, - 0x18d2: 0x0004, 0x18d3: 0x0004, + 0x18c8: 0x0002, 0x18c9: 0x0002, 0x18ca: 0x0002, 0x18cb: 0x0002, + 0x18cc: 0x0002, 0x18cd: 0x0002, 0x18ce: 0x0002, 0x18cf: 0x0002, 0x18d0: 0x0002, 0x18d1: 0x0002, + 0x18d2: 0x0002, 0x18d3: 0x0002, 0x18e0: 0x0003, 0x18e1: 0x0003, 0x18e3: 0x0003, 0x18e4: 0x0003, 0x18e5: 0x0003, 0x18e7: 0x0003, 0x18e8: 0x0003, 0x18e9: 0x0003, 0x18ea: 0x0003, 0x18ec: 0x0003, 0x18ed: 0x0003, 0x18ef: 0x0003, - 0x18ff: 0x0004, + 0x18ff: 0x0002, // Block 0x64, offset 0x1900 0x190a: 0x0002, 0x190b: 0x0002, 0x190c: 0x0002, 0x190d: 0x0002, 0x190e: 0x0002, 0x190f: 0x0002, - 0x1913: 0x0004, - 0x191e: 0x0003, 0x191f: 0x0003, 0x1921: 0x0004, - 0x192a: 0x0004, 0x192b: 0x0004, - 0x193d: 0x0004, 0x193e: 0x0004, 0x193f: 0x0003, + 0x1913: 0x0002, + 0x191e: 0x0003, 0x191f: 0x0003, 0x1921: 0x0002, + 0x192a: 0x0002, 0x192b: 0x0002, + 0x193d: 0x0002, 0x193e: 0x0002, 0x193f: 0x0003, // Block 0x65, offset 0x1940 - 0x1944: 0x0004, 0x1945: 0x0004, + 0x1944: 0x0002, 0x1945: 0x0002, 0x1946: 0x0003, 0x1947: 0x0003, 0x1948: 0x0003, 0x1949: 0x0003, 0x194a: 0x0003, 0x194b: 0x0003, - 0x194c: 0x0003, 0x194d: 0x0003, 0x194e: 0x0004, 0x194f: 0x0003, 0x1950: 0x0003, 0x1951: 0x0003, - 0x1952: 0x0003, 0x1953: 0x0003, 0x1954: 0x0004, 0x1955: 0x0003, 0x1956: 0x0003, 0x1957: 0x0003, + 0x194c: 0x0003, 0x194d: 0x0003, 0x194e: 0x0002, 0x194f: 0x0003, 0x1950: 0x0003, 0x1951: 0x0003, + 0x1952: 0x0003, 0x1953: 0x0003, 0x1954: 0x0002, 0x1955: 0x0003, 0x1956: 0x0003, 0x1957: 0x0003, 0x1958: 0x0003, 0x1959: 0x0003, 0x195a: 0x0003, 0x195b: 0x0003, 0x195c: 0x0003, 0x195d: 0x0003, 0x195e: 0x0003, 0x195f: 0x0003, 0x1960: 0x0003, 0x1961: 0x0003, 0x1963: 0x0003, 0x1968: 0x0003, 0x1969: 0x0003, - 0x196a: 0x0004, 0x196b: 0x0003, 0x196c: 0x0003, 0x196d: 0x0003, 0x196e: 0x0003, 0x196f: 0x0003, - 0x1970: 0x0003, 0x1971: 0x0003, 0x1972: 0x0004, 0x1973: 0x0004, 0x1974: 0x0003, 0x1975: 0x0004, - 0x1976: 0x0003, 0x1977: 0x0003, 0x1978: 0x0003, 0x1979: 0x0003, 0x197a: 0x0004, 0x197b: 0x0003, - 0x197c: 0x0003, 0x197d: 0x0004, 0x197e: 0x0003, 0x197f: 0x0003, + 0x196a: 0x0002, 0x196b: 0x0003, 0x196c: 0x0003, 0x196d: 0x0003, 0x196e: 0x0003, 0x196f: 0x0003, + 0x1970: 0x0003, 0x1971: 0x0003, 0x1972: 0x0002, 0x1973: 0x0002, 0x1974: 0x0003, 0x1975: 0x0002, + 0x1976: 0x0003, 0x1977: 0x0003, 0x1978: 0x0003, 0x1979: 0x0003, 0x197a: 0x0002, 0x197b: 0x0003, + 0x197c: 0x0003, 0x197d: 0x0002, 0x197e: 0x0003, 0x197f: 0x0003, // Block 0x66, offset 0x1980 - 0x1985: 0x0004, - 0x198a: 0x0004, 0x198b: 0x0004, - 0x19a8: 0x0004, + 0x1985: 0x0002, + 0x198a: 0x0002, 0x198b: 0x0002, + 0x19a8: 0x0002, 0x19bd: 0x0003, // Block 0x67, offset 0x19c0 - 0x19cc: 0x0004, 0x19ce: 0x0004, - 0x19d3: 0x0004, 0x19d4: 0x0004, 0x19d5: 0x0004, 0x19d7: 0x0004, + 0x19cc: 0x0002, 0x19ce: 0x0002, + 0x19d3: 0x0002, 0x19d4: 0x0002, 0x19d5: 0x0002, 0x19d7: 0x0002, 0x19f6: 0x0003, 0x19f7: 0x0003, 0x19f8: 0x0003, 0x19f9: 0x0003, 0x19fa: 0x0003, 0x19fb: 0x0003, 0x19fc: 0x0003, 0x19fd: 0x0003, 0x19fe: 0x0003, 0x19ff: 0x0003, // Block 0x68, offset 0x1a00 - 0x1a15: 0x0004, 0x1a16: 0x0004, 0x1a17: 0x0004, - 0x1a30: 0x0004, - 0x1a3f: 0x0004, + 0x1a15: 0x0002, 0x1a16: 0x0002, 0x1a17: 0x0002, + 0x1a30: 0x0002, + 0x1a3f: 0x0002, // Block 0x69, offset 0x1a40 - 0x1a5b: 0x0004, 0x1a5c: 0x0004, + 0x1a5b: 0x0002, 0x1a5c: 0x0002, // Block 0x6a, offset 0x1a80 - 0x1a90: 0x0004, - 0x1a95: 0x0004, 0x1a96: 0x0003, 0x1a97: 0x0003, + 0x1a90: 0x0002, + 0x1a95: 0x0002, 0x1a96: 0x0003, 0x1a97: 0x0003, 0x1a98: 0x0003, 0x1a99: 0x0003, // Block 0x6b, offset 0x1ac0 0x1aef: 0x0001, @@ -1273,9 +1271,9 @@ var stringWidthValues = [15808]uint8{ 0x3604: 0x0001, 0x3605: 0x0001, 0x3606: 0x0001, 0x3607: 0x0001, 0x3608: 0x0001, 0x3609: 0x0001, 0x360a: 0x0001, // Block 0xd9, offset 0x3640 - 0x3644: 0x0004, + 0x3644: 0x0002, // Block 0xda, offset 0x3680 - 0x368f: 0x0004, + 0x368f: 0x0002, // Block 0xdb, offset 0x36c0 0x36c0: 0x0003, 0x36c1: 0x0003, 0x36c2: 0x0003, 0x36c3: 0x0003, 0x36c4: 0x0003, 0x36c5: 0x0003, 0x36c6: 0x0003, 0x36c7: 0x0003, 0x36c8: 0x0003, 0x36c9: 0x0003, 0x36ca: 0x0003, @@ -1302,246 +1300,228 @@ var stringWidthValues = [15808]uint8{ // Block 0xdd, offset 0x3740 0x3740: 0x0003, 0x3741: 0x0003, 0x3742: 0x0003, 0x3743: 0x0003, 0x3744: 0x0003, 0x3745: 0x0003, 0x3746: 0x0003, 0x3747: 0x0003, 0x3748: 0x0003, 0x3749: 0x0003, 0x374a: 0x0003, 0x374b: 0x0003, - 0x374c: 0x0003, 0x374d: 0x0003, 0x374e: 0x0004, 0x374f: 0x0003, 0x3750: 0x0003, 0x3751: 0x0004, - 0x3752: 0x0004, 0x3753: 0x0004, 0x3754: 0x0004, 0x3755: 0x0004, 0x3756: 0x0004, 0x3757: 0x0004, - 0x3758: 0x0004, 0x3759: 0x0004, 0x375a: 0x0004, 0x375b: 0x0003, 0x375c: 0x0003, 0x375d: 0x0003, + 0x374c: 0x0003, 0x374d: 0x0003, 0x374e: 0x0002, 0x374f: 0x0003, 0x3750: 0x0003, 0x3751: 0x0002, + 0x3752: 0x0002, 0x3753: 0x0002, 0x3754: 0x0002, 0x3755: 0x0002, 0x3756: 0x0002, 0x3757: 0x0002, + 0x3758: 0x0002, 0x3759: 0x0002, 0x375a: 0x0002, 0x375b: 0x0003, 0x375c: 0x0003, 0x375d: 0x0003, 0x375e: 0x0003, 0x375f: 0x0003, 0x3760: 0x0003, 0x3761: 0x0003, 0x3762: 0x0003, 0x3763: 0x0003, 0x3764: 0x0003, 0x3765: 0x0003, 0x3766: 0x0003, 0x3767: 0x0003, 0x3768: 0x0003, 0x3769: 0x0003, 0x376a: 0x0003, 0x376b: 0x0003, 0x376c: 0x0003, // Block 0xde, offset 0x3780 - 0x3780: 0x0002, 0x3781: 0x0004, 0x3782: 0x0002, - 0x3790: 0x0002, 0x3791: 0x0002, - 0x3792: 0x0002, 0x3793: 0x0002, 0x3794: 0x0002, 0x3795: 0x0002, 0x3796: 0x0002, 0x3797: 0x0002, - 0x3798: 0x0002, 0x3799: 0x0002, 0x379a: 0x0004, 0x379b: 0x0002, 0x379c: 0x0002, 0x379d: 0x0002, - 0x379e: 0x0002, 0x379f: 0x0002, 0x37a0: 0x0002, 0x37a1: 0x0002, 0x37a2: 0x0002, 0x37a3: 0x0002, - 0x37a4: 0x0002, 0x37a5: 0x0002, 0x37a6: 0x0002, 0x37a7: 0x0002, 0x37a8: 0x0002, 0x37a9: 0x0002, - 0x37aa: 0x0002, 0x37ab: 0x0002, 0x37ac: 0x0002, 0x37ad: 0x0002, 0x37ae: 0x0002, 0x37af: 0x0004, - 0x37b0: 0x0002, 0x37b1: 0x0002, 0x37b2: 0x0004, 0x37b3: 0x0004, 0x37b4: 0x0004, 0x37b5: 0x0004, - 0x37b6: 0x0004, 0x37b7: 0x0002, 0x37b8: 0x0004, 0x37b9: 0x0004, 0x37ba: 0x0004, 0x37bb: 0x0002, + 0x37a6: 0x0002, 0x37a7: 0x0002, 0x37a8: 0x0002, 0x37a9: 0x0002, + 0x37aa: 0x0002, 0x37ab: 0x0002, 0x37ac: 0x0002, 0x37ad: 0x0002, 0x37ae: 0x0002, 0x37af: 0x0002, + 0x37b0: 0x0002, 0x37b1: 0x0002, 0x37b2: 0x0002, 0x37b3: 0x0002, 0x37b4: 0x0002, 0x37b5: 0x0002, + 0x37b6: 0x0002, 0x37b7: 0x0002, 0x37b8: 0x0002, 0x37b9: 0x0002, 0x37ba: 0x0002, 0x37bb: 0x0002, + 0x37bc: 0x0002, 0x37bd: 0x0002, 0x37be: 0x0002, 0x37bf: 0x0002, // Block 0xdf, offset 0x37c0 - 0x37c0: 0x0002, 0x37c1: 0x0002, 0x37c2: 0x0002, 0x37c3: 0x0002, 0x37c4: 0x0002, 0x37c5: 0x0002, - 0x37c6: 0x0002, 0x37c7: 0x0002, 0x37c8: 0x0002, - 0x37d0: 0x0004, 0x37d1: 0x0004, - 0x37e0: 0x0002, 0x37e1: 0x0002, 0x37e2: 0x0002, 0x37e3: 0x0002, - 0x37e4: 0x0002, 0x37e5: 0x0002, + 0x37c0: 0x0002, 0x37c1: 0x0002, 0x37c2: 0x0002, + 0x37d0: 0x0002, 0x37d1: 0x0002, + 0x37d2: 0x0002, 0x37d3: 0x0002, 0x37d4: 0x0002, 0x37d5: 0x0002, 0x37d6: 0x0002, 0x37d7: 0x0002, + 0x37d8: 0x0002, 0x37d9: 0x0002, 0x37da: 0x0002, 0x37db: 0x0002, 0x37dc: 0x0002, 0x37dd: 0x0002, + 0x37de: 0x0002, 0x37df: 0x0002, 0x37e0: 0x0002, 0x37e1: 0x0002, 0x37e2: 0x0002, 0x37e3: 0x0002, + 0x37e4: 0x0002, 0x37e5: 0x0002, 0x37e6: 0x0002, 0x37e7: 0x0002, 0x37e8: 0x0002, 0x37e9: 0x0002, + 0x37ea: 0x0002, 0x37eb: 0x0002, 0x37ec: 0x0002, 0x37ed: 0x0002, 0x37ee: 0x0002, 0x37ef: 0x0002, + 0x37f0: 0x0002, 0x37f1: 0x0002, 0x37f2: 0x0002, 0x37f3: 0x0002, 0x37f4: 0x0002, 0x37f5: 0x0002, + 0x37f6: 0x0002, 0x37f7: 0x0002, 0x37f8: 0x0002, 0x37f9: 0x0002, 0x37fa: 0x0002, 0x37fb: 0x0002, // Block 0xe0, offset 0x3800 - 0x3800: 0x0004, 0x3801: 0x0004, 0x3802: 0x0004, 0x3803: 0x0004, 0x3804: 0x0004, 0x3805: 0x0004, - 0x3806: 0x0004, 0x3807: 0x0004, 0x3808: 0x0004, 0x3809: 0x0004, 0x380a: 0x0004, 0x380b: 0x0004, - 0x380c: 0x0004, 0x380d: 0x0004, 0x380e: 0x0004, 0x380f: 0x0004, 0x3810: 0x0004, 0x3811: 0x0004, - 0x3812: 0x0004, 0x3813: 0x0004, 0x3814: 0x0004, 0x3815: 0x0004, 0x3816: 0x0004, 0x3817: 0x0004, - 0x3818: 0x0004, 0x3819: 0x0004, 0x381a: 0x0004, 0x381b: 0x0004, 0x381c: 0x0004, 0x381d: 0x0004, - 0x381e: 0x0004, 0x381f: 0x0004, 0x3820: 0x0004, - 0x382d: 0x0004, 0x382e: 0x0004, 0x382f: 0x0004, - 0x3830: 0x0004, 0x3831: 0x0004, 0x3832: 0x0004, 0x3833: 0x0004, 0x3834: 0x0004, 0x3835: 0x0004, - 0x3837: 0x0004, 0x3838: 0x0004, 0x3839: 0x0004, 0x383a: 0x0004, 0x383b: 0x0004, - 0x383c: 0x0004, 0x383d: 0x0004, 0x383e: 0x0004, 0x383f: 0x0004, + 0x3800: 0x0002, 0x3801: 0x0002, 0x3802: 0x0002, 0x3803: 0x0002, 0x3804: 0x0002, 0x3805: 0x0002, + 0x3806: 0x0002, 0x3807: 0x0002, 0x3808: 0x0002, + 0x3810: 0x0002, 0x3811: 0x0002, + 0x3820: 0x0002, 0x3821: 0x0002, 0x3822: 0x0002, 0x3823: 0x0002, + 0x3824: 0x0002, 0x3825: 0x0002, // Block 0xe1, offset 0x3840 - 0x3840: 0x0004, 0x3841: 0x0004, 0x3842: 0x0004, 0x3843: 0x0004, 0x3844: 0x0004, 0x3845: 0x0004, - 0x3846: 0x0004, 0x3847: 0x0004, 0x3848: 0x0004, 0x3849: 0x0004, 0x384a: 0x0004, 0x384b: 0x0004, - 0x384c: 0x0004, 0x384d: 0x0004, 0x384e: 0x0004, 0x384f: 0x0004, 0x3850: 0x0004, 0x3851: 0x0004, - 0x3852: 0x0004, 0x3853: 0x0004, 0x3854: 0x0004, 0x3855: 0x0004, 0x3856: 0x0004, 0x3857: 0x0004, - 0x3858: 0x0004, 0x3859: 0x0004, 0x385a: 0x0004, 0x385b: 0x0004, 0x385c: 0x0004, 0x385d: 0x0004, - 0x385e: 0x0004, 0x385f: 0x0004, 0x3860: 0x0004, 0x3861: 0x0004, 0x3862: 0x0004, 0x3863: 0x0004, - 0x3864: 0x0004, 0x3865: 0x0004, 0x3866: 0x0004, 0x3867: 0x0004, 0x3868: 0x0004, 0x3869: 0x0004, - 0x386a: 0x0004, 0x386b: 0x0004, 0x386c: 0x0004, 0x386d: 0x0004, 0x386e: 0x0004, 0x386f: 0x0004, - 0x3870: 0x0004, 0x3871: 0x0004, 0x3872: 0x0004, 0x3873: 0x0004, 0x3874: 0x0004, 0x3875: 0x0004, - 0x3876: 0x0004, 0x3877: 0x0004, 0x3878: 0x0004, 0x3879: 0x0004, 0x387a: 0x0004, 0x387b: 0x0004, - 0x387c: 0x0004, 0x387e: 0x0004, 0x387f: 0x0004, + 0x3840: 0x0002, 0x3841: 0x0002, 0x3842: 0x0002, 0x3843: 0x0002, 0x3844: 0x0002, 0x3845: 0x0002, + 0x3846: 0x0002, 0x3847: 0x0002, 0x3848: 0x0002, 0x3849: 0x0002, 0x384a: 0x0002, 0x384b: 0x0002, + 0x384c: 0x0002, 0x384d: 0x0002, 0x384e: 0x0002, 0x384f: 0x0002, 0x3850: 0x0002, 0x3851: 0x0002, + 0x3852: 0x0002, 0x3853: 0x0002, 0x3854: 0x0002, 0x3855: 0x0002, 0x3856: 0x0002, 0x3857: 0x0002, + 0x3858: 0x0002, 0x3859: 0x0002, 0x385a: 0x0002, 0x385b: 0x0002, 0x385c: 0x0002, 0x385d: 0x0002, + 0x385e: 0x0002, 0x385f: 0x0002, 0x3860: 0x0002, + 0x386d: 0x0002, 0x386e: 0x0002, 0x386f: 0x0002, + 0x3870: 0x0002, 0x3871: 0x0002, 0x3872: 0x0002, 0x3873: 0x0002, 0x3874: 0x0002, 0x3875: 0x0002, + 0x3877: 0x0002, 0x3878: 0x0002, 0x3879: 0x0002, 0x387a: 0x0002, 0x387b: 0x0002, + 0x387c: 0x0002, 0x387d: 0x0002, 0x387e: 0x0002, 0x387f: 0x0002, // Block 0xe2, offset 0x3880 - 0x3880: 0x0004, 0x3881: 0x0004, 0x3882: 0x0004, 0x3883: 0x0004, 0x3884: 0x0004, 0x3885: 0x0004, - 0x3886: 0x0004, 0x3887: 0x0004, 0x3888: 0x0004, 0x3889: 0x0004, 0x388a: 0x0004, 0x388b: 0x0004, - 0x388c: 0x0004, 0x388d: 0x0004, 0x388e: 0x0004, 0x388f: 0x0004, 0x3890: 0x0004, 0x3891: 0x0004, - 0x3892: 0x0004, 0x3893: 0x0004, - 0x38a0: 0x0004, 0x38a1: 0x0004, 0x38a2: 0x0004, 0x38a3: 0x0004, - 0x38a4: 0x0004, 0x38a5: 0x0004, 0x38a6: 0x0004, 0x38a7: 0x0004, 0x38a8: 0x0004, 0x38a9: 0x0004, - 0x38aa: 0x0004, 0x38ab: 0x0004, 0x38ac: 0x0004, 0x38ad: 0x0004, 0x38ae: 0x0004, 0x38af: 0x0004, - 0x38b0: 0x0004, 0x38b1: 0x0004, 0x38b2: 0x0004, 0x38b3: 0x0004, 0x38b4: 0x0004, 0x38b5: 0x0004, - 0x38b6: 0x0004, 0x38b7: 0x0004, 0x38b8: 0x0004, 0x38b9: 0x0004, 0x38ba: 0x0004, 0x38bb: 0x0004, - 0x38bc: 0x0004, 0x38bd: 0x0004, 0x38be: 0x0004, 0x38bf: 0x0004, + 0x3880: 0x0002, 0x3881: 0x0002, 0x3882: 0x0002, 0x3883: 0x0002, 0x3884: 0x0002, 0x3885: 0x0002, + 0x3886: 0x0002, 0x3887: 0x0002, 0x3888: 0x0002, 0x3889: 0x0002, 0x388a: 0x0002, 0x388b: 0x0002, + 0x388c: 0x0002, 0x388d: 0x0002, 0x388e: 0x0002, 0x388f: 0x0002, 0x3890: 0x0002, 0x3891: 0x0002, + 0x3892: 0x0002, 0x3893: 0x0002, 0x3894: 0x0002, 0x3895: 0x0002, 0x3896: 0x0002, 0x3897: 0x0002, + 0x3898: 0x0002, 0x3899: 0x0002, 0x389a: 0x0002, 0x389b: 0x0002, 0x389c: 0x0002, 0x389d: 0x0002, + 0x389e: 0x0002, 0x389f: 0x0002, 0x38a0: 0x0002, 0x38a1: 0x0002, 0x38a2: 0x0002, 0x38a3: 0x0002, + 0x38a4: 0x0002, 0x38a5: 0x0002, 0x38a6: 0x0002, 0x38a7: 0x0002, 0x38a8: 0x0002, 0x38a9: 0x0002, + 0x38aa: 0x0002, 0x38ab: 0x0002, 0x38ac: 0x0002, 0x38ad: 0x0002, 0x38ae: 0x0002, 0x38af: 0x0002, + 0x38b0: 0x0002, 0x38b1: 0x0002, 0x38b2: 0x0002, 0x38b3: 0x0002, 0x38b4: 0x0002, 0x38b5: 0x0002, + 0x38b6: 0x0002, 0x38b7: 0x0002, 0x38b8: 0x0002, 0x38b9: 0x0002, 0x38ba: 0x0002, 0x38bb: 0x0002, + 0x38bc: 0x0002, 0x38be: 0x0002, 0x38bf: 0x0002, // Block 0xe3, offset 0x38c0 - 0x38c0: 0x0004, 0x38c1: 0x0004, 0x38c2: 0x0004, 0x38c3: 0x0004, 0x38c4: 0x0004, 0x38c5: 0x0004, - 0x38c6: 0x0004, 0x38c7: 0x0004, 0x38c8: 0x0004, 0x38c9: 0x0004, 0x38ca: 0x0004, - 0x38cf: 0x0004, 0x38d0: 0x0004, 0x38d1: 0x0004, - 0x38d2: 0x0004, 0x38d3: 0x0004, - 0x38e0: 0x0004, 0x38e1: 0x0004, 0x38e2: 0x0004, 0x38e3: 0x0004, - 0x38e4: 0x0004, 0x38e5: 0x0004, 0x38e6: 0x0004, 0x38e7: 0x0004, 0x38e8: 0x0004, 0x38e9: 0x0004, - 0x38ea: 0x0004, 0x38eb: 0x0004, 0x38ec: 0x0004, 0x38ed: 0x0004, 0x38ee: 0x0004, 0x38ef: 0x0004, - 0x38f0: 0x0004, 0x38f4: 0x0004, - 0x38f8: 0x0004, 0x38f9: 0x0004, 0x38fa: 0x0004, 0x38fb: 0x0002, + 0x38c0: 0x0002, 0x38c1: 0x0002, 0x38c2: 0x0002, 0x38c3: 0x0002, 0x38c4: 0x0002, 0x38c5: 0x0002, + 0x38c6: 0x0002, 0x38c7: 0x0002, 0x38c8: 0x0002, 0x38c9: 0x0002, 0x38ca: 0x0002, 0x38cb: 0x0002, + 0x38cc: 0x0002, 0x38cd: 0x0002, 0x38ce: 0x0002, 0x38cf: 0x0002, 0x38d0: 0x0002, 0x38d1: 0x0002, + 0x38d2: 0x0002, 0x38d3: 0x0002, + 0x38e0: 0x0002, 0x38e1: 0x0002, 0x38e2: 0x0002, 0x38e3: 0x0002, + 0x38e4: 0x0002, 0x38e5: 0x0002, 0x38e6: 0x0002, 0x38e7: 0x0002, 0x38e8: 0x0002, 0x38e9: 0x0002, + 0x38ea: 0x0002, 0x38eb: 0x0002, 0x38ec: 0x0002, 0x38ed: 0x0002, 0x38ee: 0x0002, 0x38ef: 0x0002, + 0x38f0: 0x0002, 0x38f1: 0x0002, 0x38f2: 0x0002, 0x38f3: 0x0002, 0x38f4: 0x0002, 0x38f5: 0x0002, + 0x38f6: 0x0002, 0x38f7: 0x0002, 0x38f8: 0x0002, 0x38f9: 0x0002, 0x38fa: 0x0002, 0x38fb: 0x0002, 0x38fc: 0x0002, 0x38fd: 0x0002, 0x38fe: 0x0002, 0x38ff: 0x0002, // Block 0xe4, offset 0x3900 - 0x3900: 0x0004, 0x3901: 0x0004, 0x3902: 0x0004, 0x3903: 0x0004, 0x3904: 0x0004, 0x3905: 0x0004, - 0x3906: 0x0004, 0x3907: 0x0004, 0x3908: 0x0004, 0x3909: 0x0004, 0x390a: 0x0004, 0x390b: 0x0004, - 0x390c: 0x0004, 0x390d: 0x0004, 0x390e: 0x0004, 0x390f: 0x0004, 0x3910: 0x0004, 0x3911: 0x0004, - 0x3912: 0x0004, 0x3913: 0x0004, 0x3914: 0x0004, 0x3915: 0x0004, 0x3916: 0x0004, 0x3917: 0x0004, - 0x3918: 0x0004, 0x3919: 0x0004, 0x391a: 0x0004, 0x391b: 0x0004, 0x391c: 0x0004, 0x391d: 0x0004, - 0x391e: 0x0004, 0x391f: 0x0004, 0x3920: 0x0004, 0x3921: 0x0004, 0x3922: 0x0004, 0x3923: 0x0004, - 0x3924: 0x0004, 0x3925: 0x0004, 0x3926: 0x0004, 0x3927: 0x0004, 0x3928: 0x0004, 0x3929: 0x0004, - 0x392a: 0x0004, 0x392b: 0x0004, 0x392c: 0x0004, 0x392d: 0x0004, 0x392e: 0x0004, 0x392f: 0x0004, - 0x3930: 0x0004, 0x3931: 0x0004, 0x3932: 0x0004, 0x3933: 0x0004, 0x3934: 0x0004, 0x3935: 0x0004, - 0x3936: 0x0004, 0x3937: 0x0004, 0x3938: 0x0004, 0x3939: 0x0004, 0x393a: 0x0004, 0x393b: 0x0004, - 0x393c: 0x0004, 0x393d: 0x0004, 0x393e: 0x0004, + 0x3900: 0x0002, 0x3901: 0x0002, 0x3902: 0x0002, 0x3903: 0x0002, 0x3904: 0x0002, 0x3905: 0x0002, + 0x3906: 0x0002, 0x3907: 0x0002, 0x3908: 0x0002, 0x3909: 0x0002, 0x390a: 0x0002, + 0x390f: 0x0002, 0x3910: 0x0002, 0x3911: 0x0002, + 0x3912: 0x0002, 0x3913: 0x0002, + 0x3920: 0x0002, 0x3921: 0x0002, 0x3922: 0x0002, 0x3923: 0x0002, + 0x3924: 0x0002, 0x3925: 0x0002, 0x3926: 0x0002, 0x3927: 0x0002, 0x3928: 0x0002, 0x3929: 0x0002, + 0x392a: 0x0002, 0x392b: 0x0002, 0x392c: 0x0002, 0x392d: 0x0002, 0x392e: 0x0002, 0x392f: 0x0002, + 0x3930: 0x0002, 0x3934: 0x0002, + 0x3938: 0x0002, 0x3939: 0x0002, 0x393a: 0x0002, 0x393b: 0x0002, + 0x393c: 0x0002, 0x393d: 0x0002, 0x393e: 0x0002, 0x393f: 0x0002, // Block 0xe5, offset 0x3940 - 0x3940: 0x0004, 0x3942: 0x0004, 0x3943: 0x0004, 0x3944: 0x0004, 0x3945: 0x0004, - 0x3946: 0x0004, 0x3947: 0x0004, 0x3948: 0x0004, 0x3949: 0x0004, 0x394a: 0x0004, 0x394b: 0x0004, - 0x394c: 0x0004, 0x394d: 0x0004, 0x394e: 0x0004, 0x394f: 0x0004, 0x3950: 0x0004, 0x3951: 0x0004, - 0x3952: 0x0004, 0x3953: 0x0004, 0x3954: 0x0004, 0x3955: 0x0004, 0x3956: 0x0004, 0x3957: 0x0004, - 0x3958: 0x0004, 0x3959: 0x0004, 0x395a: 0x0004, 0x395b: 0x0004, 0x395c: 0x0004, 0x395d: 0x0004, - 0x395e: 0x0004, 0x395f: 0x0004, 0x3960: 0x0004, 0x3961: 0x0004, 0x3962: 0x0004, 0x3963: 0x0004, - 0x3964: 0x0004, 0x3965: 0x0004, 0x3966: 0x0004, 0x3967: 0x0004, 0x3968: 0x0004, 0x3969: 0x0004, - 0x396a: 0x0004, 0x396b: 0x0004, 0x396c: 0x0004, 0x396d: 0x0004, 0x396e: 0x0004, 0x396f: 0x0004, - 0x3970: 0x0004, 0x3971: 0x0004, 0x3972: 0x0004, 0x3973: 0x0004, 0x3974: 0x0004, 0x3975: 0x0004, - 0x3976: 0x0004, 0x3977: 0x0004, 0x3978: 0x0004, 0x3979: 0x0004, 0x397a: 0x0004, 0x397b: 0x0004, - 0x397c: 0x0004, 0x397d: 0x0004, 0x397e: 0x0004, 0x397f: 0x0004, + 0x3940: 0x0002, 0x3941: 0x0002, 0x3942: 0x0002, 0x3943: 0x0002, 0x3944: 0x0002, 0x3945: 0x0002, + 0x3946: 0x0002, 0x3947: 0x0002, 0x3948: 0x0002, 0x3949: 0x0002, 0x394a: 0x0002, 0x394b: 0x0002, + 0x394c: 0x0002, 0x394d: 0x0002, 0x394e: 0x0002, 0x394f: 0x0002, 0x3950: 0x0002, 0x3951: 0x0002, + 0x3952: 0x0002, 0x3953: 0x0002, 0x3954: 0x0002, 0x3955: 0x0002, 0x3956: 0x0002, 0x3957: 0x0002, + 0x3958: 0x0002, 0x3959: 0x0002, 0x395a: 0x0002, 0x395b: 0x0002, 0x395c: 0x0002, 0x395d: 0x0002, + 0x395e: 0x0002, 0x395f: 0x0002, 0x3960: 0x0002, 0x3961: 0x0002, 0x3962: 0x0002, 0x3963: 0x0002, + 0x3964: 0x0002, 0x3965: 0x0002, 0x3966: 0x0002, 0x3967: 0x0002, 0x3968: 0x0002, 0x3969: 0x0002, + 0x396a: 0x0002, 0x396b: 0x0002, 0x396c: 0x0002, 0x396d: 0x0002, 0x396e: 0x0002, 0x396f: 0x0002, + 0x3970: 0x0002, 0x3971: 0x0002, 0x3972: 0x0002, 0x3973: 0x0002, 0x3974: 0x0002, 0x3975: 0x0002, + 0x3976: 0x0002, 0x3977: 0x0002, 0x3978: 0x0002, 0x3979: 0x0002, 0x397a: 0x0002, 0x397b: 0x0002, + 0x397c: 0x0002, 0x397d: 0x0002, 0x397e: 0x0002, // Block 0xe6, offset 0x3980 - 0x3980: 0x0004, 0x3981: 0x0004, 0x3982: 0x0004, 0x3983: 0x0004, 0x3984: 0x0004, 0x3985: 0x0004, - 0x3986: 0x0004, 0x3987: 0x0004, 0x3988: 0x0004, 0x3989: 0x0004, 0x398a: 0x0004, 0x398b: 0x0004, - 0x398c: 0x0004, 0x398d: 0x0004, 0x398e: 0x0004, 0x398f: 0x0004, 0x3990: 0x0004, 0x3991: 0x0004, - 0x3992: 0x0004, 0x3993: 0x0004, 0x3994: 0x0004, 0x3995: 0x0004, 0x3996: 0x0004, 0x3997: 0x0004, - 0x3998: 0x0004, 0x3999: 0x0004, 0x399a: 0x0004, 0x399b: 0x0004, 0x399c: 0x0004, 0x399d: 0x0004, - 0x399e: 0x0004, 0x399f: 0x0004, 0x39a0: 0x0004, 0x39a1: 0x0004, 0x39a2: 0x0004, 0x39a3: 0x0004, - 0x39a4: 0x0004, 0x39a5: 0x0004, 0x39a6: 0x0004, 0x39a7: 0x0004, 0x39a8: 0x0004, 0x39a9: 0x0004, - 0x39aa: 0x0004, 0x39ab: 0x0004, 0x39ac: 0x0004, 0x39ad: 0x0004, 0x39ae: 0x0004, 0x39af: 0x0004, - 0x39b0: 0x0004, 0x39b1: 0x0004, 0x39b2: 0x0004, 0x39b3: 0x0004, 0x39b4: 0x0004, 0x39b5: 0x0004, - 0x39b6: 0x0004, 0x39b7: 0x0004, 0x39b8: 0x0004, 0x39b9: 0x0004, 0x39ba: 0x0004, 0x39bb: 0x0004, - 0x39bc: 0x0004, 0x39bd: 0x0004, 0x39be: 0x0004, 0x39bf: 0x0004, + 0x3980: 0x0002, 0x3982: 0x0002, 0x3983: 0x0002, 0x3984: 0x0002, 0x3985: 0x0002, + 0x3986: 0x0002, 0x3987: 0x0002, 0x3988: 0x0002, 0x3989: 0x0002, 0x398a: 0x0002, 0x398b: 0x0002, + 0x398c: 0x0002, 0x398d: 0x0002, 0x398e: 0x0002, 0x398f: 0x0002, 0x3990: 0x0002, 0x3991: 0x0002, + 0x3992: 0x0002, 0x3993: 0x0002, 0x3994: 0x0002, 0x3995: 0x0002, 0x3996: 0x0002, 0x3997: 0x0002, + 0x3998: 0x0002, 0x3999: 0x0002, 0x399a: 0x0002, 0x399b: 0x0002, 0x399c: 0x0002, 0x399d: 0x0002, + 0x399e: 0x0002, 0x399f: 0x0002, 0x39a0: 0x0002, 0x39a1: 0x0002, 0x39a2: 0x0002, 0x39a3: 0x0002, + 0x39a4: 0x0002, 0x39a5: 0x0002, 0x39a6: 0x0002, 0x39a7: 0x0002, 0x39a8: 0x0002, 0x39a9: 0x0002, + 0x39aa: 0x0002, 0x39ab: 0x0002, 0x39ac: 0x0002, 0x39ad: 0x0002, 0x39ae: 0x0002, 0x39af: 0x0002, + 0x39b0: 0x0002, 0x39b1: 0x0002, 0x39b2: 0x0002, 0x39b3: 0x0002, 0x39b4: 0x0002, 0x39b5: 0x0002, + 0x39b6: 0x0002, 0x39b7: 0x0002, 0x39b8: 0x0002, 0x39b9: 0x0002, 0x39ba: 0x0002, 0x39bb: 0x0002, + 0x39bc: 0x0002, 0x39bd: 0x0002, 0x39be: 0x0002, 0x39bf: 0x0002, // Block 0xe7, offset 0x39c0 - 0x39c0: 0x0004, 0x39c1: 0x0004, 0x39c2: 0x0004, 0x39c3: 0x0004, 0x39c4: 0x0004, 0x39c5: 0x0004, - 0x39c6: 0x0004, 0x39c7: 0x0004, 0x39c8: 0x0004, 0x39c9: 0x0004, 0x39ca: 0x0004, 0x39cb: 0x0004, - 0x39cc: 0x0004, 0x39cd: 0x0004, 0x39ce: 0x0004, 0x39cf: 0x0004, 0x39d0: 0x0004, 0x39d1: 0x0004, - 0x39d2: 0x0004, 0x39d3: 0x0004, 0x39d4: 0x0004, 0x39d5: 0x0004, 0x39d6: 0x0004, 0x39d7: 0x0004, - 0x39d8: 0x0004, 0x39d9: 0x0004, 0x39da: 0x0004, 0x39db: 0x0004, 0x39dc: 0x0004, 0x39dd: 0x0004, - 0x39de: 0x0004, 0x39df: 0x0004, 0x39e0: 0x0004, 0x39e1: 0x0004, 0x39e2: 0x0004, 0x39e3: 0x0004, - 0x39e4: 0x0004, 0x39e5: 0x0004, 0x39e6: 0x0004, 0x39e7: 0x0004, 0x39e8: 0x0004, 0x39e9: 0x0004, - 0x39ea: 0x0004, 0x39eb: 0x0004, 0x39ec: 0x0004, 0x39ed: 0x0004, 0x39ee: 0x0004, 0x39ef: 0x0004, - 0x39f0: 0x0004, 0x39f1: 0x0004, 0x39f2: 0x0004, 0x39f3: 0x0004, 0x39f4: 0x0004, 0x39f5: 0x0004, - 0x39f6: 0x0004, 0x39f7: 0x0004, 0x39f8: 0x0004, 0x39f9: 0x0004, 0x39fa: 0x0004, 0x39fb: 0x0004, - 0x39fc: 0x0004, 0x39ff: 0x0004, + 0x39c0: 0x0002, 0x39c1: 0x0002, 0x39c2: 0x0002, 0x39c3: 0x0002, 0x39c4: 0x0002, 0x39c5: 0x0002, + 0x39c6: 0x0002, 0x39c7: 0x0002, 0x39c8: 0x0002, 0x39c9: 0x0002, 0x39ca: 0x0002, 0x39cb: 0x0002, + 0x39cc: 0x0002, 0x39cd: 0x0002, 0x39ce: 0x0002, 0x39cf: 0x0002, 0x39d0: 0x0002, 0x39d1: 0x0002, + 0x39d2: 0x0002, 0x39d3: 0x0002, 0x39d4: 0x0002, 0x39d5: 0x0002, 0x39d6: 0x0002, 0x39d7: 0x0002, + 0x39d8: 0x0002, 0x39d9: 0x0002, 0x39da: 0x0002, 0x39db: 0x0002, 0x39dc: 0x0002, 0x39dd: 0x0002, + 0x39de: 0x0002, 0x39df: 0x0002, 0x39e0: 0x0002, 0x39e1: 0x0002, 0x39e2: 0x0002, 0x39e3: 0x0002, + 0x39e4: 0x0002, 0x39e5: 0x0002, 0x39e6: 0x0002, 0x39e7: 0x0002, 0x39e8: 0x0002, 0x39e9: 0x0002, + 0x39ea: 0x0002, 0x39eb: 0x0002, 0x39ec: 0x0002, 0x39ed: 0x0002, 0x39ee: 0x0002, 0x39ef: 0x0002, + 0x39f0: 0x0002, 0x39f1: 0x0002, 0x39f2: 0x0002, 0x39f3: 0x0002, 0x39f4: 0x0002, 0x39f5: 0x0002, + 0x39f6: 0x0002, 0x39f7: 0x0002, 0x39f8: 0x0002, 0x39f9: 0x0002, 0x39fa: 0x0002, 0x39fb: 0x0002, + 0x39fc: 0x0002, 0x39ff: 0x0002, // Block 0xe8, offset 0x3a00 - 0x3a00: 0x0004, 0x3a01: 0x0004, 0x3a02: 0x0004, 0x3a03: 0x0004, 0x3a04: 0x0004, 0x3a05: 0x0004, - 0x3a06: 0x0004, 0x3a07: 0x0004, 0x3a08: 0x0004, 0x3a09: 0x0004, 0x3a0a: 0x0004, 0x3a0b: 0x0004, - 0x3a0c: 0x0004, 0x3a0d: 0x0004, 0x3a0e: 0x0004, 0x3a0f: 0x0004, 0x3a10: 0x0004, 0x3a11: 0x0004, - 0x3a12: 0x0004, 0x3a13: 0x0004, 0x3a14: 0x0004, 0x3a15: 0x0004, 0x3a16: 0x0004, 0x3a17: 0x0004, - 0x3a18: 0x0004, 0x3a19: 0x0004, 0x3a1a: 0x0004, 0x3a1b: 0x0004, 0x3a1c: 0x0004, 0x3a1d: 0x0004, - 0x3a1e: 0x0004, 0x3a1f: 0x0004, 0x3a20: 0x0004, 0x3a21: 0x0004, 0x3a22: 0x0004, 0x3a23: 0x0004, - 0x3a24: 0x0004, 0x3a25: 0x0004, 0x3a26: 0x0004, 0x3a27: 0x0004, 0x3a28: 0x0004, 0x3a29: 0x0004, - 0x3a2a: 0x0004, 0x3a2b: 0x0004, 0x3a2c: 0x0004, 0x3a2d: 0x0004, 0x3a2e: 0x0004, 0x3a2f: 0x0004, - 0x3a30: 0x0004, 0x3a31: 0x0004, 0x3a32: 0x0004, 0x3a33: 0x0004, 0x3a34: 0x0004, 0x3a35: 0x0004, - 0x3a36: 0x0004, 0x3a37: 0x0004, 0x3a38: 0x0004, 0x3a39: 0x0004, 0x3a3a: 0x0004, 0x3a3b: 0x0004, - 0x3a3c: 0x0004, 0x3a3d: 0x0004, + 0x3a00: 0x0002, 0x3a01: 0x0002, 0x3a02: 0x0002, 0x3a03: 0x0002, 0x3a04: 0x0002, 0x3a05: 0x0002, + 0x3a06: 0x0002, 0x3a07: 0x0002, 0x3a08: 0x0002, 0x3a09: 0x0002, 0x3a0a: 0x0002, 0x3a0b: 0x0002, + 0x3a0c: 0x0002, 0x3a0d: 0x0002, 0x3a0e: 0x0002, 0x3a0f: 0x0002, 0x3a10: 0x0002, 0x3a11: 0x0002, + 0x3a12: 0x0002, 0x3a13: 0x0002, 0x3a14: 0x0002, 0x3a15: 0x0002, 0x3a16: 0x0002, 0x3a17: 0x0002, + 0x3a18: 0x0002, 0x3a19: 0x0002, 0x3a1a: 0x0002, 0x3a1b: 0x0002, 0x3a1c: 0x0002, 0x3a1d: 0x0002, + 0x3a1e: 0x0002, 0x3a1f: 0x0002, 0x3a20: 0x0002, 0x3a21: 0x0002, 0x3a22: 0x0002, 0x3a23: 0x0002, + 0x3a24: 0x0002, 0x3a25: 0x0002, 0x3a26: 0x0002, 0x3a27: 0x0002, 0x3a28: 0x0002, 0x3a29: 0x0002, + 0x3a2a: 0x0002, 0x3a2b: 0x0002, 0x3a2c: 0x0002, 0x3a2d: 0x0002, 0x3a2e: 0x0002, 0x3a2f: 0x0002, + 0x3a30: 0x0002, 0x3a31: 0x0002, 0x3a32: 0x0002, 0x3a33: 0x0002, 0x3a34: 0x0002, 0x3a35: 0x0002, + 0x3a36: 0x0002, 0x3a37: 0x0002, 0x3a38: 0x0002, 0x3a39: 0x0002, 0x3a3a: 0x0002, 0x3a3b: 0x0002, + 0x3a3c: 0x0002, 0x3a3d: 0x0002, // Block 0xe9, offset 0x3a40 - 0x3a4b: 0x0004, - 0x3a4c: 0x0004, 0x3a4d: 0x0004, 0x3a4e: 0x0004, 0x3a50: 0x0004, 0x3a51: 0x0004, - 0x3a52: 0x0004, 0x3a53: 0x0004, 0x3a54: 0x0004, 0x3a55: 0x0004, 0x3a56: 0x0004, 0x3a57: 0x0004, - 0x3a58: 0x0004, 0x3a59: 0x0004, 0x3a5a: 0x0004, 0x3a5b: 0x0004, 0x3a5c: 0x0004, 0x3a5d: 0x0004, - 0x3a5e: 0x0004, 0x3a5f: 0x0004, 0x3a60: 0x0004, 0x3a61: 0x0004, 0x3a62: 0x0004, 0x3a63: 0x0004, - 0x3a64: 0x0004, 0x3a65: 0x0004, 0x3a66: 0x0004, 0x3a67: 0x0004, - 0x3a7a: 0x0004, + 0x3a4b: 0x0002, + 0x3a4c: 0x0002, 0x3a4d: 0x0002, 0x3a4e: 0x0002, 0x3a50: 0x0002, 0x3a51: 0x0002, + 0x3a52: 0x0002, 0x3a53: 0x0002, 0x3a54: 0x0002, 0x3a55: 0x0002, 0x3a56: 0x0002, 0x3a57: 0x0002, + 0x3a58: 0x0002, 0x3a59: 0x0002, 0x3a5a: 0x0002, 0x3a5b: 0x0002, 0x3a5c: 0x0002, 0x3a5d: 0x0002, + 0x3a5e: 0x0002, 0x3a5f: 0x0002, 0x3a60: 0x0002, 0x3a61: 0x0002, 0x3a62: 0x0002, 0x3a63: 0x0002, + 0x3a64: 0x0002, 0x3a65: 0x0002, 0x3a66: 0x0002, 0x3a67: 0x0002, + 0x3a7a: 0x0002, // Block 0xea, offset 0x3a80 - 0x3a95: 0x0004, 0x3a96: 0x0004, - 0x3aa4: 0x0004, + 0x3a95: 0x0002, 0x3a96: 0x0002, + 0x3aa4: 0x0002, // Block 0xeb, offset 0x3ac0 - 0x3afb: 0x0004, - 0x3afc: 0x0004, 0x3afd: 0x0004, 0x3afe: 0x0004, 0x3aff: 0x0004, + 0x3afb: 0x0002, + 0x3afc: 0x0002, 0x3afd: 0x0002, 0x3afe: 0x0002, 0x3aff: 0x0002, // Block 0xec, offset 0x3b00 - 0x3b00: 0x0004, 0x3b01: 0x0004, 0x3b02: 0x0004, 0x3b03: 0x0004, 0x3b04: 0x0004, 0x3b05: 0x0004, - 0x3b06: 0x0004, 0x3b07: 0x0004, 0x3b08: 0x0004, 0x3b09: 0x0004, 0x3b0a: 0x0004, 0x3b0b: 0x0004, - 0x3b0c: 0x0004, 0x3b0d: 0x0004, 0x3b0e: 0x0004, 0x3b0f: 0x0004, + 0x3b00: 0x0002, 0x3b01: 0x0002, 0x3b02: 0x0002, 0x3b03: 0x0002, 0x3b04: 0x0002, 0x3b05: 0x0002, + 0x3b06: 0x0002, 0x3b07: 0x0002, 0x3b08: 0x0002, 0x3b09: 0x0002, 0x3b0a: 0x0002, 0x3b0b: 0x0002, + 0x3b0c: 0x0002, 0x3b0d: 0x0002, 0x3b0e: 0x0002, 0x3b0f: 0x0002, // Block 0xed, offset 0x3b40 - 0x3b40: 0x0004, 0x3b41: 0x0004, 0x3b42: 0x0004, 0x3b43: 0x0004, 0x3b44: 0x0004, 0x3b45: 0x0004, - 0x3b4c: 0x0004, 0x3b50: 0x0004, 0x3b51: 0x0004, - 0x3b52: 0x0004, 0x3b55: 0x0004, 0x3b56: 0x0004, 0x3b57: 0x0004, - 0x3b5c: 0x0004, 0x3b5d: 0x0004, - 0x3b5e: 0x0004, 0x3b5f: 0x0004, - 0x3b6b: 0x0004, 0x3b6c: 0x0004, - 0x3b74: 0x0004, 0x3b75: 0x0004, - 0x3b76: 0x0004, 0x3b77: 0x0004, 0x3b78: 0x0004, 0x3b79: 0x0004, 0x3b7a: 0x0004, 0x3b7b: 0x0004, - 0x3b7c: 0x0004, + 0x3b40: 0x0002, 0x3b41: 0x0002, 0x3b42: 0x0002, 0x3b43: 0x0002, 0x3b44: 0x0002, 0x3b45: 0x0002, + 0x3b4c: 0x0002, 0x3b50: 0x0002, 0x3b51: 0x0002, + 0x3b52: 0x0002, 0x3b55: 0x0002, 0x3b56: 0x0002, 0x3b57: 0x0002, + 0x3b5c: 0x0002, 0x3b5d: 0x0002, + 0x3b5e: 0x0002, 0x3b5f: 0x0002, + 0x3b6b: 0x0002, 0x3b6c: 0x0002, + 0x3b74: 0x0002, 0x3b75: 0x0002, + 0x3b76: 0x0002, 0x3b77: 0x0002, 0x3b78: 0x0002, 0x3b79: 0x0002, 0x3b7a: 0x0002, 0x3b7b: 0x0002, + 0x3b7c: 0x0002, // Block 0xee, offset 0x3b80 - 0x3ba0: 0x0004, 0x3ba1: 0x0004, 0x3ba2: 0x0004, 0x3ba3: 0x0004, - 0x3ba4: 0x0004, 0x3ba5: 0x0004, 0x3ba6: 0x0004, 0x3ba7: 0x0004, 0x3ba8: 0x0004, 0x3ba9: 0x0004, - 0x3baa: 0x0004, 0x3bab: 0x0004, - 0x3bb0: 0x0004, + 0x3ba0: 0x0002, 0x3ba1: 0x0002, 0x3ba2: 0x0002, 0x3ba3: 0x0002, + 0x3ba4: 0x0002, 0x3ba5: 0x0002, 0x3ba6: 0x0002, 0x3ba7: 0x0002, 0x3ba8: 0x0002, 0x3ba9: 0x0002, + 0x3baa: 0x0002, 0x3bab: 0x0002, + 0x3bb0: 0x0002, // Block 0xef, offset 0x3bc0 - 0x3bcc: 0x0004, 0x3bcd: 0x0004, 0x3bce: 0x0004, 0x3bcf: 0x0004, 0x3bd0: 0x0004, 0x3bd1: 0x0004, - 0x3bd2: 0x0004, 0x3bd3: 0x0004, 0x3bd4: 0x0004, 0x3bd5: 0x0004, 0x3bd6: 0x0004, 0x3bd7: 0x0004, - 0x3bd8: 0x0004, 0x3bd9: 0x0004, 0x3bda: 0x0004, 0x3bdb: 0x0004, 0x3bdc: 0x0004, 0x3bdd: 0x0004, - 0x3bde: 0x0004, 0x3bdf: 0x0004, 0x3be0: 0x0004, 0x3be1: 0x0004, 0x3be2: 0x0004, 0x3be3: 0x0004, - 0x3be4: 0x0004, 0x3be5: 0x0004, 0x3be6: 0x0004, 0x3be7: 0x0004, 0x3be8: 0x0004, 0x3be9: 0x0004, - 0x3bea: 0x0004, 0x3beb: 0x0004, 0x3bec: 0x0004, 0x3bed: 0x0004, 0x3bee: 0x0004, 0x3bef: 0x0004, - 0x3bf0: 0x0004, 0x3bf1: 0x0004, 0x3bf2: 0x0004, 0x3bf3: 0x0004, 0x3bf4: 0x0004, 0x3bf5: 0x0004, - 0x3bf6: 0x0004, 0x3bf7: 0x0004, 0x3bf8: 0x0004, 0x3bf9: 0x0004, 0x3bfa: 0x0004, - 0x3bfc: 0x0004, 0x3bfd: 0x0004, 0x3bfe: 0x0004, 0x3bff: 0x0004, + 0x3bcc: 0x0002, 0x3bcd: 0x0002, 0x3bce: 0x0002, 0x3bcf: 0x0002, 0x3bd0: 0x0002, 0x3bd1: 0x0002, + 0x3bd2: 0x0002, 0x3bd3: 0x0002, 0x3bd4: 0x0002, 0x3bd5: 0x0002, 0x3bd6: 0x0002, 0x3bd7: 0x0002, + 0x3bd8: 0x0002, 0x3bd9: 0x0002, 0x3bda: 0x0002, 0x3bdb: 0x0002, 0x3bdc: 0x0002, 0x3bdd: 0x0002, + 0x3bde: 0x0002, 0x3bdf: 0x0002, 0x3be0: 0x0002, 0x3be1: 0x0002, 0x3be2: 0x0002, 0x3be3: 0x0002, + 0x3be4: 0x0002, 0x3be5: 0x0002, 0x3be6: 0x0002, 0x3be7: 0x0002, 0x3be8: 0x0002, 0x3be9: 0x0002, + 0x3bea: 0x0002, 0x3beb: 0x0002, 0x3bec: 0x0002, 0x3bed: 0x0002, 0x3bee: 0x0002, 0x3bef: 0x0002, + 0x3bf0: 0x0002, 0x3bf1: 0x0002, 0x3bf2: 0x0002, 0x3bf3: 0x0002, 0x3bf4: 0x0002, 0x3bf5: 0x0002, + 0x3bf6: 0x0002, 0x3bf7: 0x0002, 0x3bf8: 0x0002, 0x3bf9: 0x0002, 0x3bfa: 0x0002, + 0x3bfc: 0x0002, 0x3bfd: 0x0002, 0x3bfe: 0x0002, 0x3bff: 0x0002, // Block 0xf0, offset 0x3c00 - 0x3c00: 0x0004, 0x3c01: 0x0004, 0x3c02: 0x0004, 0x3c03: 0x0004, 0x3c04: 0x0004, 0x3c05: 0x0004, - 0x3c07: 0x0004, 0x3c08: 0x0004, 0x3c09: 0x0004, 0x3c0a: 0x0004, 0x3c0b: 0x0004, - 0x3c0c: 0x0004, 0x3c0d: 0x0004, 0x3c0e: 0x0004, 0x3c0f: 0x0004, 0x3c10: 0x0004, 0x3c11: 0x0004, - 0x3c12: 0x0004, 0x3c13: 0x0004, 0x3c14: 0x0004, 0x3c15: 0x0004, 0x3c16: 0x0004, 0x3c17: 0x0004, - 0x3c18: 0x0004, 0x3c19: 0x0004, 0x3c1a: 0x0004, 0x3c1b: 0x0004, 0x3c1c: 0x0004, 0x3c1d: 0x0004, - 0x3c1e: 0x0004, 0x3c1f: 0x0004, 0x3c20: 0x0004, 0x3c21: 0x0004, 0x3c22: 0x0004, 0x3c23: 0x0004, - 0x3c24: 0x0004, 0x3c25: 0x0004, 0x3c26: 0x0004, 0x3c27: 0x0004, 0x3c28: 0x0004, 0x3c29: 0x0004, - 0x3c2a: 0x0004, 0x3c2b: 0x0004, 0x3c2c: 0x0004, 0x3c2d: 0x0004, 0x3c2e: 0x0004, 0x3c2f: 0x0004, - 0x3c30: 0x0004, 0x3c31: 0x0004, 0x3c32: 0x0004, 0x3c33: 0x0004, 0x3c34: 0x0004, 0x3c35: 0x0004, - 0x3c36: 0x0004, 0x3c37: 0x0004, 0x3c38: 0x0004, 0x3c39: 0x0004, 0x3c3a: 0x0004, 0x3c3b: 0x0004, - 0x3c3c: 0x0004, 0x3c3d: 0x0004, 0x3c3e: 0x0004, 0x3c3f: 0x0004, + 0x3c00: 0x0002, 0x3c01: 0x0002, 0x3c02: 0x0002, 0x3c03: 0x0002, 0x3c04: 0x0002, 0x3c05: 0x0002, + 0x3c07: 0x0002, 0x3c08: 0x0002, 0x3c09: 0x0002, 0x3c0a: 0x0002, 0x3c0b: 0x0002, + 0x3c0c: 0x0002, 0x3c0d: 0x0002, 0x3c0e: 0x0002, 0x3c0f: 0x0002, 0x3c10: 0x0002, 0x3c11: 0x0002, + 0x3c12: 0x0002, 0x3c13: 0x0002, 0x3c14: 0x0002, 0x3c15: 0x0002, 0x3c16: 0x0002, 0x3c17: 0x0002, + 0x3c18: 0x0002, 0x3c19: 0x0002, 0x3c1a: 0x0002, 0x3c1b: 0x0002, 0x3c1c: 0x0002, 0x3c1d: 0x0002, + 0x3c1e: 0x0002, 0x3c1f: 0x0002, 0x3c20: 0x0002, 0x3c21: 0x0002, 0x3c22: 0x0002, 0x3c23: 0x0002, + 0x3c24: 0x0002, 0x3c25: 0x0002, 0x3c26: 0x0002, 0x3c27: 0x0002, 0x3c28: 0x0002, 0x3c29: 0x0002, + 0x3c2a: 0x0002, 0x3c2b: 0x0002, 0x3c2c: 0x0002, 0x3c2d: 0x0002, 0x3c2e: 0x0002, 0x3c2f: 0x0002, + 0x3c30: 0x0002, 0x3c31: 0x0002, 0x3c32: 0x0002, 0x3c33: 0x0002, 0x3c34: 0x0002, 0x3c35: 0x0002, + 0x3c36: 0x0002, 0x3c37: 0x0002, 0x3c38: 0x0002, 0x3c39: 0x0002, 0x3c3a: 0x0002, 0x3c3b: 0x0002, + 0x3c3c: 0x0002, 0x3c3d: 0x0002, 0x3c3e: 0x0002, 0x3c3f: 0x0002, // Block 0xf1, offset 0x3c40 - 0x3c70: 0x0004, 0x3c71: 0x0004, 0x3c72: 0x0004, 0x3c73: 0x0004, 0x3c74: 0x0004, 0x3c75: 0x0004, - 0x3c76: 0x0004, 0x3c77: 0x0004, 0x3c78: 0x0004, 0x3c79: 0x0004, 0x3c7a: 0x0004, 0x3c7b: 0x0004, - 0x3c7c: 0x0004, + 0x3c70: 0x0002, 0x3c71: 0x0002, 0x3c72: 0x0002, 0x3c73: 0x0002, 0x3c74: 0x0002, 0x3c75: 0x0002, + 0x3c76: 0x0002, 0x3c77: 0x0002, 0x3c78: 0x0002, 0x3c79: 0x0002, 0x3c7a: 0x0002, 0x3c7b: 0x0002, + 0x3c7c: 0x0002, // Block 0xf2, offset 0x3c80 - 0x3c80: 0x0004, 0x3c81: 0x0004, 0x3c82: 0x0004, 0x3c83: 0x0004, 0x3c84: 0x0004, 0x3c85: 0x0004, - 0x3c86: 0x0004, 0x3c87: 0x0004, 0x3c88: 0x0004, 0x3c89: 0x0004, - 0x3c8f: 0x0004, 0x3c90: 0x0004, 0x3c91: 0x0004, - 0x3c92: 0x0004, 0x3c93: 0x0004, 0x3c94: 0x0004, 0x3c95: 0x0004, 0x3c96: 0x0004, 0x3c97: 0x0004, - 0x3c98: 0x0004, 0x3c99: 0x0004, 0x3c9a: 0x0004, 0x3c9b: 0x0004, 0x3c9c: 0x0004, 0x3c9d: 0x0004, - 0x3c9e: 0x0004, 0x3c9f: 0x0004, 0x3ca0: 0x0004, 0x3ca1: 0x0004, 0x3ca2: 0x0004, 0x3ca3: 0x0004, - 0x3ca4: 0x0004, 0x3ca5: 0x0004, 0x3ca6: 0x0004, 0x3ca7: 0x0004, 0x3ca8: 0x0004, 0x3ca9: 0x0004, - 0x3caa: 0x0004, 0x3cab: 0x0004, 0x3cac: 0x0004, 0x3cad: 0x0004, 0x3cae: 0x0004, 0x3caf: 0x0004, - 0x3cb0: 0x0004, 0x3cb1: 0x0004, 0x3cb2: 0x0004, 0x3cb3: 0x0004, 0x3cb4: 0x0004, 0x3cb5: 0x0004, - 0x3cb6: 0x0004, 0x3cb7: 0x0004, 0x3cb8: 0x0004, 0x3cb9: 0x0004, 0x3cba: 0x0004, 0x3cbb: 0x0004, - 0x3cbc: 0x0004, 0x3cbd: 0x0004, 0x3cbe: 0x0004, 0x3cbf: 0x0004, + 0x3c80: 0x0002, 0x3c81: 0x0002, 0x3c82: 0x0002, 0x3c83: 0x0002, 0x3c84: 0x0002, 0x3c85: 0x0002, + 0x3c86: 0x0002, 0x3c87: 0x0002, 0x3c88: 0x0002, 0x3c89: 0x0002, + 0x3c8f: 0x0002, 0x3c90: 0x0002, 0x3c91: 0x0002, + 0x3c92: 0x0002, 0x3c93: 0x0002, 0x3c94: 0x0002, 0x3c95: 0x0002, 0x3c96: 0x0002, 0x3c97: 0x0002, + 0x3c98: 0x0002, 0x3c99: 0x0002, 0x3c9a: 0x0002, 0x3c9b: 0x0002, 0x3c9c: 0x0002, 0x3c9d: 0x0002, + 0x3c9e: 0x0002, 0x3c9f: 0x0002, 0x3ca0: 0x0002, 0x3ca1: 0x0002, 0x3ca2: 0x0002, 0x3ca3: 0x0002, + 0x3ca4: 0x0002, 0x3ca5: 0x0002, 0x3ca6: 0x0002, 0x3ca7: 0x0002, 0x3ca8: 0x0002, 0x3ca9: 0x0002, + 0x3caa: 0x0002, 0x3cab: 0x0002, 0x3cac: 0x0002, 0x3cad: 0x0002, 0x3cae: 0x0002, 0x3caf: 0x0002, + 0x3cb0: 0x0002, 0x3cb1: 0x0002, 0x3cb2: 0x0002, 0x3cb3: 0x0002, 0x3cb4: 0x0002, 0x3cb5: 0x0002, + 0x3cb6: 0x0002, 0x3cb7: 0x0002, 0x3cb8: 0x0002, 0x3cb9: 0x0002, 0x3cba: 0x0002, 0x3cbb: 0x0002, + 0x3cbc: 0x0002, 0x3cbd: 0x0002, 0x3cbe: 0x0002, 0x3cbf: 0x0002, // Block 0xf3, offset 0x3cc0 - 0x3cc0: 0x0004, 0x3cc1: 0x0004, 0x3cc2: 0x0004, 0x3cc3: 0x0004, 0x3cc4: 0x0004, 0x3cc5: 0x0004, - 0x3cc6: 0x0004, - 0x3cce: 0x0004, 0x3ccf: 0x0004, 0x3cd0: 0x0004, 0x3cd1: 0x0004, - 0x3cd2: 0x0004, 0x3cd3: 0x0004, 0x3cd4: 0x0004, 0x3cd5: 0x0004, 0x3cd6: 0x0004, 0x3cd7: 0x0004, - 0x3cd8: 0x0004, 0x3cd9: 0x0004, 0x3cda: 0x0004, 0x3cdb: 0x0004, 0x3cdc: 0x0004, - 0x3cdf: 0x0004, 0x3ce0: 0x0004, 0x3ce1: 0x0004, 0x3ce2: 0x0004, 0x3ce3: 0x0004, - 0x3ce4: 0x0004, 0x3ce5: 0x0004, 0x3ce6: 0x0004, 0x3ce7: 0x0004, 0x3ce8: 0x0004, 0x3ce9: 0x0004, - 0x3cf0: 0x0004, 0x3cf1: 0x0004, 0x3cf2: 0x0004, 0x3cf3: 0x0004, 0x3cf4: 0x0004, 0x3cf5: 0x0004, - 0x3cf6: 0x0004, 0x3cf7: 0x0004, 0x3cf8: 0x0004, + 0x3cc0: 0x0002, 0x3cc1: 0x0002, 0x3cc2: 0x0002, 0x3cc3: 0x0002, 0x3cc4: 0x0002, 0x3cc5: 0x0002, + 0x3cc6: 0x0002, + 0x3cce: 0x0002, 0x3ccf: 0x0002, 0x3cd0: 0x0002, 0x3cd1: 0x0002, + 0x3cd2: 0x0002, 0x3cd3: 0x0002, 0x3cd4: 0x0002, 0x3cd5: 0x0002, 0x3cd6: 0x0002, 0x3cd7: 0x0002, + 0x3cd8: 0x0002, 0x3cd9: 0x0002, 0x3cda: 0x0002, 0x3cdb: 0x0002, 0x3cdc: 0x0002, + 0x3cdf: 0x0002, 0x3ce0: 0x0002, 0x3ce1: 0x0002, 0x3ce2: 0x0002, 0x3ce3: 0x0002, + 0x3ce4: 0x0002, 0x3ce5: 0x0002, 0x3ce6: 0x0002, 0x3ce7: 0x0002, 0x3ce8: 0x0002, 0x3ce9: 0x0002, + 0x3cf0: 0x0002, 0x3cf1: 0x0002, 0x3cf2: 0x0002, 0x3cf3: 0x0002, 0x3cf4: 0x0002, 0x3cf5: 0x0002, + 0x3cf6: 0x0002, 0x3cf7: 0x0002, 0x3cf8: 0x0002, // Block 0xf4, offset 0x3d00 - 0x3d00: 0x0002, 0x3d01: 0x0002, 0x3d02: 0x0002, 0x3d03: 0x0002, 0x3d04: 0x0002, 0x3d05: 0x0002, - 0x3d06: 0x0002, 0x3d07: 0x0002, 0x3d08: 0x0002, 0x3d09: 0x0002, 0x3d0a: 0x0002, 0x3d0b: 0x0002, - 0x3d0c: 0x0002, 0x3d0d: 0x0002, 0x3d0e: 0x0002, 0x3d0f: 0x0002, 0x3d10: 0x0002, 0x3d11: 0x0002, - 0x3d12: 0x0002, 0x3d13: 0x0002, 0x3d14: 0x0002, 0x3d15: 0x0002, 0x3d16: 0x0002, 0x3d17: 0x0002, - 0x3d18: 0x0002, 0x3d19: 0x0002, 0x3d1a: 0x0002, 0x3d1b: 0x0002, 0x3d1c: 0x0002, 0x3d1d: 0x0002, - 0x3d1e: 0x0002, 0x3d1f: 0x0002, 0x3d20: 0x0002, 0x3d21: 0x0002, 0x3d22: 0x0002, 0x3d23: 0x0002, - 0x3d24: 0x0002, 0x3d25: 0x0002, 0x3d26: 0x0002, 0x3d27: 0x0002, 0x3d28: 0x0002, 0x3d29: 0x0002, - 0x3d2a: 0x0002, 0x3d2b: 0x0002, 0x3d2c: 0x0002, 0x3d2d: 0x0002, 0x3d2e: 0x0002, 0x3d2f: 0x0002, - 0x3d30: 0x0002, 0x3d31: 0x0002, 0x3d32: 0x0002, 0x3d33: 0x0002, 0x3d34: 0x0002, 0x3d35: 0x0002, - 0x3d36: 0x0002, 0x3d37: 0x0002, 0x3d38: 0x0002, 0x3d39: 0x0002, 0x3d3a: 0x0002, 0x3d3b: 0x0002, - 0x3d3c: 0x0002, 0x3d3d: 0x0002, + 0x3d01: 0x0001, + 0x3d20: 0x0001, 0x3d21: 0x0001, 0x3d22: 0x0001, 0x3d23: 0x0001, + 0x3d24: 0x0001, 0x3d25: 0x0001, 0x3d26: 0x0001, 0x3d27: 0x0001, 0x3d28: 0x0001, 0x3d29: 0x0001, + 0x3d2a: 0x0001, 0x3d2b: 0x0001, 0x3d2c: 0x0001, 0x3d2d: 0x0001, 0x3d2e: 0x0001, 0x3d2f: 0x0001, + 0x3d30: 0x0001, 0x3d31: 0x0001, 0x3d32: 0x0001, 0x3d33: 0x0001, 0x3d34: 0x0001, 0x3d35: 0x0001, + 0x3d36: 0x0001, 0x3d37: 0x0001, 0x3d38: 0x0001, 0x3d39: 0x0001, 0x3d3a: 0x0001, 0x3d3b: 0x0001, + 0x3d3c: 0x0001, 0x3d3d: 0x0001, 0x3d3e: 0x0001, 0x3d3f: 0x0001, // Block 0xf5, offset 0x3d40 - 0x3d41: 0x0001, - 0x3d60: 0x0001, 0x3d61: 0x0001, 0x3d62: 0x0001, 0x3d63: 0x0001, - 0x3d64: 0x0001, 0x3d65: 0x0001, 0x3d66: 0x0001, 0x3d67: 0x0001, 0x3d68: 0x0001, 0x3d69: 0x0001, - 0x3d6a: 0x0001, 0x3d6b: 0x0001, 0x3d6c: 0x0001, 0x3d6d: 0x0001, 0x3d6e: 0x0001, 0x3d6f: 0x0001, - 0x3d70: 0x0001, 0x3d71: 0x0001, 0x3d72: 0x0001, 0x3d73: 0x0001, 0x3d74: 0x0001, 0x3d75: 0x0001, - 0x3d76: 0x0001, 0x3d77: 0x0001, 0x3d78: 0x0001, 0x3d79: 0x0001, 0x3d7a: 0x0001, 0x3d7b: 0x0001, - 0x3d7c: 0x0001, 0x3d7d: 0x0001, 0x3d7e: 0x0001, 0x3d7f: 0x0001, - // Block 0xf6, offset 0x3d80 - 0x3d80: 0x0003, 0x3d81: 0x0003, 0x3d82: 0x0003, 0x3d83: 0x0003, 0x3d84: 0x0003, 0x3d85: 0x0003, - 0x3d86: 0x0003, 0x3d87: 0x0003, 0x3d88: 0x0003, 0x3d89: 0x0003, 0x3d8a: 0x0003, 0x3d8b: 0x0003, - 0x3d8c: 0x0003, 0x3d8d: 0x0003, 0x3d8e: 0x0003, 0x3d8f: 0x0003, 0x3d90: 0x0003, 0x3d91: 0x0003, - 0x3d92: 0x0003, 0x3d93: 0x0003, 0x3d94: 0x0003, 0x3d95: 0x0003, 0x3d96: 0x0003, 0x3d97: 0x0003, - 0x3d98: 0x0003, 0x3d99: 0x0003, 0x3d9a: 0x0003, 0x3d9b: 0x0003, 0x3d9c: 0x0003, 0x3d9d: 0x0003, - 0x3d9e: 0x0003, 0x3d9f: 0x0003, 0x3da0: 0x0003, 0x3da1: 0x0003, 0x3da2: 0x0003, 0x3da3: 0x0003, - 0x3da4: 0x0003, 0x3da5: 0x0003, 0x3da6: 0x0003, 0x3da7: 0x0003, 0x3da8: 0x0003, 0x3da9: 0x0003, - 0x3daa: 0x0003, 0x3dab: 0x0003, 0x3dac: 0x0003, 0x3dad: 0x0003, 0x3dae: 0x0003, 0x3daf: 0x0003, - 0x3db0: 0x0003, 0x3db1: 0x0003, 0x3db2: 0x0003, 0x3db3: 0x0003, 0x3db4: 0x0003, 0x3db5: 0x0003, - 0x3db6: 0x0003, 0x3db7: 0x0003, 0x3db8: 0x0003, 0x3db9: 0x0003, 0x3dba: 0x0003, 0x3dbb: 0x0003, - 0x3dbc: 0x0003, 0x3dbd: 0x0003, + 0x3d40: 0x0003, 0x3d41: 0x0003, 0x3d42: 0x0003, 0x3d43: 0x0003, 0x3d44: 0x0003, 0x3d45: 0x0003, + 0x3d46: 0x0003, 0x3d47: 0x0003, 0x3d48: 0x0003, 0x3d49: 0x0003, 0x3d4a: 0x0003, 0x3d4b: 0x0003, + 0x3d4c: 0x0003, 0x3d4d: 0x0003, 0x3d4e: 0x0003, 0x3d4f: 0x0003, 0x3d50: 0x0003, 0x3d51: 0x0003, + 0x3d52: 0x0003, 0x3d53: 0x0003, 0x3d54: 0x0003, 0x3d55: 0x0003, 0x3d56: 0x0003, 0x3d57: 0x0003, + 0x3d58: 0x0003, 0x3d59: 0x0003, 0x3d5a: 0x0003, 0x3d5b: 0x0003, 0x3d5c: 0x0003, 0x3d5d: 0x0003, + 0x3d5e: 0x0003, 0x3d5f: 0x0003, 0x3d60: 0x0003, 0x3d61: 0x0003, 0x3d62: 0x0003, 0x3d63: 0x0003, + 0x3d64: 0x0003, 0x3d65: 0x0003, 0x3d66: 0x0003, 0x3d67: 0x0003, 0x3d68: 0x0003, 0x3d69: 0x0003, + 0x3d6a: 0x0003, 0x3d6b: 0x0003, 0x3d6c: 0x0003, 0x3d6d: 0x0003, 0x3d6e: 0x0003, 0x3d6f: 0x0003, + 0x3d70: 0x0003, 0x3d71: 0x0003, 0x3d72: 0x0003, 0x3d73: 0x0003, 0x3d74: 0x0003, 0x3d75: 0x0003, + 0x3d76: 0x0003, 0x3d77: 0x0003, 0x3d78: 0x0003, 0x3d79: 0x0003, 0x3d7a: 0x0003, 0x3d7b: 0x0003, + 0x3d7c: 0x0003, 0x3d7d: 0x0003, } // stringWidthIndex: 30 blocks, 1920 entries, 1920 bytes @@ -1673,11 +1653,11 @@ var stringWidthIndex = [1920]uint8{ 0x593: 0xd4, 0x5a3: 0xd5, 0x5a5: 0xd6, // Block 0x17, offset 0x5c0 - 0x5c0: 0xd7, 0x5c3: 0xd8, 0x5c4: 0xd9, 0x5c5: 0xda, 0x5c6: 0xdb, - 0x5c8: 0xdc, 0x5c9: 0xdd, 0x5cc: 0xde, 0x5cd: 0xdf, 0x5ce: 0xe0, 0x5cf: 0xe1, - 0x5d0: 0xe2, 0x5d1: 0xe3, 0x5d2: 0xe4, 0x5d3: 0xe5, 0x5d4: 0xe6, 0x5d5: 0xe7, 0x5d6: 0xe8, 0x5d7: 0xe9, - 0x5d8: 0xe4, 0x5d9: 0xea, 0x5da: 0xe4, 0x5db: 0xeb, 0x5df: 0xec, - 0x5e4: 0xed, 0x5e5: 0xee, 0x5e6: 0xe4, 0x5e7: 0xe4, + 0x5c0: 0xd7, 0x5c3: 0xd8, 0x5c4: 0xd9, 0x5c5: 0xda, 0x5c6: 0xdb, 0x5c7: 0xdc, + 0x5c8: 0xdd, 0x5c9: 0xde, 0x5cc: 0xdf, 0x5cd: 0xe0, 0x5ce: 0xe1, 0x5cf: 0xe2, + 0x5d0: 0xe3, 0x5d1: 0xe4, 0x5d2: 0x39, 0x5d3: 0xe5, 0x5d4: 0xe6, 0x5d5: 0xe7, 0x5d6: 0xe8, 0x5d7: 0xe9, + 0x5d8: 0x39, 0x5d9: 0xea, 0x5da: 0x39, 0x5db: 0xeb, 0x5df: 0xec, + 0x5e4: 0xed, 0x5e5: 0xee, 0x5e6: 0x39, 0x5e7: 0x39, 0x5e9: 0xef, 0x5ea: 0xf0, 0x5eb: 0xf1, // Block 0x18, offset 0x600 0x600: 0x39, 0x601: 0x39, 0x602: 0x39, 0x603: 0x39, 0x604: 0x39, 0x605: 0x39, 0x606: 0x39, 0x607: 0x39, @@ -1687,7 +1667,7 @@ var stringWidthIndex = [1920]uint8{ 0x620: 0x39, 0x621: 0x39, 0x622: 0x39, 0x623: 0x39, 0x624: 0x39, 0x625: 0x39, 0x626: 0x39, 0x627: 0x39, 0x628: 0x39, 0x629: 0x39, 0x62a: 0x39, 0x62b: 0x39, 0x62c: 0x39, 0x62d: 0x39, 0x62e: 0x39, 0x62f: 0x39, 0x630: 0x39, 0x631: 0x39, 0x632: 0x39, 0x633: 0x39, 0x634: 0x39, 0x635: 0x39, 0x636: 0x39, 0x637: 0x39, - 0x638: 0x39, 0x639: 0x39, 0x63a: 0x39, 0x63b: 0x39, 0x63c: 0x39, 0x63d: 0x39, 0x63e: 0x39, 0x63f: 0xf2, + 0x638: 0x39, 0x639: 0x39, 0x63a: 0x39, 0x63b: 0x39, 0x63c: 0x39, 0x63d: 0x39, 0x63e: 0x39, 0x63f: 0xe6, // Block 0x19, offset 0x640 0x650: 0x0b, 0x651: 0x0c, 0x653: 0x0d, 0x656: 0x0e, 0x657: 0x06, 0x658: 0x0f, 0x65a: 0x10, 0x65b: 0x11, 0x65c: 0x12, 0x65d: 0x13, 0x65e: 0x14, 0x65f: 0x15, @@ -1696,7 +1676,7 @@ var stringWidthIndex = [1920]uint8{ 0x670: 0x06, 0x671: 0x06, 0x672: 0x06, 0x673: 0x06, 0x674: 0x06, 0x675: 0x06, 0x676: 0x06, 0x677: 0x06, 0x678: 0x06, 0x679: 0x06, 0x67a: 0x06, 0x67b: 0x06, 0x67c: 0x06, 0x67d: 0x06, 0x67e: 0x06, 0x67f: 0x16, // Block 0x1a, offset 0x680 - 0x680: 0xf3, 0x681: 0x08, 0x684: 0x08, 0x685: 0x08, 0x686: 0x08, 0x687: 0x09, + 0x680: 0xf2, 0x681: 0x08, 0x684: 0x08, 0x685: 0x08, 0x686: 0x08, 0x687: 0x09, // Block 0x1b, offset 0x6c0 0x6c0: 0x5b, 0x6c1: 0x5b, 0x6c2: 0x5b, 0x6c3: 0x5b, 0x6c4: 0x5b, 0x6c5: 0x5b, 0x6c6: 0x5b, 0x6c7: 0x5b, 0x6c8: 0x5b, 0x6c9: 0x5b, 0x6ca: 0x5b, 0x6cb: 0x5b, 0x6cc: 0x5b, 0x6cd: 0x5b, 0x6ce: 0x5b, 0x6cf: 0x5b, @@ -1705,7 +1685,7 @@ var stringWidthIndex = [1920]uint8{ 0x6e0: 0x5b, 0x6e1: 0x5b, 0x6e2: 0x5b, 0x6e3: 0x5b, 0x6e4: 0x5b, 0x6e5: 0x5b, 0x6e6: 0x5b, 0x6e7: 0x5b, 0x6e8: 0x5b, 0x6e9: 0x5b, 0x6ea: 0x5b, 0x6eb: 0x5b, 0x6ec: 0x5b, 0x6ed: 0x5b, 0x6ee: 0x5b, 0x6ef: 0x5b, 0x6f0: 0x5b, 0x6f1: 0x5b, 0x6f2: 0x5b, 0x6f3: 0x5b, 0x6f4: 0x5b, 0x6f5: 0x5b, 0x6f6: 0x5b, 0x6f7: 0x5b, - 0x6f8: 0x5b, 0x6f9: 0x5b, 0x6fa: 0x5b, 0x6fb: 0x5b, 0x6fc: 0x5b, 0x6fd: 0x5b, 0x6fe: 0x5b, 0x6ff: 0xf4, + 0x6f8: 0x5b, 0x6f9: 0x5b, 0x6fa: 0x5b, 0x6fb: 0x5b, 0x6fc: 0x5b, 0x6fd: 0x5b, 0x6fe: 0x5b, 0x6ff: 0xf3, // Block 0x1c, offset 0x700 0x720: 0x18, 0x730: 0x09, 0x731: 0x09, 0x732: 0x09, 0x733: 0x09, 0x734: 0x09, 0x735: 0x09, 0x736: 0x09, 0x737: 0x09, diff --git a/vendor/github.com/clipperhouse/displaywidth/width.go b/vendor/github.com/clipperhouse/displaywidth/width.go index bd6b65f047..a96ab0b075 100644 --- a/vendor/github.com/clipperhouse/displaywidth/width.go +++ b/vendor/github.com/clipperhouse/displaywidth/width.go @@ -34,7 +34,7 @@ func (options Options) String(s string) int { case 0: return 0 case 1: - return int(asciiWidths[s[0]]) + return asciiWidth(s[0]) } width := 0 @@ -60,7 +60,7 @@ func (options Options) Bytes(s []byte) int { case 0: return 0 case 1: - return int(asciiWidths[s[0]]) + return asciiWidth(s[0]) } width := 0 @@ -90,7 +90,7 @@ func Rune(r rune) int { // Iterating over runes to measure width is incorrect in many cases. func (options Options) Rune(r rune) int { if r < utf8.RuneSelf { - return int(asciiWidths[byte(r)]) + return asciiWidth(byte(r)) } // Surrogates (U+D800-U+DFFF) are invalid UTF-8. @@ -102,9 +102,11 @@ func (options Options) Rune(r rune) int { n := utf8.EncodeRune(buf[:], r) // Skip the grapheme iterator - return lookupProperties(buf[:n]).width(options) + return graphemeWidth(buf[:n], options) } +const _Default property = 0 + // graphemeWidth returns the display width of a grapheme cluster. // The passed string must be a single grapheme cluster. func graphemeWidth[T stringish.Interface](s T, options Options) int { @@ -113,99 +115,53 @@ func graphemeWidth[T stringish.Interface](s T, options Options) int { case 0: return 0 case 1: - return int(asciiWidths[s[0]]) - } - - return lookupProperties(s).width(options) -} - -// isRIPrefix checks if the slice matches the Regional Indicator prefix -// (F0 9F 87). It assumes len(s) >= 3. -func isRIPrefix[T stringish.Interface](s T) bool { - return s[0] == 0xF0 && s[1] == 0x9F && s[2] == 0x87 -} - -// isVS16 checks if the slice matches VS16 (U+FE0F) UTF-8 encoding -// (EF B8 8F). It assumes len(s) >= 3. -func isVS16[T stringish.Interface](s T) bool { - return s[0] == 0xEF && s[1] == 0xB8 && s[2] == 0x8F -} - -// lookupProperties returns the properties for a grapheme. -// The passed string must be at least one byte long. -// -// Callers must handle zero and single-byte strings upstream, both as an -// optimization, and to reduce the scope of this function. -func lookupProperties[T stringish.Interface](s T) property { - l := len(s) - - if s[0] < utf8.RuneSelf { - // Check for variation selector after ASCII (e.g., keycap sequences like 1️⃣) - if l >= 4 { - // Subslice may help eliminate bounds checks - vs := s[1:4] - if isVS16(vs) { - // VS16 requests emoji presentation (width 2) - return _Emoji - } - // VS15 (0x8E) requests text presentation but does not affect width, - // in my reading of Unicode TR51. Falls through to _Default. - } - return asciiProperties[s[0]] - } - - // Regional indicator pair (flag) - if l >= 8 { - // Subslice may help eliminate bounds checks - ri := s[:8] - // First rune - if isRIPrefix(ri[0:3]) { - b3 := ri[3] - if b3 >= 0xA6 && b3 <= 0xBF { - // Second rune - if isRIPrefix(ri[4:7]) { - b7 := ri[7] - if b7 >= 0xA6 && b7 <= 0xBF { - return _Emoji - } - } - } - } + return asciiWidth(s[0]) } p, sz := lookup(s) + prop := property(p) - // Variation Selectors - if sz > 0 && l >= sz+3 { - // Subslice may help eliminate bounds checks + // Variation Selector 16 (VS16) requests emoji presentation + if prop != _Wide && sz > 0 && len(s) >= sz+3 { vs := s[sz : sz+3] if isVS16(vs) { - // VS16 requests emoji presentation (width 2) - return _Emoji + prop = _Wide } // VS15 (0x8E) requests text presentation but does not affect width, // in my reading of Unicode TR51. Falls through to return the base // character's property. } - return property(p) -} - -const _Default property = 0 -const boundsCheck = property(len(propertyWidths) - 1) + if options.EastAsianWidth && prop == _East_Asian_Ambiguous { + prop = _Wide + } -// width determines the display width of a character based on its properties, -// and configuration options -func (p property) width(options Options) int { - if options.EastAsianWidth && p == _East_Asian_Ambiguous { - return 2 + if prop > upperBound { + prop = _Default } - // Bounds check may help the compiler eliminate its bounds check, - // and safety of course. - if p > boundsCheck { - return 1 // default width + return propertyWidths[prop] +} + +func asciiWidth(b byte) int { + if b <= 0x1F || b == 0x7F { + return 0 } + return 1 +} + +// isVS16 checks if the slice matches VS16 (U+FE0F) UTF-8 encoding +// (EF B8 8F). It assumes len(s) >= 3. +func isVS16[T stringish.Interface](s T) bool { + return s[0] == 0xEF && s[1] == 0xB8 && s[2] == 0x8F +} - return propertyWidths[p] +// propertyWidths is a jump table of sorts, instead of a switch +var propertyWidths = [4]int{ + _Default: 1, + _Zero_Width: 0, + _Wide: 2, + _East_Asian_Ambiguous: 1, } + +const upperBound = property(len(propertyWidths) - 1) diff --git a/vendor/github.com/olekukonko/ll/global.go b/vendor/github.com/olekukonko/ll/global.go index 85146f5436..178de8fe4a 100644 --- a/vendor/github.com/olekukonko/ll/global.go +++ b/vendor/github.com/olekukonko/ll/global.go @@ -667,3 +667,8 @@ func Inspect(values ...interface{}) { o := NewInspector(defaultLogger) o.Log(2, values...) } + +func Apply(opts ...Option) *Logger { + return defaultLogger.Apply(opts...) + +} diff --git a/vendor/github.com/olekukonko/ll/lh/colorized.go b/vendor/github.com/olekukonko/ll/lh/colorized.go index e343ff3816..fcc0c9ec8e 100644 --- a/vendor/github.com/olekukonko/ll/lh/colorized.go +++ b/vendor/github.com/olekukonko/ll/lh/colorized.go @@ -29,6 +29,7 @@ type Palette struct { Info string // Color for Info level messages Warn string // Color for Warn level messages Error string // Color for Error level messages + Fatal string // Color for Fatal level messages Title string // Color for dump titles (BEGIN/END separators) } @@ -47,10 +48,11 @@ var darkPalette = Palette{ Hex: "\033[38;5;156m", // Light green for hex values Ascii: "\033[38;5;224m", // Light pink for ASCII values - Debug: "\033[36m", // Cyan for Debug level - Info: "\033[32m", // Green for Info level - Warn: "\033[33m", // Yellow for Warn level - Error: "\033[31m", // Red for Error level + Debug: "\033[36m", // Cyan for Debug level + Info: "\033[32m", // Green for Info level + Warn: "\033[33m", // Yellow for Warn level + Error: "\033[31m", // Standard red + Fatal: "\033[1;31m", // Bold red - stands out more } // lightPalette defines colors optimized for light terminal backgrounds. @@ -68,10 +70,11 @@ var lightPalette = Palette{ Hex: "\033[38;5;156m", // Light green for hex values Ascii: "\033[38;5;224m", // Light pink for ASCII values - Debug: "\033[36m", // Cyan for Debug level - Info: "\033[32m", // Green for Info level - Warn: "\033[33m", // Yellow for Warn level - Error: "\033[31m", // Red for Error level + Debug: "\033[36m", // Cyan for Debug level + Info: "\033[32m", // Green for Info level + Warn: "\033[33m", // Yellow for Warn level + Error: "\033[31m", // Standard red + Fatal: "\033[1;31m", // Bold red - stands out more } // ColorizedHandler is a handler that outputs log entries with ANSI color codes. @@ -250,6 +253,7 @@ func (h *ColorizedHandler) formatLevel(b *strings.Builder, e *lx.Entry) { lx.LevelInfo: h.palette.Info, // Green lx.LevelWarn: h.palette.Warn, // Yellow lx.LevelError: h.palette.Error, // Red + lx.LevelFatal: h.palette.Fatal, // Bold Red }[e.Level] b.WriteString(color) diff --git a/vendor/github.com/olekukonko/ll/lh/multi.go b/vendor/github.com/olekukonko/ll/lh/multi.go index 8a9d8846d3..54ca9768da 100644 --- a/vendor/github.com/olekukonko/ll/lh/multi.go +++ b/vendor/github.com/olekukonko/ll/lh/multi.go @@ -3,6 +3,7 @@ package lh import ( "errors" "fmt" + "github.com/olekukonko/ll/lx" ) @@ -30,6 +31,18 @@ func NewMultiHandler(h ...lx.Handler) *MultiHandler { } } +// Len returns the number of handlers in the MultiHandler. +func (h *MultiHandler) Len() int { + return len(h.Handlers) +} + +// Append adds one or more lx.Handler instances to the MultiHandler's list of handlers. +func (h *MultiHandler) Append(handlers ...lx.Handler) { + for _, e := range handlers { + h.Handlers = append(h.Handlers, e) + } +} + // Handle implements the Handler interface, calling Handle on each handler in sequence. // It collects any errors from handlers and combines them into a single error using errors.Join. // If no errors occur, it returns nil. Thread-safe if the underlying handlers are thread-safe. diff --git a/vendor/github.com/olekukonko/ll/lh/slog.go b/vendor/github.com/olekukonko/ll/lh/slog.go index 77584202ea..0b738d9738 100644 --- a/vendor/github.com/olekukonko/ll/lh/slog.go +++ b/vendor/github.com/olekukonko/ll/lh/slog.go @@ -2,8 +2,9 @@ package lh import ( "context" - "github.com/olekukonko/ll/lx" "log/slog" + + "github.com/olekukonko/ll/lx" ) // SlogHandler adapts a slog.Handler to implement lx.Handler. @@ -81,7 +82,7 @@ func toSlogLevel(level lx.LevelType) slog.Level { return slog.LevelInfo case lx.LevelWarn: return slog.LevelWarn - case lx.LevelError: + case lx.LevelError, lx.LevelFatal: return slog.LevelError default: return slog.LevelInfo // Default for unknown levels diff --git a/vendor/github.com/olekukonko/ll/ll.go b/vendor/github.com/olekukonko/ll/ll.go index 7510b89aec..6505f8d2a9 100644 --- a/vendor/github.com/olekukonko/ll/ll.go +++ b/vendor/github.com/olekukonko/ll/ll.go @@ -39,6 +39,8 @@ type Logger struct { stackBufferSize int // Buffer size for capturing stack traces separator string // Separator for namespace paths (e.g., "/") entries atomic.Int64 // Tracks total log entries sent to handler + fatalExits bool + fatalStack bool } // New creates a new Logger with the given namespace and optional configurations. @@ -71,22 +73,71 @@ func New(namespace string, opts ...Option) *Logger { return logger } -// AddContext adds a key-value pair to the logger's context, modifying it directly. -// Unlike Context, it mutates the existing context. It is thread-safe using a write lock. +// Apply applies one or more functional options to the default/global logger. +// Useful for late configuration (e.g., after migration, attach VictoriaLogs handler, +// set level, add middleware, etc.) without changing existing New() calls. +// // Example: // -// logger := New("app").Enable() -// logger.AddContext("user", "alice") -// logger.Info("Action") // Output: [app] INFO: Action [user=alice] -func (l *Logger) AddContext(key string, value interface{}) *Logger { +// // In main() or init(), after setting up handler +// ll.Apply( +// ll.Handler(vlBatched), +// ll.Level(ll.LevelInfo), +// ll.Use(rateLimiterMiddleware), +// ) +// +// Returns the default logger for chaining (if needed). +func (l *Logger) Apply(opts ...Option) *Logger { l.mu.Lock() defer l.mu.Unlock() + for _, opt := range opts { + if opt != nil { + opt(l) + } + } + return l +} - // Initialize context map if nil +// AddContext adds one or more key-value pairs to the logger's persistent context. +// These fields will be included in **every** subsequent log message from this logger +// (and its child namespace loggers). +// +// It supports variadic key-value pairs (string key, any value). +// Non-string keys or uneven number of arguments will be safely ignored/logged. +// +// Returns the logger for chaining. +// +// Examples: +// +// logger.AddContext("user", "alice", "env", "prod") +// logger.AddContext("request_id", reqID, "trace_id", traceID) +// logger.AddContext("service", "payment") // single pair +func (l *Logger) AddContext(pairs ...any) *Logger { + l.mu.Lock() + defer l.mu.Unlock() + + // Lazy initialization of context map if l.context == nil { l.context = make(map[string]interface{}) } - l.context[key] = value + + // Process key-value pairs + for i := 0; i < len(pairs)-1; i += 2 { + key, ok := pairs[i].(string) + if !ok { + l.Warnf("AddContext: non-string key at index %d: %v", i, pairs[i]) + continue + } + + value := pairs[i+1] + l.context[key] = value + } + + // Optional: warn about uneven number of arguments + if len(pairs)%2 != 0 { + l.Warn("AddContext: uneven number of arguments, last value ignored") + } + return l } @@ -357,6 +408,7 @@ func (l *Logger) Output(values ...interface{}) { l.output(2, values...) } +// mark logs the caller's file and line number along with an optional custom name label for tracing execution flow. func (l *Logger) output(skip int, values ...interface{}) { if !l.shouldLog(lx.LevelInfo) { return @@ -536,8 +588,10 @@ func (l *Logger) Fatal(args ...any) { os.Exit(1) } - l.log(lx.LevelError, lx.ClassText, cat.Space(args...), nil, false) - os.Exit(1) + l.log(lx.LevelFatal, lx.ClassText, cat.Space(args...), nil, l.fatalStack) + if l.fatalExits { + os.Exit(1) + } } // Fatalf logs a formatted message at Error level with a stack trace and exits the program. @@ -795,6 +849,7 @@ func (l *Logger) Mark(name ...string) { l.mark(2, name...) } +// mark logs the caller's file and line number along with an optional custom name label for tracing execution flow. func (l *Logger) mark(skip int, names ...string) { // Skip logging if Info level is not enabled if !l.shouldLog(lx.LevelInfo) { @@ -978,7 +1033,7 @@ func (l *Logger) Panic(args ...any) { panic(msg) } - l.log(lx.LevelError, lx.ClassText, msg, nil, true) + l.log(lx.LevelFatal, lx.ClassText, msg, nil, true) panic(msg) } @@ -1459,54 +1514,3 @@ func (l *Logger) shouldLog(level lx.LevelType) bool { return true } - -// WithHandler sets the handler for the logger as a functional option for configuring -// a new logger instance. -// Example: -// -// logger := New("app", WithHandler(lh.NewJSONHandler(os.Stdout))) -func WithHandler(handler lx.Handler) Option { - return func(l *Logger) { - l.handler = handler - } -} - -// WithTimestamped returns an Option that configures timestamp settings for the logger's existing handler. -// It enables or disables timestamp logging and optionally sets the timestamp format if the handler -// supports the lx.Timestamper interface. If no handler is set, the function has no effect. -// Parameters: -// -// enable: Boolean to enable or disable timestamp logging -// format: Optional string(s) to specify the timestamp format -func WithTimestamped(enable bool, format ...string) Option { - return func(l *Logger) { - if l.handler != nil { // Check if a handler is set - // Verify if the handler supports the lx.Timestamper interface - if h, ok := l.handler.(lx.Timestamper); ok { - h.Timestamped(enable, format...) // Apply timestamp settings to the handler - } - } - } -} - -// WithLevel sets the minimum log level for the logger as a functional option for -// configuring a new logger instance. -// Example: -// -// logger := New("app", WithLevel(lx.LevelWarn)) -func WithLevel(level lx.LevelType) Option { - return func(l *Logger) { - l.level = level - } -} - -// WithStyle sets the namespace formatting style for the logger as a functional option -// for configuring a new logger instance. -// Example: -// -// logger := New("app", WithStyle(lx.NestedPath)) -func WithStyle(style lx.StyleType) Option { - return func(l *Logger) { - l.style = style - } -} diff --git a/vendor/github.com/olekukonko/ll/lx/lx.go b/vendor/github.com/olekukonko/ll/lx/lx.go index d370cb2d01..ded0e58b26 100644 --- a/vendor/github.com/olekukonko/ll/lx/lx.go +++ b/vendor/github.com/olekukonko/ll/lx/lx.go @@ -36,6 +36,7 @@ const ( LevelInfo // Info level for general operational messages LevelWarn // Warn level for warning conditions LevelError // Error level for error conditions requiring attention + LevelFatal // Fatal level for critical error conditions LevelDebug // None level for logs without a specific severity (e.g., raw output) LevelUnknown // None level for logs without a specific severity (e.g., raw output) ) @@ -45,7 +46,9 @@ const ( DebugString = "DEBUG" InfoString = "INFO" WarnString = "WARN" + WarningString = "WARNING" ErrorString = "ERROR" + FatalString = "FATAL" NoneString = "NONE" UnknownString = "UNKNOWN" @@ -98,6 +101,8 @@ func (l LevelType) String() string { return WarnString case LevelError: return ErrorString + case LevelFatal: + return FatalString case LevelNone: return NoneString default: @@ -114,7 +119,7 @@ func LevelParse(s string) LevelType { return LevelDebug case InfoString: return LevelInfo - case WarnString, "WARNING": // Allow both "WARN" and "WARNING" + case WarnString, WarningString: // Allow both "WARN" and "WARNING" return LevelWarn case ErrorString: return LevelError diff --git a/vendor/github.com/olekukonko/ll/options.go b/vendor/github.com/olekukonko/ll/options.go new file mode 100644 index 0000000000..50fa194422 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/options.go @@ -0,0 +1,67 @@ +package ll + +import "github.com/olekukonko/ll/lx" + +// WithHandler sets the handler for the logger as a functional option for configuring +// a new logger instance. +// Example: +// +// logger := New("app", WithHandler(lh.NewJSONHandler(os.Stdout))) +func WithHandler(handler lx.Handler) Option { + return func(l *Logger) { + l.handler = handler + } +} + +// WithTimestamped returns an Option that configures timestamp settings for the logger's existing handler. +// It enables or disables timestamp logging and optionally sets the timestamp format if the handler +// supports the lx.Timestamper interface. If no handler is set, the function has no effect. +// Parameters: +// +// enable: Boolean to enable or disable timestamp logging +// format: Optional string(s) to specify the timestamp format +func WithTimestamped(enable bool, format ...string) Option { + return func(l *Logger) { + if l.handler != nil { // Check if a handler is set + // Verify if the handler supports the lx.Timestamper interface + if h, ok := l.handler.(lx.Timestamper); ok { + h.Timestamped(enable, format...) // Apply timestamp settings to the handler + } + } + } +} + +// WithLevel sets the minimum log level for the logger as a functional option for +// configuring a new logger instance. +// Example: +// +// logger := New("app", WithLevel(lx.LevelWarn)) +func WithLevel(level lx.LevelType) Option { + return func(l *Logger) { + l.level = level + } +} + +// WithStyle sets the namespace formatting style for the logger as a functional option +// for configuring a new logger instance. +// Example: +// +// logger := New("app", WithStyle(lx.NestedPath)) +func WithStyle(style lx.StyleType) Option { + return func(l *Logger) { + l.style = style + } +} + +// Functional options (can be passed to New() or applied later) +func WithFatalExits(enabled bool) Option { + return func(l *Logger) { + l.fatalExits = enabled + } +} + +func WithFatalStack(enabled bool) Option { + return func(l *Logger) { + l.fatalStack = enabled + } +} diff --git a/vendor/github.com/olekukonko/tablewriter/README.md b/vendor/github.com/olekukonko/tablewriter/README.md index 3af9409f9a..d8334424c4 100644 --- a/vendor/github.com/olekukonko/tablewriter/README.md +++ b/vendor/github.com/olekukonko/tablewriter/README.md @@ -28,7 +28,7 @@ go get github.com/olekukonko/tablewriter@v0.0.5 #### Latest Version The latest stable version ```bash -go get github.com/olekukonko/tablewriter@v1.1.2 +go get github.com/olekukonko/tablewriter@v1.1.3 ``` **Warning:** Version `v1.0.0` contains missing functionality and should not be used. @@ -62,7 +62,7 @@ func main() { data := [][]string{ {"Package", "Version", "Status"}, {"tablewriter", "v0.0.5", "legacy"}, - {"tablewriter", "v1.1.2", "latest"}, + {"tablewriter", "v1.1.3", "latest"}, } table := tablewriter.NewWriter(os.Stdout) @@ -77,7 +77,7 @@ func main() { │ PACKAGE │ VERSION │ STATUS │ ├─────────────┼─────────┼────────┤ │ tablewriter │ v0.0.5 │ legacy │ -│ tablewriter │ v1.1.2 │ latest │ +│ tablewriter │ v1.1.3 │ latest │ └─────────────┴─────────┴────────┘ ``` diff --git a/vendor/github.com/olekukonko/tablewriter/pkg/twwidth/ea.go b/vendor/github.com/olekukonko/tablewriter/pkg/twwidth/ea.go new file mode 100644 index 0000000000..378e129faf --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/pkg/twwidth/ea.go @@ -0,0 +1,424 @@ +/* +Package twwidth provides intelligent East Asian width detection. + +In 2025/2026, most modern terminal emulators (VSCode, Windows Terminal, iTerm2, +Alacritty) and modern monospace fonts (Hack, Fira Code, Cascadia Code) treat +box-drawing characters as Single Width, regardless of the underlying OS Locale. + +Detection Logic (in order of priority): +- RUNEWIDTH_EASTASIAN environment variable (explicit user override) +- Force Legacy Mode (programmatic override for backward compatibility) +- Modern environment detection (VSCode, Windows Terminal, etc. -> Narrow) +- Locale-based detection (CJK locales in traditional terminals -> Wide) + +This prioritization ensures that: +- Users can always override behavior using RUNEWIDTH_EASTASIAN +- Modern development environments work correctly by default +- Traditional CJK terminals maintain compatibility via locale checks + +Examples: + + // Force narrow borders (for Hack font in zh_CN) + RUNEWIDTH_EASTASIAN=0 go run . + + // Force wide borders (for legacy CJK terminals) + RUNEWIDTH_EASTASIAN=1 go run . +*/ +package twwidth + +import ( + "os" + "runtime" + "strings" + "sync" +) + +// Environment Variable Constants +const ( + EnvLCAll = "LC_ALL" + EnvLCCtype = "LC_CTYPE" + EnvLang = "LANG" + EnvRuneWidthEastAsian = "RUNEWIDTH_EASTASIAN" + EnvTerm = "TERM" + EnvTermProgram = "TERM_PROGRAM" + EnvTermProgramWsl = "TERM_PROGRAM_WSL" + EnvWTProfile = "WT_PROFILE_ID" // Windows Terminal + EnvConEmuANSI = "ConEmuANSI" // ConEmu + EnvAlacritty = "ALACRITTY_LOG" // Alacritty + EnvVTEVersion = "VTE_VERSION" // GNOME/VTE +) + +const ( + overwriteOn = "override_on" + overwriteOff = "override_off" + + envModern = "modern_env" + envCjk = "locale_cjk" + envAscii = "default_ascii" +) + +// CJK Language Codes (Prefixes) +// Covers ISO 639-1 (2-letter) and common full names used in some systems. +var cjkPrefixes = []string{ + "zh", "ja", "ko", // Standard: Chinese, Japanese, Korean + "chi", "zho", // ISO 639-2/B and T for Chinese + "jpn", "kor", // ISO 639-2 for Japanese, Korean + "chinese", "japanese", "korean", // Full names (rare but possible in some legacy systems) +} + +// CJK Region Codes +// Checks for specific regions that imply CJK font usage (e.g., en_HK). +var cjkRegions = map[string]bool{ + "cn": true, // China + "tw": true, // Taiwan + "hk": true, // Hong Kong + "mo": true, // Macau + "jp": true, // Japan + "kr": true, // South Korea + "kp": true, // North Korea + "sg": true, // Singapore (Often uses CJK fonts) +} + +// Modern environments that should use narrow borders (1-width box chars) +var modernEnvironments = map[string]bool{ + // Terminal programs + "vscode": true, "visual studio code": true, + "iterm.app": true, "iterm2": true, + "windows terminal": true, "windowsterminal": true, + "alacritty": true, "kitty": true, + "hyper": true, "tabby": true, "terminus": true, "fluentterminal": true, + "warp": true, "ghostty": true, "rio": true, + "jetbrains-jediterm": true, + + // Terminal types (TERM signatures) + "xterm-kitty": true, "xterm-ghostty": true, "wezterm": true, +} + +var ( + eastAsianOnce sync.Once + eastAsianVal bool + + // Legacy override control + // Renamed to cfgMu to avoid conflict with width.go's mu + cfgMu sync.RWMutex + forceLegacyEastAsian = false +) + +type Enviroment struct { + GOOS string `json:"goos"` + LC_ALL string `json:"lc_all"` + LC_CTYPE string `json:"lc_ctype"` + LANG string `json:"lang"` + RUNEWIDTH_EASTASIAN string `json:"runewidth_eastasian"` + TERM string `json:"term"` + TERM_PROGRAM string `json:"term_program"` +} + +// State captures the calculated internal state. +type State struct { + NormalizedLocale string `json:"normalized_locale"` + IsCJKLocale bool `json:"is_cjk_locale"` + IsModernEnv bool `json:"is_modern_env"` + LegacyOverrideMode bool `json:"legacy_override_mode"` +} + +// Detection aggregates all debug information regarding East Asian width detection. +type Detection struct { + AutoUseEastAsian bool `json:"auto_use_east_asian"` + DetectionMode string `json:"detection_mode"` + Raw Enviroment `json:"raw"` + Derived State `json:"derived"` +} + +// EastAsianForceLegacy forces the detection logic to ignore modern environment checks. +// It relies solely on Locale detection. This is useful for applications that need +// strict backward compatibility. +// +// Note: This does NOT override RUNEWIDTH_EASTASIAN. User environment variables take precedence. +// This should be called before the first table render. +func EastAsianForceLegacy(force bool) { + cfgMu.Lock() + defer cfgMu.Unlock() + forceLegacyEastAsian = force +} + +// EastAsianDetect checks the environment variables to determine if +// East Asian width calculations should be enabled. +func EastAsianDetect() bool { + eastAsianOnce.Do(func() { + eastAsianVal = detectEastAsian() + }) + return eastAsianVal +} + +// EastAsianConservative is a stricter version that only defaults to Narrow +// if the terminal is definitely known to be modern (e.g. VSCode, iTerm2). +// It avoids heuristics like checking "xterm" in the TERM variable. +func EastAsianConservative() bool { + // Check overrides first + if val, found := checkOverrides(); found { + return val + } + + // Stricter modern environment detection + if isConservativeModernEnvironment() { + return false + } + + // Fall back to locale + return checkLocale() +} + +// EastAsianMode returns the decision path used for the current environment. +// Useful for debugging why a specific width was chosen. +func EastAsianMode() string { + // Check override + if val, found := checkOverrides(); found { + if val { + return overwriteOn + } + return overwriteOff + } + + cfgMu.RLock() + legacy := forceLegacyEastAsian + cfgMu.RUnlock() + + if legacy { + if checkLocale() { + return envCjk + } + return envAscii + } + + if isModernEnvironment() { + return envModern + } + + if checkLocale() { + return envCjk + } + + return envAscii +} + +// Debugging returns detailed information about the detection decision. +// Useful for users to include in Github issues. +func Debugging() Detection { + locale := getNormalizedLocale() + + cfgMu.RLock() + legacy := forceLegacyEastAsian + cfgMu.RUnlock() + + return Detection{ + AutoUseEastAsian: EastAsianDetect(), + DetectionMode: EastAsianMode(), + Raw: Enviroment{ + GOOS: runtime.GOOS, + LC_ALL: os.Getenv(EnvLCAll), + LC_CTYPE: os.Getenv(EnvLCCtype), + LANG: os.Getenv(EnvLang), + RUNEWIDTH_EASTASIAN: os.Getenv(EnvRuneWidthEastAsian), + TERM: os.Getenv(EnvTerm), + TERM_PROGRAM: os.Getenv(EnvTermProgram), + }, + Derived: State{ + NormalizedLocale: locale, + IsCJKLocale: isCJKLocale(locale), + IsModernEnv: isModernEnvironment(), + LegacyOverrideMode: legacy, + }, + } +} + +// detectEastAsian evaluates the environment and locale settings to determine if East Asian width rules should apply. +func detectEastAsian() bool { + // User Override check (Highest Priority) + if val, found := checkOverrides(); found { + return val + } + + // Force Legacy Mode check + cfgMu.RLock() + isLegacy := forceLegacyEastAsian + cfgMu.RUnlock() + + if isLegacy { + // Legacy mode ignores modern environment checks, + // relying solely on locale. + return checkLocale() + } + + // Modern Environment Detection + // If modern, we assume Single Width (return false) + if isModernEnvironment() { + return false + } + + // 4. Locale Fallback + return checkLocale() +} + +// checkOverrides looks for RUNEWIDTH_EASTASIAN +func checkOverrides() (bool, bool) { + if rw := os.Getenv(EnvRuneWidthEastAsian); rw != "" { + rw = strings.ToLower(rw) + if rw == "0" || rw == "off" || rw == "false" || rw == "no" { + return false, true + } + if rw == "1" || rw == "on" || rw == "true" || rw == "yes" { + return true, true + } + } + return false, false +} + +// checkLocale performs the string analysis on LANG/LC_ALL +func checkLocale() bool { + locale := getNormalizedLocale() + if locale == "" { + return false + } + return isCJKLocale(locale) +} + +// isModernEnvironment performs comprehensive checks for modern terminal capabilities. +func isModernEnvironment() bool { + // Check TERM_PROGRAM (Most reliable) + if termProg := os.Getenv(EnvTermProgram); termProg != "" { + termProgLower := strings.ToLower(termProg) + if modernEnvironments[termProgLower] { + return true + } + } + + // Check WSL specific variable + if os.Getenv(EnvTermProgramWsl) != "" { + return true + } + + // Windows Specifics + if runtime.GOOS == "windows" { + // Windows Terminal + if os.Getenv(EnvWTProfile) != "" { + return true + } + // ConEmu/Cmder + if os.Getenv(EnvConEmuANSI) == "ON" { + return true + } + // Modern Windows console (Windows 10+) check via TERM + if term := os.Getenv(EnvTerm); term != "" { + termLower := strings.ToLower(term) + if strings.Contains(termLower, "xterm") || + strings.Contains(termLower, "vt") { + return true + } + } + } + + // VTE-based terminals (GNOME Terminal, Tilix, etc.) + if os.Getenv(EnvVTEVersion) != "" { + return true + } + + // Check for Alacritty specifically + if os.Getenv(EnvAlacritty) != "" { + return true + } + + // Check TERM for modern terminal signatures + if term := os.Getenv(EnvTerm); term != "" { + termLower := strings.ToLower(term) + // Specific modern terminals often put their name in TERM + if modernEnvironments[termLower] { + return true + } + // Heuristics for standard modern-capable descriptors + if strings.Contains(termLower, "xterm") && !strings.Contains(termLower, "xterm-mono") { + return true + } + if strings.Contains(termLower, "screen") || + strings.Contains(termLower, "tmux") { + return true + } + } + + return false +} + +// isConservativeModernEnvironment performs strict checks only for known modern terminals. +func isConservativeModernEnvironment() bool { + termProg := strings.ToLower(os.Getenv(EnvTermProgram)) + + // Allow-list of definitely modern terminals + switch termProg { + case "vscode", "visual studio code": + return true + case "iterm.app", "iterm2": + return true + case "windows terminal", "windowsterminal": + return true + case "alacritty", "wezterm", "kitty", "ghostty": + return true + case "warp", "tabby", "hyper": + return true + } + + // Windows Terminal via specific Env + if os.Getenv(EnvWTProfile) != "" { + return true + } + + return false +} + +// isCJKLocale determines if a given locale string corresponds to a CJK (Chinese, Japanese, Korean) language or region. +func isCJKLocale(locale string) bool { + // Check Language Prefix + for _, prefix := range cjkPrefixes { + if strings.HasPrefix(locale, prefix) { + return true + } + } + + // Check Regions + parts := strings.Split(locale, "_") + if len(parts) > 1 { + for _, part := range parts[1:] { + if cjkRegions[part] { + return true + } + } + } + + return false +} + +// getNormalizedLocale returns the normalized locale by inspecting environment variables LC_ALL, LC_CTYPE, and LANG. +func getNormalizedLocale() string { + var locale string + if loc := os.Getenv(EnvLCAll); loc != "" { + locale = loc + } else if loc := os.Getenv(EnvLCCtype); loc != "" { + locale = loc + } else if loc := os.Getenv(EnvLang); loc != "" { + locale = loc + } + + // Fast fail for empty or standard C/POSIX locales + if locale == "" || locale == "C" || locale == "POSIX" { + return "" + } + + // Strip encoding and modifiers + if idx := strings.IndexByte(locale, '.'); idx != -1 { + locale = locale[:idx] + } + if idx := strings.IndexByte(locale, '@'); idx != -1 { + locale = locale[:idx] + } + + return strings.ToLower(locale) +} diff --git a/vendor/github.com/olekukonko/tablewriter/pkg/twwidth/width.go b/vendor/github.com/olekukonko/tablewriter/pkg/twwidth/width.go index 4afff74f82..1a7582c860 100644 --- a/vendor/github.com/olekukonko/tablewriter/pkg/twwidth/width.go +++ b/vendor/github.com/olekukonko/tablewriter/pkg/twwidth/width.go @@ -1,3 +1,4 @@ +// width.go package twwidth import ( @@ -21,6 +22,10 @@ const ( // Options allows for configuring width calculation on a per-call basis. type Options struct { EastAsianWidth bool + + // Explicitly force box drawing chars to be narrow + // regardless of EastAsianWidth setting. + ForceNarrowBorders bool } // globalOptions holds the global displaywidth configuration, including East Asian width settings. @@ -36,12 +41,25 @@ var widthCache *twcache.LRU[string, int] var ansi = Filter() func init() { - // Initialize global options by detecting from the environment, - // which is the one key feature we get from go-runewidth. + isEastAsian := EastAsianDetect() + cond := runewidth.NewCondition() + cond.EastAsianWidth = isEastAsian + globalOptions = Options{ - EastAsianWidth: cond.EastAsianWidth, + EastAsianWidth: isEastAsian, + + // Auto-enable ForceNarrowBorders for edge cases. + // If EastAsianWidth is ON (e.g. forced via Env Var), but we detect + // a modern environment, we might technically want to narrow borders + // while keeping text wide. + // + // Note: In the standard EastAsian logic, isEastAsian will + // ALREADY be false for modern environments, so this boolean implies + // a specific "Forced On" scenario. + ForceNarrowBorders: isEastAsian && isModernEnvironment(), } + widthCache = twcache.NewLRU[string, int](cacheCapacity) } @@ -55,6 +73,14 @@ func makeCacheKey(str string, eastAsianWidth bool) string { return cachePrefix + str } +// Display calculates the visual width of a string using a specific runewidth.Condition. +// Deprecated: use WidthWithOptions with the new twwidth.Options struct instead. +// This function is kept for backward compatibility. +func Display(cond *runewidth.Condition, str string) int { + opts := Options{EastAsianWidth: cond.EastAsianWidth} + return WidthWithOptions(str, opts) +} + // Filter compiles and returns a regular expression for matching ANSI escape sequences, // including CSI (Control Sequence Introducer) and OSC (Operating System Command) sequences. // The returned regex can be used to strip ANSI codes from strings. @@ -73,25 +99,15 @@ func Filter() *regexp.Regexp { return regexp.MustCompile("(" + regCSI + "|" + regOSC + ")") } -// SetOptions sets the global options for width calculation. -// This function is thread-safe. -func SetOptions(opts Options) { +// GetCacheStats returns current cache statistics +func GetCacheStats() (size, capacity int, hitRate float64) { mu.Lock() defer mu.Unlock() - if globalOptions.EastAsianWidth != opts.EastAsianWidth { - globalOptions = opts - widthCache.Purge() - } -} -// SetEastAsian enables or disables East Asian width handling globally. -// This function is thread-safe. -// -// Example: -// -// twdw.SetEastAsian(true) // Enable East Asian width handling -func SetEastAsian(enable bool) { - SetOptions(Options{EastAsianWidth: enable}) + if widthCache == nil { + return 0, 0, 0 + } + return widthCache.Len(), widthCache.Cap(), widthCache.HitRate() } // IsEastAsian returns the current East Asian width setting. @@ -108,6 +124,22 @@ func IsEastAsian() bool { return globalOptions.EastAsianWidth } +// SetCacheCapacity changes the cache size dynamically +// If capacity <= 0, disables caching entirely +func SetCacheCapacity(capacity int) { + mu.Lock() + defer mu.Unlock() + + if capacity <= 0 { + widthCache = nil // nil = fully disabled + return + } + + newCache := twcache.NewLRU[string, int](capacity) + widthCache = newCache +} + +// SetCondition sets the global East Asian width setting based on a runewidth.Condition. // Deprecated: use SetOptions with the new twwidth.Options struct instead. // This function is kept for backward compatibility. func SetCondition(cond *runewidth.Condition) { @@ -120,55 +152,33 @@ func SetCondition(cond *runewidth.Condition) { } } -// Width calculates the visual width of a string using the global cache for performance. -// It excludes ANSI escape sequences and accounts for the global East Asian width setting. +// SetEastAsian enables or disables East Asian width handling globally. // This function is thread-safe. // // Example: // -// width := twdw.Width("Hello\x1b[31mWorld") // Returns 10 -func Width(str string) int { - currentEA := IsEastAsian() - key := makeCacheKey(str, currentEA) - - if w, found := widthCache.Get(key); found { - return w - } - - opts := displaywidth.Options{EastAsianWidth: currentEA} - stripped := ansi.ReplaceAllLiteralString(str, "") - calculatedWidth := opts.String(stripped) - - widthCache.Add(key, calculatedWidth) - return calculatedWidth -} - -// WidthWithOptions calculates the visual width of a string with specific options, -// bypassing the global settings and cache. This is useful for one-shot calculations -// where global state is not desired. -func WidthWithOptions(str string, opts Options) int { - dwOpts := displaywidth.Options{EastAsianWidth: opts.EastAsianWidth} - stripped := ansi.ReplaceAllLiteralString(str, "") - return dwOpts.String(stripped) +// twdw.SetEastAsian(true) // Enable East Asian width handling +func SetEastAsian(enable bool) { + SetOptions(Options{EastAsianWidth: enable}) } -// WidthNoCache calculates the visual width of a string without using the global cache. -// -// Example: -// -// width := twdw.WidthNoCache("Hello\x1b[31mWorld") // Returns 10 -func WidthNoCache(str string) int { - // This function's behavior is equivalent to a one-shot calculation - // using the current global options. The WidthWithOptions function - // does not interact with the cache, thus fulfilling the requirement. - return WidthWithOptions(str, Options{EastAsianWidth: IsEastAsian()}) +// SetForceNarrow to preserve the new flag, or create a new setter +func SetForceNarrow(enable bool) { + mu.Lock() + defer mu.Unlock() + globalOptions.ForceNarrowBorders = enable + widthCache.Purge() // Clear cache because widths might change } -// Deprecated: use WidthWithOptions with the new twwidth.Options struct instead. -// This function is kept for backward compatibility. -func Display(cond *runewidth.Condition, str string) int { - opts := Options{EastAsianWidth: cond.EastAsianWidth} - return WidthWithOptions(str, opts) +// SetOptions sets the global options for width calculation. +// This function is thread-safe. +func SetOptions(opts Options) { + mu.Lock() + defer mu.Unlock() + if globalOptions.EastAsianWidth != opts.EastAsianWidth || globalOptions.ForceNarrowBorders != opts.ForceNarrowBorders { + globalOptions = opts + widthCache.Purge() + } } // Truncate shortens a string to fit within a specified visual width, optionally @@ -235,11 +245,13 @@ func Truncate(s string, maxWidth int, suffix ...string) string { // Case 4: String needs truncation (sDisplayWidth > maxWidth). // maxWidth is the total budget for the final string (content + suffix). - currentGlobalEastAsianWidth := IsEastAsian() + mu.Lock() + currentOpts := globalOptions + mu.Unlock() - // Special case for EastAsian true: if only suffix fits, return suffix. + // Special case for EastAsianDetect true: if only suffix fits, return suffix. // This was derived from previous test behavior. - if len(suffixStr) > 0 && currentGlobalEastAsianWidth { + if len(suffixStr) > 0 && currentOpts.EastAsianWidth { provisionalContentWidth := maxWidth - suffixDisplayWidth if provisionalContentWidth == 0 { // Exactly enough space for suffix only return suffixStr @@ -271,8 +283,6 @@ func Truncate(s string, maxWidth int, suffix ...string) string { inAnsiSequence := false ansiWrittenToContent := false - dwOpts := displaywidth.Options{EastAsianWidth: currentGlobalEastAsianWidth} - for _, r := range s { if r == '\x1b' { inAnsiSequence = true @@ -305,7 +315,7 @@ func Truncate(s string, maxWidth int, suffix ...string) string { ansiSeqBuf.Reset() } } else { // Normal character - runeDisplayWidth := dwOpts.Rune(r) + runeDisplayWidth := calculateRunewidth(r, currentOpts) if targetContentForIteration == 0 { // No budget for content at all break } @@ -342,28 +352,81 @@ func Truncate(s string, maxWidth int, suffix ...string) string { return result } -// SetCacheCapacity changes the cache size dynamically -// If capacity <= 0, disables caching entirely -func SetCacheCapacity(capacity int) { +// Width calculates the visual width of a string using the global cache for performance. +// It excludes ANSI escape sequences and accounts for the global East Asian width setting. +// This function is thread-safe. +// +// Example: +// +// width := twdw.Width("Hello\x1b[31mWorld") // Returns 10 +func Width(str string) int { + // Fast path ASCII (Optimization) + if len(str) == 1 && str[0] < 0x80 { + return 1 + } + mu.Lock() - defer mu.Unlock() + currentOpts := globalOptions + mu.Unlock() - if capacity <= 0 { - widthCache = nil // nil = fully disabled - return + key := makeCacheKey(str, currentOpts.EastAsianWidth) + + // Check Cache (Optimization) + if w, found := widthCache.Get(key); found { + return w } - newCache := twcache.NewLRU[string, int](capacity) - widthCache = newCache + stripped := ansi.ReplaceAllLiteralString(str, "") + calculatedWidth := 0 + + for _, r := range stripped { + calculatedWidth += calculateRunewidth(r, currentOpts) + } + + // Store in Cache + widthCache.Add(key, calculatedWidth) + return calculatedWidth } -// GetCacheStats returns current cache statistics -func GetCacheStats() (size, capacity int, hitRate float64) { +// WidthNoCache calculates the visual width of a string without using the global cache. +// +// Example: +// +// width := twdw.WidthNoCache("Hello\x1b[31mWorld") // Returns 10 +func WidthNoCache(str string) int { + // This function's behavior is equivalent to a one-shot calculation + // using the current global options. The WidthWithOptions function + // does not interact with the cache, thus fulfilling the requirement. mu.Lock() - defer mu.Unlock() + opts := globalOptions + mu.Unlock() + return WidthWithOptions(str, opts) +} - if widthCache == nil { - return 0, 0, 0 +// WidthWithOptions calculates the visual width of a string with specific options, +// bypassing the global settings and cache. This is useful for one-shot calculations +// where global state is not desired. +func WidthWithOptions(str string, opts Options) int { + stripped := ansi.ReplaceAllLiteralString(str, "") + calculatedWidth := 0 + for _, r := range stripped { + calculatedWidth += calculateRunewidth(r, opts) } - return widthCache.Len(), widthCache.Cap(), widthCache.HitRate() + return calculatedWidth +} + +// calculateRunewidth calculates the width of a single rune based on the provided options. +// It applies narrow overrides for box drawing characters if configured. +func calculateRunewidth(r rune, opts Options) int { + if opts.ForceNarrowBorders && isBoxDrawingChar(r) { + return 1 + } + + dwOpts := displaywidth.Options{EastAsianWidth: opts.EastAsianWidth} + return dwOpts.Rune(r) +} + +// isBoxDrawingChar checks if a rune is within the Unicode Box Drawing range. +func isBoxDrawingChar(r rune) bool { + return r >= 0x2500 && r <= 0x257F } diff --git a/vendor/github.com/olekukonko/tablewriter/renderer/colorized.go b/vendor/github.com/olekukonko/tablewriter/renderer/colorized.go index 9bee749312..1a0d87da14 100644 --- a/vendor/github.com/olekukonko/tablewriter/renderer/colorized.go +++ b/vendor/github.com/olekukonko/tablewriter/renderer/colorized.go @@ -4,7 +4,6 @@ import ( "io" "strings" - "github.com/fatih/color" "github.com/olekukonko/ll" "github.com/olekukonko/ll/lh" "github.com/olekukonko/tablewriter/pkg/twwidth" @@ -24,28 +23,6 @@ type ColorizedConfig struct { Symbols tw.Symbols // Symbols for table drawing (e.g., corners, lines) } -// Colors is a slice of color attributes for use with fatih/color, such as color.FgWhite or color.Bold. -type Colors []color.Attribute - -// Tint defines foreground and background color settings for table elements, with optional per-column overrides. -type Tint struct { - FG Colors // Foreground color attributes - BG Colors // Background color attributes - Columns []Tint // Per-column color settings -} - -// Apply applies the Tint's foreground and background colors to the given text, returning the text unchanged if no colors are set. -func (t Tint) Apply(text string) string { - if len(t.FG) == 0 && len(t.BG) == 0 { - return text - } - // Combine foreground and background colors - combinedColors := append(t.FG, t.BG...) - // Create a color function and apply it to the text - c := color.New(combinedColors...).SprintFunc() - return c(text) -} - // Colorized renders colored ASCII tables with customizable borders, colors, and alignments. type Colorized struct { config ColorizedConfig // Renderer configuration diff --git a/vendor/github.com/olekukonko/tablewriter/renderer/tint.go b/vendor/github.com/olekukonko/tablewriter/renderer/tint.go new file mode 100644 index 0000000000..4090a0f639 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/renderer/tint.go @@ -0,0 +1,25 @@ +package renderer + +import "github.com/fatih/color" + +// Colors is a slice of color attributes for use with fatih/color, such as color.FgWhite or color.Bold. +type Colors []color.Attribute + +// Tint defines foreground and background color settings for table elements, with optional per-column overrides. +type Tint struct { + FG Colors // Foreground color attributes + BG Colors // Background color attributes + Columns []Tint // Per-column color settings +} + +// Apply applies the Tint's foreground and background colors to the given text, returning the text unchanged if no colors are set. +func (t Tint) Apply(text string) string { + if len(t.FG) == 0 && len(t.BG) == 0 { + return text + } + // Combine foreground and background colors + combinedColors := append(t.FG, t.BG...) + // Create a color function and apply it to the text + c := color.New(combinedColors...).SprintFunc() + return c(text) +} diff --git a/vendor/github.com/olekukonko/tablewriter/tablewriter.go b/vendor/github.com/olekukonko/tablewriter/tablewriter.go index 464324a1d9..1cea0b94ba 100644 --- a/vendor/github.com/olekukonko/tablewriter/tablewriter.go +++ b/vendor/github.com/olekukonko/tablewriter/tablewriter.go @@ -4,7 +4,6 @@ import ( "bytes" "io" "math" - "os" "reflect" "runtime" "strings" @@ -419,7 +418,6 @@ func (t *Table) Options(opts ...Option) *Table { } // force debugging mode if set - // This should be move away form WithDebug if t.config.Debug { t.logger.Enable() t.logger.Resume() @@ -434,11 +432,28 @@ func (t *Table) Options(opts ...Option) *Table { goArch := runtime.GOARCH numCPU := runtime.NumCPU() - t.logger.Infof("Environment: LC_CTYPE=%s, LANG=%s, TERM=%s", os.Getenv("LC_CTYPE"), os.Getenv("LANG"), os.Getenv("TERM")) - t.logger.Infof("Go Runtime: Version=%s, OS=%s, Arch=%s, CPUs=%d", goVersion, goOS, goArch, numCPU) + // Use the new struct-based info. + // No type assertions or magic strings needed. + info := twwidth.Debugging() + + t.logger.Infof("Go Runtime: Version=%s, OS=%s, Arch=%s, CPUs=%d", + goVersion, goOS, goArch, numCPU) + + t.logger.Infof("Environment: LC_CTYPE=%s, LANG=%s, TERM=%s, TERM_PROGRAM=%s", + info.Raw.LC_CTYPE, + info.Raw.LANG, + info.Raw.TERM, + info.Raw.TERM_PROGRAM, + ) + + t.logger.Infof("East Asian Detection: Auto=%v, Mode=%s, ModernEnv=%v, CJKLocale=%v", + info.AutoUseEastAsian, + info.DetectionMode, + info.Derived.IsModernEnv, + info.Derived.IsCJKLocale, + ) // send logger to renderer - // this will overwrite the default logger t.renderer.Logger(t.logger) return t } diff --git a/vendor/github.com/olekukonko/tablewriter/zoo.go b/vendor/github.com/olekukonko/tablewriter/zoo.go index b11c4b79b7..c24a53d1d5 100644 --- a/vendor/github.com/olekukonko/tablewriter/zoo.go +++ b/vendor/github.com/olekukonko/tablewriter/zoo.go @@ -991,7 +991,7 @@ func (t *Table) calculateContentMaxWidth(colIdx int, config tw.CellConfig, padLe constraintTotalCellWidth := 0 hasConstraint := false - // 1. Check new Widths.PerColumn (highest priority) + // Check new Widths.PerColumn (highest priority) if t.config.Widths.Constrained() { if colWidth, ok := t.config.Widths.PerColumn.OK(colIdx); ok && colWidth > 0 { @@ -1001,7 +1001,7 @@ func (t *Table) calculateContentMaxWidth(colIdx int, config tw.CellConfig, padLe colIdx, constraintTotalCellWidth) } - // 2. Check new Widths.Global + // Check new Widths.Global if !hasConstraint && t.config.Widths.Global > 0 { constraintTotalCellWidth = t.config.Widths.Global hasConstraint = true @@ -1009,7 +1009,7 @@ func (t *Table) calculateContentMaxWidth(colIdx int, config tw.CellConfig, padLe } } - // 3. Fall back to legacy ColMaxWidths.PerColumn (backward compatibility) + // Fall back to legacy ColMaxWidths.PerColumn (backward compatibility) if !hasConstraint && config.ColMaxWidths.PerColumn != nil { if colMax, ok := config.ColMaxWidths.PerColumn.OK(colIdx); ok && colMax > 0 { constraintTotalCellWidth = colMax @@ -1019,7 +1019,7 @@ func (t *Table) calculateContentMaxWidth(colIdx int, config tw.CellConfig, padLe } } - // 4. Fall back to legacy ColMaxWidths.Global + // Fall back to legacy ColMaxWidths.Global if !hasConstraint && config.ColMaxWidths.Global > 0 { constraintTotalCellWidth = config.ColMaxWidths.Global hasConstraint = true @@ -1027,7 +1027,7 @@ func (t *Table) calculateContentMaxWidth(colIdx int, config tw.CellConfig, padLe constraintTotalCellWidth) } - // 5. Fall back to table MaxWidth if auto-wrapping + // Fall back to table MaxWidth if auto-wrapping if !hasConstraint && t.config.MaxWidth > 0 && config.Formatting.AutoWrap != tw.WrapNone { constraintTotalCellWidth = t.config.MaxWidth hasConstraint = true @@ -1217,14 +1217,10 @@ func (t *Table) convertToString(value interface{}) string { // convertItemToCells is responsible for converting a single input item (which could be // a struct, a basic type, or an item implementing Stringer/Formatter) into a slice // of strings, where each string represents a cell for the table row. -// zoo.go - -// convertItemToCells is responsible for converting a single input item into a slice of strings. -// It now uses the unified struct parser for structs. func (t *Table) convertItemToCells(item interface{}) ([]string, error) { t.logger.Debugf("convertItemToCells: Converting item of type %T", item) - // 1. User-defined table-wide stringer (t.stringer) takes highest precedence. + // User-defined table-wide stringer (t.stringer) takes highest precedence. if t.stringer != nil { res, err := t.convertToStringer(item) if err == nil { @@ -1234,13 +1230,13 @@ func (t *Table) convertItemToCells(item interface{}) ([]string, error) { t.logger.Warnf("convertItemToCells: Custom table stringer was set but incompatible for type %T: %v. Will attempt other methods.", item, err) } - // 2. Handle untyped nil directly. + // Handle untyped nil directly. if item == nil { t.logger.Debugf("convertItemToCells: Item is untyped nil. Returning single empty cell.") return []string{""}, nil } - // 3. Use the new unified struct parser. It handles pointers and embedding. + // Use the new unified struct parser. It handles pointers and embedding. // We only care about the values it returns. _, values := t.extractFieldsAndValuesFromStruct(item) if values != nil { @@ -1248,7 +1244,7 @@ func (t *Table) convertItemToCells(item interface{}) ([]string, error) { return values, nil } - // 4. Fallback for any other single item (e.g., basic types, or types that implement Stringer/Formatter). + // Fallback for any other single item (e.g., basic types, or types that implement Stringer/Formatter). // This code path is now for non-struct types. if formatter, ok := item.(tw.Formatter); ok { t.logger.Debugf("convertItemToCells: Item (non-struct, type %T) is tw.Formatter. Using Format().", item) diff --git a/vendor/modules.txt b/vendor/modules.txt index 8fb02d1745..20247ef13c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -255,7 +255,7 @@ github.com/cespare/xxhash/v2 # github.com/cevaris/ordered_map v0.0.0-20190319150403-3adeae072e73 ## explicit github.com/cevaris/ordered_map -# github.com/clipperhouse/displaywidth v0.6.0 +# github.com/clipperhouse/displaywidth v0.6.2 ## explicit; go 1.18 github.com/clipperhouse/displaywidth # github.com/clipperhouse/stringish v0.1.1 @@ -1197,12 +1197,12 @@ github.com/olekukonko/cat # github.com/olekukonko/errors v1.1.0 ## explicit; go 1.21 github.com/olekukonko/errors -# github.com/olekukonko/ll v0.1.3 +# github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0 ## explicit; go 1.21 github.com/olekukonko/ll github.com/olekukonko/ll/lh github.com/olekukonko/ll/lx -# github.com/olekukonko/tablewriter v1.1.2 +# github.com/olekukonko/tablewriter v1.1.3 ## explicit; go 1.21 github.com/olekukonko/tablewriter github.com/olekukonko/tablewriter/pkg/twcache