File: truncate.go

package info (click to toggle)
glab 1.53.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,936 kB
  • sloc: sh: 295; makefile: 153; perl: 99; ruby: 68; javascript: 67
file content (74 lines) | stat: -rw-r--r-- 1,886 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package text

import "bytes"

// Truncate resizes the string with the given length. It ellipses with '...' when the string's length exceeds
// the desired length or pads spaces to the right of the string when length is smaller than desired
func Truncate(s string, length int) string {
	slen := StringWidth(s)
	n := length
	if slen == n {
		return s
	}
	// Pads only when length of the string smaller than len needed
	s = PadRight(s, n, ' ')

	if slen > n {
		buf := bytes.Buffer{}
		w := 0
		dotsWritten := 0

		hyperlinkMatches := hyperlinkOSCRegexp.FindAllStringIndex(s, -1)

		// append a faked match so that we always have something in
		// hyperlinkMatches[0] and can avoid nil checks
		hyperlinkMatches = append(hyperlinkMatches, []int{len(s), len(s)})

		for i, r := range s {
			startPos := hyperlinkMatches[0][0]
			endPos := hyperlinkMatches[0][1]

			if i >= startPos && i < endPos {
				// write runes inside hyperlink OSC sequences - this doesn't count
				// against our grapheme total
				buf.WriteRune(r)
			} else if w == 0 {
				// always write the first character
				buf.WriteRune(r)
				w += RuneWidth(r)
			} else {
				rw := RuneWidth(r)

				if w+rw <= n-3 {
					// if we have room before the ellipsis, go ahead and write it
					buf.WriteRune(r)
					w += rw
				} else if dotsWritten < 3 {
					buf.WriteRune('.')
					w++
					dotsWritten++
				} else {
					break
				}
			}

			if i == endPos-1 {
				// we're at the end of this hyperlink OSC sequence - get ready
				// to check for the next one
				hyperlinkMatches = hyperlinkMatches[1:]
			}
		}

		// if we currently have an "open" hyperlink OSC sequence, we need to write
		// a closing sequence
		nextOSC := s[hyperlinkMatches[0][0]:hyperlinkMatches[0][1]]
		isNextOSCClosing := nextOSC == "\x1b]8;;\x1b\\"

		if isNextOSCClosing {
			buf.WriteString(nextOSC)
		}

		s = buf.String()
	}
	return s
}