linux,windows命令行输出控制指令,带颜色的信息,多行刷新,进度条效果,golang

一、带颜色的信息
linux

颜色及模式编号

// 前景 背景 颜色
// ---------------------------------------
// 30  40  黑色
// 31  41  红色
// 32  42  绿色
// 33  43  黄色
// 34  44  蓝色
// 35  45  紫红色
// 36  46  青蓝色
// 37  47  白色
//
// 模式代码 意义
// -------------------------
//  0  终端默认设置
//  1  高亮显示
//  4  使用下划线
//  5  闪烁
//  7  反白显示
//  8  不可见

输出模板

// 其中0x1B是标记,[开始定义颜色,依次为:模式,背景色,前景色,0代表恢复默认颜色。
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

在 cmd 下查看颜色编号

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

设置字体颜色及背景色并输出

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)
}

查看当前操作系统类型

// darwin, windows, linux
if runtime.GOOS == "windows" {
	......
} else {
	......
}

想法是通过判断操作系统类型来执行对应的输出方法,在 windows 下可以正常运行,但是在 linux 下编译都通不过,报错

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

的确在Linux系统下 syscall.NewLazyDLL不存在。

那么现在的问题就是,如何告诉golang编译器基于是否是windows平台来选择性的编译或不编译某个文件呢?

实际上可以做到这一点,只需要在文件头部加上注解:

只在 windows 系统下编译此文件,则需要在文件头部加上
// +build windows

在非 windows 系统下编译此文件,则需要在文件头部加上
// +build !windows

类似于这样:test.go

// +build windows

pachage main

....

解决了这个问题之后,整合代码,又发现一个问题,如果不编译 ColorOutput_windows.go 文件,那么在这个文件中定义的方法又会报不存在了,但实际上也不会被调用,于是我们定义方法类型,然后在 ColorOutput_windows.go 文件中来实现即可。到此这个功能已经初步完成。

包地址:github.com/phprao/ColorOutput

使用

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

windows 系统
在这里插入图片描述
linux 系统
在这里插入图片描述

补充知识:
1、关于 SetConsoleTextAttribute

通过调用windows操作系统API设置终端文本属性,包括:前景色,背景色,高亮。可同时设置多个属性,使用竖线 | 隔开。

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
属性值: https://docs.microsoft.com/zh-cn/windows/console/console-screen-buffers#character-attributes

SetConsoleTextAttribute函数用于设置显示后续写入文本的颜色。在退出之前,程序会还原原始控制台输入模式和颜色属性。但是微软官方建议使用“虚拟终端”来实现终端控制,而且是跨平台的。

建议使用基于windows提供的“虚拟终端序列”来实现兼容多平台的终端控制,比如: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、关于如何设置前景色和背景色

背景色 | 前景色
注意,简单的或操作是错误的,比如 4 | 2,实际是 6 即 黄色,和预期的红底绿字不一致。
应该构成1个8位的二进制,前四位是背景色,后四位是前景色,因此背景色需要左移4位。

当然这些都已经封装在ColorOutput里面了,不需要操心。

最后推荐一个很好的颜色包:https://github.com/gookit/color,使用的虚拟终端序列来实现的,功能强大,兼容性好。

二、单个进度条效果

单个进度条的原理很简单,在for循环中,每输出一次后使用\r使光标回到当前行的开头,如果每次输出内容的长度不一样的话,还需要清除此行(在下面讲到)。

三、多行刷新

比如我们在linux系统下使用 top 命令的效果。

主要的输出控制指令

\033[0m 关闭所有属性
\033[1m 设置高亮度
\033[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[30m — \033[37m 设置前景色
\033[40m — \033[47m 设置背景色
\033[nA 光标上移n行
\033[nB 光标下移n行
\033[nC 光标右移n行
\033[nD 光标左移n行
\033[y;xH设置光标位置
\033[2J 清屏,其实是翻页,滚动鼠标还能看到上一页的输出
\033[K 清除从光标到行尾的内容
\033[s 保存光标位置
\033[u 恢复光标位置
\033[?25l 隐藏光标
\033[?25h 显示光标

我们会用到光标的上移和下移清除从光标到行尾的内容

\033[nA 光标上移n行,这个n值就是上一次输出的行数,我们要把光标移到起始行,这个指令只需要做一次,然后在输出每一行之前先使用\033[K指令清理当前行,因为每一此输出时某一行的内容长度是不一样的,如果这一次的长度没有上一次长,那么还能看到上一次的残留信息。

func ff() {
	fmt.Println("aaa\nbbb\nccc")

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

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

效果就是后面的替换掉前面的输出。

封装一下

func RefreshTable(data string) string {
	lines := strings.Split(data, "\n")
	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, "\n")
	return dst
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值