Linux, windows command line output control instructions, colored information, multi-line refresh, progress bar effect, golang

1. Colored information
linux

Color and pattern number

// foreground background color
//------------------------------------------
// 30 40 black
// 31 41 red
// 32 42 green
// 33 43 yellow
// 34 44 blue
// 35 45 purple
// 36 46 cyan blue
// 37 47 white
//
//Mode code meaning
//------------------------
// 0 terminal default settings
// 1 highlight
// 4 Use underscore
// 5 flashes
// 7 Highlight display
// 8 invisible

Output template

// Where 0x1B is the mark, [starts to define the color, in order: mode, background color, foreground color, 0 means restoring the default color.
func (c ColorOutput) Println(str interface{<!-- -->}) {<!-- -->
fmt.Println(fmt.Sprintf("%c[%d;%d;%dm%s%c[0m", 0x1B, c.mode, c.backColor, c.frontColor, str, 0x1B))
}
windows

Check the color number under cmd

View the color number under windows cmd: color /?

Sets the default console foreground and background colors.

COLOR [attr]

  attr Specifies color attribute of console output

Color attributes are specified by TWO hex digits -- the first
corresponds to the background; the second the foreground. Each digit
can be any of the following values:

    0 = Black 8 = Gray
    1 = Blue 9 = Light Blue
    2 = Green A = Light Green
    3 = Aqua B = Light Aqua
    4 = Red C = Light Red
    5 = Purple D = Light Purple
    6 = Yellow E = Light Yellow
    7 = White F = Bright White

If no argument is given, this command restores the color to what it was
when CMD.EXE started. This value either comes from the current console
window, the /T command line switch or from the DefaultColor registry
value.

The COLOR command sets ERRORLEVEL to 1 if an attempt is made to execute
the COLOR command with a foreground and background color that are the
same.

Example: "COLOR fc" produces light red on bright white

Set font color and background color and output

func SetCmdPrint(s interface{<!-- -->}, i int) {<!-- -->
proc := kernel32.NewProc("SetConsoleTextAttribute")
handle, _, _ := proc.Call(uintptr(syscall.Stdout), uintptr(i))
fmt.Println(s)
handle, _, _ = proc.Call(uintptr(syscall.Stdout), uintptr(7))
CloseHandle := kernel32.NewProc("CloseHandle")
CloseHandle.Call(handle)
}

View current operating system type

// darwin, windows, linux
if runtime.GOOS == "windows" {<!-- -->
...
} else {<!-- -->
...
}

The idea is to execute the corresponding output method by judging the operating system type. It can run normally under windows, but it cannot be compiled under linux and an error is reported.

./ColorOutput.go:139:15: undefined: syscall.LazyDLL
./ColorOutput.go:187:13: undefined: syscall.NewLazyDLL

Indeed, syscall.NewLazyDLL does not exist under Linux systems.

So the question now is, how to tell the golang compiler to selectively compile or not compile a certain file based on whether it is a windows platform?

You can actually do this, just add annotation to the header of the file:

To compile this file only under Windows system, you need to add
// + build windows

To compile this file under a non-windows system, you need to add
// + build !windows

Something like this: test.go

// + build windows

page main

....

After solving this problem, I integrated the code and found another problem. If the ColorOutput_windows.go file is not compiled, the method defined in this file will report that it does not exist, but in fact it will not. is called, so we define the method type and then implement it in the ColorOutput_windows.go file. At this point, this function has been initially completed.

Package address: github.com/phprao/ColorOutput

use

ColorOutput.Colorful.WithFrontColor("green").WithBackColor("red").Println("ColorOutput test...")

windows system

linux system

Additional knowledge:
1. About SetConsoleTextAttribute

Set the terminal text properties by calling the Windows operating system API, including: foreground color, background color, and highlight. Multiple attributes can be set at the same time, separated by vertical bars |.

DOC: https://docs.microsoft.com/zh-cn/windows/console/setconsoletextattribute
Usage: https://docs.microsoft.com/zh-cn/windows/console/using-the-high-level-input-and-output-functions
Attribute value: https://docs.microsoft.com/zh-cn/windows/console/console-screen-buffers#character-attributes

The SetConsoleTextAttribute function is used to set the color for displaying subsequently written text. Before exiting, the program restores the original console input mode and color attributes. However, Microsoft officially recommends using “virtual terminal” to achieve terminal control, and it is cross-platform.

It is recommended to use the “virtual terminal sequence” provided by Windows to achieve terminal control compatible with multiple platforms, such as: https://github.com/gookit/color
https://docs.microsoft.com/zh-cn/windows/console/console-virtual-terminal-sequences
https://docs.microsoft.com/zh-cn/windows/console/console-virtual-terminal-sequences#samples

2. About how to set the foreground color and background color

Background color | Foreground color
Note that the simple or operation is wrong, such as 4 | 2, which is actually 6 or yellow, which is inconsistent with the expected green text on a red background.
It should form an 8-bit binary, the first four bits are the background color, and the last four bits are the foreground color, so the background color needs to be shifted left by 4 bits.

Of course, these have been encapsulated in ColorOutput, so there is no need to worry about it.

Finally, I recommend a good color package: https://github.com/gookit/color, which is implemented using the virtual terminal sequence. It has powerful functions and good compatibility.

2. Effect of a single progress bar

The principle of a single progress bar is very simple. In the for loop, use \r after each output to return the cursor to the beginning of the current line. If the length of the output content is different each time, you need to Clear this line (covered below).

3. Multi-line refresh

For example, the effect of using the top command under Linux system.

Main output control instructions

\033[0m Turn off all attributes
\033[1m Set high brightness
\033[4m underline
\033[5m flashing
\033[7m reverse display
\033[8m blanking
\033[30m - \033[37m Set the foreground color
\033[40m - \033[47m Set background color
\033[nA Move the cursor up n lines
\033[nB Move the cursor down n lines
\033[nC Move the cursor n lines to the right
\033[nD Move cursor n lines to the left
\033[y;xHSet cursor position
\033[2J Clear the screen, which is actually turning the page. You can also see the output of the previous page by scrolling the mouse.
\033[K Clears content from the cursor to the end of the line
\033[s Save cursor position
\033[u restore cursor position
\033[?25l Hide cursor
\033[?25h Show cursor

We will use move the cursor up and down and clear the content from the cursor to the end of the line.

\033[nA Move the cursor up n lines. This n value is the number of lines last output. We need to move the cursor to the starting line. This command only needs to be done once, and then after each output Before a line, use the \033[K command to clean up the current line, because the content length of a line is different each time it is output. If the length this time is not as long as the last time, it can still See the remaining information from the last time.

func ff() {<!-- -->
fmt.Println("aaa\\
bbb\\
ccc")

t := 1
for {<!-- -->
if t == 0 {<!-- -->
fmt.Println("\033[3A\033[Kaaa\\
\033[Kbbb\\
\033[Kccc")
t++
} else {<!-- -->
fmt.Println("\033[3A\033[K11111\\
\033[K222222222\\
\033[K333")
t--
}

time.Sleep(3 * time.Second)
}
}

The effect is that the latter one replaces the previous output.

Encapsulate it

func RefreshTable(data string) string {<!-- -->
lines := strings.Split(data, "\\
")
num := strconv.Itoa(len(lines))
for k, line := range lines {<!-- -->
lines[k] = "\033[K" + line
}

lines[0] = "\033[" + num + "A" + lines[0]
dst := strings.Join(lines, "\\
")
return dst
}