podman

Форк
0
176 строк · 3.3 Кб
1
package goterm
2

3
import (
4
	"bytes"
5
	"regexp"
6
	"strings"
7
	_ "unicode/utf8"
8
)
9

10
const DEFAULT_BORDER = "- │ ┌ ┐ └ ┘"
11

12
// Box allows you to create independent parts of screen, with its own buffer and borders.
13
// Can be used for creating modal windows
14
//
15
// Generates boxes likes this:
16
// ┌--------┐
17
// │hello   │
18
// │world   │
19
// │        │
20
// └--------┘
21
//
22
type Box struct {
23
	Buf *bytes.Buffer
24

25
	Width  int
26
	Height int
27

28
	// To get even padding: PaddingX ~= PaddingY*4
29
	PaddingX int
30
	PaddingY int
31

32
	// Should contain 6 border pieces separated by spaces
33
	//
34
	// Example border:
35
	//   "- │ ┌ ┐ └ ┘"
36
	Border string
37

38
	Flags int // Not used now
39
}
40

41
// Create new Box.
42
// Width and height can be relative:
43
//
44
//    // Create box with 50% with of current screen and 10 lines height
45
//    box := tm.NewBox(50|tm.PCT, 10, 0)
46
//
47
func NewBox(width, height int, flags int) *Box {
48
	width, height = GetXY(width, height)
49

50
	box := new(Box)
51
	box.Buf = new(bytes.Buffer)
52
	box.Width = width
53
	box.Height = height
54
	box.Border = DEFAULT_BORDER
55
	box.PaddingX = 1
56
	box.PaddingY = 0
57
	box.Flags = flags
58

59
	return box
60
}
61

62
func (b *Box) Write(p []byte) (int, error) {
63
	return b.Buf.Write(p)
64
}
65

66
var ANSI_RE = regexp.MustCompile(`\\0\d+\[\d+(?:;\d+)?m`)
67

68
// String renders Box
69
func (b *Box) String() (out string) {
70
	borders := strings.Split(b.Border, " ")
71
	lines := strings.Split(b.Buf.String(), "\n")
72

73
	// Border + padding
74
	prefix := borders[1] + strings.Repeat(" ", b.PaddingX)
75
	suffix := strings.Repeat(" ", b.PaddingX) + borders[1]
76

77
	offset := b.PaddingY + 1 // 1 is border width
78

79
	// Content width without borders and padding
80
	contentWidth := b.Width - (b.PaddingX+1)*2
81
	for y := 0; y < b.Height; y++ {
82
		var line string
83

84
		switch {
85
		// Draw borders for first line
86
		case y == 0:
87
			line = borders[2] + strings.Repeat(borders[0], b.Width-2) + borders[3]
88

89
		// Draw borders for last line
90
		case y == (b.Height - 1):
91
			line = borders[4] + strings.Repeat(borders[0], b.Width-2) + borders[5]
92

93
		// Draw top and bottom padding
94
		case y <= b.PaddingY || y >= (b.Height-b.PaddingY):
95
			line = borders[1] + strings.Repeat(" ", b.Width-2) + borders[1]
96

97
		// Render content
98
		default:
99
			if len(lines) > y-offset {
100
				line = lines[y-offset]
101
			} else {
102
				line = ""
103
			}
104

105
			r := []rune(line)
106

107
			lastAnsii := ""
108
			withoutAnsii := []rune{}
109
			withOffset := []rune{}
110
			i := 0
111

112
			for {
113
				if i >= len(r) {
114
					break
115
				}
116

117
				if r[i] == 27 {
118
					lastAnsii = ""
119
					withOffset = append(withOffset, r[i])
120
					lastAnsii += string(r[i])
121
					i++
122
					for {
123

124
						i++
125
						if i > len(r) {
126
							break
127
						}
128

129
						withOffset = append(withOffset, r[i])
130
						lastAnsii += string(r[i])
131

132
						if r[i] == 'm' {
133
							i++
134
							break
135
						}
136
					}
137
				}
138

139
				if i >= len(r) {
140
					break
141
				}
142

143
				withoutAnsii = append(withoutAnsii, r[i])
144

145
				if len(withoutAnsii) <= contentWidth {
146
					withOffset = append(withOffset, r[i])
147
				}
148

149
				i++
150
			}
151

152
			if len(withoutAnsii) > contentWidth {
153
				// If line is too large limit it
154
				line = string(withOffset)
155
			} else {
156
				// If line is too small enlarge it by adding spaces
157
				line += strings.Repeat(" ", contentWidth-len(withoutAnsii))
158
			}
159

160
			if lastAnsii != "" {
161
				line += RESET
162
			}
163

164
			line = prefix + line + suffix
165
		}
166

167
		// Don't add newline for last element
168
		if y != b.Height-1 {
169
			line += "\n"
170
		}
171

172
		out += line
173
	}
174

175
	return out
176
}
177

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.