podman

Форк
0
249 строк · 5.0 Кб
1
// Provides basic bulding blocks for advanced console UI
2
//
3
// Coordinate system:
4
//
5
//  1/1---X---->
6
//   |
7
//   Y
8
//   |
9
//   v
10
//
11
// Documentation for ANSI codes: http://en.wikipedia.org/wiki/ANSI_escape_code#Colors
12
//
13
// Inspired by: http://www.darkcoding.net/software/pretty-command-line-console-output-on-unix-in-python-and-go-lang/
14
package goterm
15

16
import (
17
	"bufio"
18
	"bytes"
19
	"fmt"
20
	"os"
21
	"strings"
22
)
23

24
// Reset all custom styles
25
const RESET = "\033[0m"
26

27
// Reset to default color
28
const RESET_COLOR = "\033[32m"
29

30
// Return cursor to start of line and clean it
31
const RESET_LINE = "\r\033[K"
32

33
// List of possible colors
34
const (
35
	BLACK = iota
36
	RED
37
	GREEN
38
	YELLOW
39
	BLUE
40
	MAGENTA
41
	CYAN
42
	WHITE
43
)
44

45
var Output *bufio.Writer = bufio.NewWriter(os.Stdout)
46

47
func getColor(code int) string {
48
	return fmt.Sprintf("\033[3%dm", code)
49
}
50

51
func getBgColor(code int) string {
52
	return fmt.Sprintf("\033[4%dm", code)
53
}
54

55
// Set percent flag: num | PCT
56
//
57
// Check percent flag: num & PCT
58
//
59
// Reset percent flag: num & 0xFF
60
const shift = uint(^uint(0)>>63) << 4
61
const PCT = 0x8000 << shift
62

63
type winsize struct {
64
	Row    uint16
65
	Col    uint16
66
	Xpixel uint16
67
	Ypixel uint16
68
}
69

70
// Global screen buffer
71
// Its not recommended write to buffer dirrectly, use package Print,Printf,Println fucntions instead.
72
var Screen *bytes.Buffer = new(bytes.Buffer)
73

74
// GetXY gets relative or absolute coordinates
75
// To get relative, set PCT flag to number:
76
//
77
//      // Get 10% of total width to `x` and 20 to y
78
//      x, y = tm.GetXY(10|tm.PCT, 20)
79
//
80
func GetXY(x int, y int) (int, int) {
81
	if y == -1 {
82
		y = CurrentHeight() + 1
83
	}
84

85
	if x&PCT != 0 {
86
		x = int((x & 0xFF) * Width() / 100)
87
	}
88

89
	if y&PCT != 0 {
90
		y = int((y & 0xFF) * Height() / 100)
91
	}
92

93
	return x, y
94
}
95

96
type sf func(int, string) string
97

98
// Apply given transformation func for each line in string
99
func applyTransform(str string, transform sf) (out string) {
100
	out = ""
101

102
	for idx, line := range strings.Split(str, "\n") {
103
		out += transform(idx, line)
104
	}
105

106
	return
107
}
108

109
// Clear screen
110
func Clear() {
111
	Output.WriteString("\033[2J")
112
}
113

114
// Move cursor to given position
115
func MoveCursor(x int, y int) {
116
	fmt.Fprintf(Screen, "\033[%d;%dH", y, x)
117
}
118

119
// Move cursor up relative the current position
120
func MoveCursorUp(bias int) {
121
	fmt.Fprintf(Screen, "\033[%dA", bias)
122
}
123

124
// Move cursor down relative the current position
125
func MoveCursorDown(bias int) {
126
	fmt.Fprintf(Screen, "\033[%dB", bias)
127
}
128

129
// Move cursor forward relative the current position
130
func MoveCursorForward(bias int) {
131
	fmt.Fprintf(Screen, "\033[%dC", bias)
132
}
133

134
// Move cursor backward relative the current position
135
func MoveCursorBackward(bias int) {
136
	fmt.Fprintf(Screen, "\033[%dD", bias)
137
}
138

139
// Move string to possition
140
func MoveTo(str string, x int, y int) (out string) {
141
	x, y = GetXY(x, y)
142

143
	return applyTransform(str, func(idx int, line string) string {
144
		return fmt.Sprintf("\033[%d;%dH%s", y+idx, x, line)
145
	})
146
}
147

148
// ResetLine returns carrier to start of line
149
func ResetLine(str string) (out string) {
150
	return applyTransform(str, func(idx int, line string) string {
151
		return fmt.Sprintf("%s%s", RESET_LINE, line)
152
	})
153
}
154

155
// Make bold
156
func Bold(str string) string {
157
	return applyTransform(str, func(idx int, line string) string {
158
		return fmt.Sprintf("\033[1m%s\033[0m", line)
159
	})
160
}
161

162
// Apply given color to string:
163
//
164
//     tm.Color("RED STRING", tm.RED)
165
//
166
func Color(str string, color int) string {
167
	return applyTransform(str, func(idx int, line string) string {
168
		return fmt.Sprintf("%s%s%s", getColor(color), line, RESET)
169
	})
170
}
171

172
func Highlight(str, substr string, color int) string {
173
	hiSubstr := Color(substr, color)
174
	return strings.Replace(str, substr, hiSubstr, -1)
175
}
176

177
func HighlightRegion(str string, from, to, color int) string {
178
	return str[:from] + Color(str[from:to], color) + str[to:]
179
}
180

181
// Change background color of string:
182
//
183
//     tm.Background("string", tm.RED)
184
//
185
func Background(str string, color int) string {
186
	return applyTransform(str, func(idx int, line string) string {
187
		return fmt.Sprintf("%s%s%s", getBgColor(color), line, RESET)
188
	})
189
}
190

191
// Width gets console width
192
func Width() int {
193
	ws, err := getWinsize()
194

195
	if err != nil {
196
		return -1
197
	}
198

199
	return int(ws.Col)
200
}
201

202
// CurrentHeight gets current height. Line count in Screen buffer.
203
func CurrentHeight() int {
204
	return strings.Count(Screen.String(), "\n")
205
}
206

207
// Flush buffer and ensure that it will not overflow screen
208
func Flush() {
209
	for idx, str := range strings.SplitAfter(Screen.String(), "\n") {
210
		if idx > Height() {
211
			return
212
		}
213

214
		Output.WriteString(str)
215
	}
216

217
	Output.Flush()
218
	Screen.Reset()
219
}
220

221
func Print(a ...interface{}) (n int, err error) {
222
	return fmt.Fprint(Screen, a...)
223
}
224

225
func Println(a ...interface{}) (n int, err error) {
226
	return fmt.Fprintln(Screen, a...)
227
}
228

229
func Printf(format string, a ...interface{}) (n int, err error) {
230
	return fmt.Fprintf(Screen, format, a...)
231
}
232

233
func Context(data string, idx, max int) string {
234
	var start, end int
235

236
	if len(data[:idx]) < (max / 2) {
237
		start = 0
238
	} else {
239
		start = idx - max/2
240
	}
241

242
	if len(data)-idx < (max / 2) {
243
		end = len(data) - 1
244
	} else {
245
		end = idx + max/2
246
	}
247

248
	return data[start:end]
249
}
250

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

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

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

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