mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-13 08:26:56 +00:00
Get basic full string width tests running
This commit is contained in:
parent
cf6bb29ef7
commit
3a4d32b85b
4 changed files with 137 additions and 11 deletions
15
embeds.go
15
embeds.go
|
|
@ -2,10 +2,23 @@ package kitty
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
|
||||
//go:embed kitty_tests/GraphemeBreakTest.json
|
||||
var GraphemeBreakTestData []byte
|
||||
var grapheme_break_test_data []byte
|
||||
|
||||
type GraphemeBreakTest struct {
|
||||
Data []string `json:"data"`
|
||||
Comment string `json:"comment"`
|
||||
}
|
||||
|
||||
func LoadGraphemeBreakTests() (ans []GraphemeBreakTest, err error) {
|
||||
if err := json.Unmarshal(grapheme_break_test_data, &ans); err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse GraphemeBreakTest JSON with error: %s", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,130 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"kitty"
|
||||
"kitty/tools/tui/loop"
|
||||
"kitty/tools/utils"
|
||||
"kitty/tools/wcswidth"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
|
||||
type test_struct struct {
|
||||
description string
|
||||
expected_cursor_positions []int
|
||||
actual_cursor_positions []int
|
||||
payload string
|
||||
}
|
||||
|
||||
const cursor_position_report = "\x1b[6n"
|
||||
|
||||
func run_tests(tests []*test_struct) (err error) {
|
||||
lp, err := loop.New(loop.NoAlternateScreen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf := strings.Builder{}
|
||||
buf.WriteString(loop.PENDING_UPDATE.EscapeCodeToSet())
|
||||
for _, t := range tests {
|
||||
buf.WriteString(t.payload)
|
||||
buf.WriteString("\r\x1b[K")
|
||||
if buf.Len() > 512*1024 {
|
||||
buf.WriteString(loop.PENDING_UPDATE.EscapeCodeToReset())
|
||||
buf.WriteString(loop.PENDING_UPDATE.EscapeCodeToSet())
|
||||
}
|
||||
}
|
||||
buf.WriteString(loop.PENDING_UPDATE.EscapeCodeToReset())
|
||||
buf.WriteString("\x1b[c")
|
||||
|
||||
lp.OnInitialize = func() (string, error) {
|
||||
lp.SetCursorVisible(false)
|
||||
lp.Printf("Running %d tests, please wait...\n", len(tests))
|
||||
lp.QueueWriteString(buf.String())
|
||||
return "", err
|
||||
}
|
||||
lp.OnFinalize = func() string {
|
||||
lp.SetCursorVisible(true)
|
||||
return ""
|
||||
}
|
||||
current_test_idx := 0
|
||||
lp.OnEscapeCode = func(typ loop.EscapeCodeType, data []byte) error {
|
||||
if typ == loop.CSI {
|
||||
switch data[len(data)-1] {
|
||||
case 'c':
|
||||
lp.Quit(0)
|
||||
case 'R':
|
||||
if idx := bytes.IndexByte(data, ';'); idx > -1 {
|
||||
if xpos, e := strconv.Atoi(utils.UnsafeBytesToString(data[idx+1 : len(data)-1])); e == nil {
|
||||
t := tests[current_test_idx]
|
||||
if len(t.actual_cursor_positions) >= len(t.expected_cursor_positions) && current_test_idx+1 < len(tests) {
|
||||
current_test_idx += 1
|
||||
t = tests[current_test_idx]
|
||||
}
|
||||
t.actual_cursor_positions = append(t.actual_cursor_positions, xpos-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err = lp.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return show_results(tests)
|
||||
}
|
||||
|
||||
func show_results(tests []*test_struct) (err error) {
|
||||
num_failures := 0
|
||||
for _, t := range tests {
|
||||
if diff := cmp.Diff(t.expected_cursor_positions, t.actual_cursor_positions); diff != "" {
|
||||
fmt.Println("\x1b[31mTest failed\x1b[39m:", t.description)
|
||||
fmt.Println(diff)
|
||||
num_failures++
|
||||
}
|
||||
}
|
||||
if num_failures > 0 {
|
||||
err = fmt.Errorf("%d out of %d tests failed.", num_failures, len(tests))
|
||||
} else {
|
||||
fmt.Printf("All %d tests passed!\n", len(tests))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func has_control_chars(text string) bool {
|
||||
for _, ch := range text {
|
||||
if ch < ' ' {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func main() (rc int, err error) {
|
||||
var tests []*test_struct
|
||||
if gb_tests, err := kitty.LoadGraphemeBreakTests(); err == nil {
|
||||
for i, t := range gb_tests {
|
||||
desc := fmt.Sprintf("Unicode GraphemeBreakTest: #%d (%s)", i, t.Comment)
|
||||
text := strings.Join(t.Data, "")
|
||||
if has_control_chars(text) {
|
||||
continue
|
||||
}
|
||||
payload := " " + text + cursor_position_report
|
||||
test := test_struct{description: desc, payload: payload, expected_cursor_positions: []int{1 + wcswidth.Stringwidth(text)}}
|
||||
tests = append(tests, &test)
|
||||
}
|
||||
if err = run_tests(tests); err != nil {
|
||||
return 1, err
|
||||
}
|
||||
} else {
|
||||
return 1, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ func KeyEventFromCSI(csi string) *KeyEvent {
|
|||
}
|
||||
orig_csi := csi
|
||||
last_char := csi[len(csi)-1:]
|
||||
if !strings.Contains("u~ABCDEHFPQRS", last_char) || (last_char == "~" && (csi == "200~" || csi == "201~")) {
|
||||
if !strings.Contains("u~ABCDEHFPQS", last_char) || (last_char == "~" && (csi == "200~" || csi == "201~")) {
|
||||
return nil
|
||||
}
|
||||
csi = csi[:len(csi)-1]
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
package wcswidth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
_ "embed"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"kitty"
|
||||
|
|
@ -14,11 +14,6 @@ import (
|
|||
|
||||
var _ = fmt.Print
|
||||
|
||||
type GraphemeBreakTest struct {
|
||||
Data []string `json:"data"`
|
||||
Comment string `json:"comment"`
|
||||
}
|
||||
|
||||
func TestSplitIntoGraphemes(t *testing.T) {
|
||||
var m = map[string][]string{
|
||||
" \u0308 ": {" \u0308", " "},
|
||||
|
|
@ -29,9 +24,9 @@ func TestSplitIntoGraphemes(t *testing.T) {
|
|||
t.Fatalf("Failed to split %#v into graphemes: %s", text, diff)
|
||||
}
|
||||
}
|
||||
tests := []GraphemeBreakTest{}
|
||||
if err := json.Unmarshal(kitty.GraphemeBreakTestData, &tests); err != nil {
|
||||
t.Fatalf("Failed to parse GraphemeBreakTest JSON with error: %s", err)
|
||||
tests, err := kitty.LoadGraphemeBreakTests()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, x := range tests {
|
||||
text := strings.Join(x.Data, "")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue