New upstream release.
Debian Janitor
1 year, 4 months ago
132 | 132 | - [`FirstSentence`](https://pkg.go.dev/github.com/rivo/uniseg#FirstSentence) or [`FirstSentenceInString`](https://pkg.go.dev/github.com/rivo/uniseg#FirstSentenceInString) for sentence segmentation only, and |
133 | 133 | - [`FirstLineSegment`](https://pkg.go.dev/github.com/rivo/uniseg#FirstLineSegment) or [`FirstLineSegmentInString`](https://pkg.go.dev/github.com/rivo/uniseg#FirstLineSegmentInString) for line breaking / word wrapping (although using [`Step`](https://pkg.go.dev/github.com/rivo/uniseg#Step) or [`StepString`](https://pkg.go.dev/github.com/rivo/uniseg#StepString) is preferred as it will observe grapheme cluster boundaries). |
134 | 134 | |
135 | Finally, if you need to reverse a string while preserving grapheme clusters, use [`ReverseString`](https://pkg.go.dev/github.com/rivo/uniseg#ReverseString): | |
136 | ||
137 | ```go | |
138 | fmt.Println(uniseg.ReverseString("π©πͺπ³οΈβπ")) | |
139 | // π³οΈβππ©πͺ | |
140 | ``` | |
141 | ||
135 | 142 | ## Documentation |
136 | 143 | |
137 | 144 | Refer to https://pkg.go.dev/github.com/rivo/uniseg for the package's documentation. |
0 | golang-github-rivo-uniseg (0.4.3-1) UNRELEASED; urgency=low | |
1 | ||
2 | * New upstream release. | |
3 | ||
4 | -- Debian Janitor <janitor@jelmer.uk> Sun, 01 Jan 2023 04:19:43 -0000 | |
5 | ||
0 | 6 | golang-github-rivo-uniseg (0.4.2-1) unstable; urgency=medium |
1 | 7 | |
2 | 8 | * New upstream release |
69 | 69 | Monospace width, as referred to in this package, is the width of a string in a |
70 | 70 | monospace font. This is commonly used in terminal user interfaces or text |
71 | 71 | displays or editors that don't support proportional fonts. A width of 1 |
72 | corresponds to a single character cell. The C function [wcwidth()] and its | |
72 | corresponds to a single character cell. The C function [wcswidth()] and its | |
73 | 73 | implementation in other programming languages is in widespread use for the same |
74 | 74 | purpose. However, there is no standard for the calculation of such widths, and |
75 | this package differs from wcwidth() in a number of ways, presumably to generate | |
75 | this package differs from wcswidth() in a number of ways, presumably to generate | |
76 | 76 | more visually pleasing results. |
77 | 77 | |
78 | 78 | To start, we assume that every code point has a width of 1, with the following |
102 | 102 | render engine, to which extent it conforms to the Unicode Standard, and its |
103 | 103 | choice of font. |
104 | 104 | |
105 | [wcwidth()]: https://man7.org/linux/man-pages/man3/wcwidth.3.html | |
105 | [wcswidth()]: https://man7.org/linux/man-pages/man3/wcswidth.3.html | |
106 | 106 | */ |
107 | 107 | package uniseg |
162 | 162 | return |
163 | 163 | } |
164 | 164 | |
165 | // ReverseString reverses the given string while observing grapheme cluster | |
166 | // boundaries. | |
167 | func ReverseString(s string) string { | |
168 | str := []byte(s) | |
169 | reversed := make([]byte, len(str)) | |
170 | state := -1 | |
171 | index := len(str) | |
172 | for len(str) > 0 { | |
173 | var cluster []byte | |
174 | cluster, str, _, state = FirstGraphemeCluster(str, state) | |
175 | index -= len(cluster) | |
176 | copy(reversed[index:], cluster) | |
177 | if index <= len(str)/2 { | |
178 | break | |
179 | } | |
180 | } | |
181 | return string(reversed) | |
182 | } | |
183 | ||
165 | 184 | // The number of bits the grapheme property must be shifted to make place for |
166 | 185 | // grapheme states. |
167 | 186 | const shiftGraphemePropState = 4 |
335 | 335 | } |
336 | 336 | } |
337 | 337 | |
338 | // Test the ReverseString function. | |
339 | func TestReverseString(t *testing.T) { | |
340 | for _, testCase := range testCases { | |
341 | var r []rune | |
342 | for index := len(testCase.expected) - 1; index >= 0; index-- { | |
343 | r = append(r, testCase.expected[index]...) | |
344 | } | |
345 | if string(r) != ReverseString(testCase.original) { | |
346 | t.Errorf(`Exepected reverse of %q to be %q, got %q`, testCase.original, string(r), ReverseString(testCase.original)) | |
347 | } | |
348 | } | |
349 | ||
350 | // Three additional ones, for good measure. | |
351 | if ReverseString("π©πͺπ³οΈβπ") != "π³οΈβππ©πͺ" { | |
352 | t.Error("Flags weren't reversed correctly") | |
353 | } | |
354 | if ReverseString("π³οΈβπ") != "π³οΈβπ" { | |
355 | t.Error("Flag wasn't reversed correctly") | |
356 | } | |
357 | if ReverseString("") != "" { | |
358 | t.Error("Empty string wasn't reversed correctly") | |
359 | } | |
360 | } | |
361 | ||
338 | 362 | // Run all lists of test cases using the Graphemes function for byte slices. |
339 | 363 | func TestGraphemesFunctionBytes(t *testing.T) { |
340 | 364 | allCases := append(testCases, graphemeBreakTestCases...) |
0 | 0 | package uniseg |
1 | 1 | |
2 | import "testing" | |
2 | import ( | |
3 | "testing" | |
4 | ) | |
3 | 5 | |
4 | 6 | // widthTestCases is a list of test cases for the calculation of string widths. |
5 | 7 | var widthTestCases = []struct { |
326 | 328 | {"\U0001f3f3\ufe0f\u200d\U0001f308", 2}, // Rainbow flag |
327 | 329 | {"\U0001f1e9\U0001f1ea", 2}, // German flag |
328 | 330 | {"\u0916\u093e", 2}, // ΰ€ΰ€Ύ (Hindi, "eat") |
331 | {"\u0915\u0948\u0938\u0947", 2}, // ΰ€ΰ₯ΰ€Έΰ₯ (Hindi, "how") | |
329 | 332 | {"\U0001f468\u200d\U0001f469\u200d\U0001f467\u200d\U0001f466", 2}, // Family: Man, Woman, Girl, Boy |
330 | 333 | {"\u1112\u116f\u11b6", 2}, // αα ―αΆ (Hangul, conjoining Jamo, "h+weo+lh") |
331 | 334 | {"\ud6ef", 2}, // ν― (Hangul, precomposed, "h+weo+lh") |
427 | 430 | } |
428 | 431 | } |
429 | 432 | } |
433 | ||
434 | func TestRunesWidth(t *testing.T) { | |
435 | tc := []struct { | |
436 | name string | |
437 | raw string | |
438 | width int | |
439 | }{ | |
440 | {"latin ", "long", 4}, | |
441 | {"chinese ", "δΈε½", 4}, | |
442 | {"combining", "shangha\u0308\u0308i", 8}, | |
443 | { | |
444 | "emoji 1", "π", | |
445 | 1, | |
446 | }, | |
447 | { | |
448 | "emoji 2", "π»", | |
449 | 2, | |
450 | }, | |
451 | { | |
452 | "emoji 3", "π", | |
453 | 1, | |
454 | }, | |
455 | { | |
456 | "flags", "π³π±π§π·i", | |
457 | 5, | |
458 | }, | |
459 | { | |
460 | "flag 2", "π¨π³", | |
461 | 2, | |
462 | }, | |
463 | } | |
464 | ||
465 | for _, v := range tc { | |
466 | graphemes := NewGraphemes(v.raw) | |
467 | width := 0 | |
468 | var rs []rune | |
469 | for graphemes.Next() { | |
470 | rs = graphemes.Runes() | |
471 | width += StringWidth(string(rs)) | |
472 | } | |
473 | ||
474 | if v.width != width { | |
475 | t.Logf("%s :\t %q %U\n", v.name, v.raw, rs) | |
476 | t.Errorf("%s:\t %q expect width %d, got %d\n", v.name, v.raw, v.width, width) | |
477 | } | |
478 | } | |
479 | } |