教你写一个color日志库,不止有代码还有原理

123GO · 2016-12-26 02:41:07 · 4321 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2016-12-26 02:41:07 的主题,其中的信息可能已经有所发展或是发生改变。

#教你写一个color日志库,不止有代码还有原理。

##前言 在计算机里面,ansi转义码是使用带内信号去控制格式化,颜色,或者其他的输出选项在视频流或者文本终端中的一种办法。编码这些格式化信息,就是在确定的字节序列中,把上述所说的ansi码嵌入到这个文本中。终端会去寻找命令去解释这些字符,而不是把它看作简单的字符码(ascii)。

1970年提出的ansi码,但是直到1980年的早期才普及在了迷你主机和大型机房中。它被使用在早期的电子公告板上,对比之前缺乏光标移动的系统,它改善了显示的效果,这导致了它被广泛的使用。

尽管硬件文本终端,在21世纪已经日益稀少。但是不动摇ansi标准的影响。因为大部分的文本模拟器的解释工作,至少还有相当一部分的文本存在ansi转义序列。唯一的例外就是微软的win32 console。不过这些在微软升级到window10之后已经被解决了。

所以这个古老的协议对我们现在的文本输出依然是有很重要的影响。

###一条小命令

echo  -e "\033[1;31mI ♡  You \e[0m"

output:

不上图我写什么文档,对吧。这条命令可以用来简单的告白用。送给大家了。从这里我们引出了ansi对文本颜色的输出影响,看,就是图中字符的颜色发生了变化。利用这样的性质我们今天就要分享一下如何写一个彩色的日子库(color log)

###CSI 转义序列使用ESC控制字符开始,对于2个字符序列,第二个字符是ASCII的64到95。(@到_,还有所有大写英文字母和[]\^),然而,序列中大多数是超过2个字符的,并以ESC控制字符和左中括号开始。序列被称作CSI,即控制序列引导器或者控制序列启动器的简称。这个序列的最后一个字符是在ASCII范围64到126。也还有一个单字符的CSI (155/0x9B/0233)ESC[,这两个字符序列比单个字符形式用的更多,细节参看C0和C1控制编码。(下文会添加文档的链接),使用UTF-8编码的终端上,两种形式都使用2字节(CSI in UTF-8 is 0xC2, 0x9B),但ESC[序列更加明了。

###文本颜色 文本颜色(和SGR (Select Graphic Rendition)参数)使用CSI n1 [;n2 [; ...]] m 序列来处理,如上所示,序列中每一个n1, n2, ...就是一个SGR参数。因此,例如,你使用30~37表示前景色,40~47表示背景色。下图是一张颜色过渡图。

###开始编码

package util

import (
    "fmt"
    "time"
)

const (
    color_red = uint8(iota + 91)
    color_green
    color_yellow
    color_blue
    color_magenta //洋红

    info = "[INFO]"
    trac = "[TRAC]"
    erro = "[ERRO]"
    warn = "[WARN]"
    succ = "[SUCC]"
)

// see complete color rules in document in https://en.wikipedia.org/wiki/ANSI_escape_code#cite_note-ecma48-13
func Trace(format string, a ...interface{}) {
    prefix := yellow(trac)
    fmt.Println(formatLog(prefix), fmt.Sprintf(format, a...))
}

func Info(format string, a ...interface{}) {
    prefix := blue(info)
    fmt.Println(formatLog(prefix), fmt.Sprintf(format, a...))
}

func Success(format string, a ...interface{}) {
    prefix := green(succ)
    fmt.Println(formatLog(prefix), fmt.Sprintf(format, a...))
}

func Warning(format string, a ...interface{}) {
    prefix := magenta(warn)
    fmt.Println(formatLog(prefix), fmt.Sprintf(format, a...))
}

func Error(format string, a ...interface{}) {
    prefix := red(erro)
    fmt.Println(formatLog(prefix), fmt.Sprintf(format, a...))
}

func red(s string) string {
    return fmt.Sprintf("\x1b[%dm%s\x1b[0m", color_red, s)
}

func green(s string) string {
    return fmt.Sprintf("\x1b[%dm%s\x1b[0m", color_green, s)
}

func yellow(s string) string {
    return fmt.Sprintf("\x1b[%dm%s\x1b[0m", color_yellow, s)
}

func blue(s string) string {
    return fmt.Sprintf("\x1b[%dm%s\x1b[0m", color_blue, s)
}

func magenta(s string) string {
    return fmt.Sprintf("\x1b[%dm%s\x1b[0m", color_magenta, s)
}

func formatLog(prefix string) string {
    return time.Now().Format("2006/01/02 15:04:05") + " " + prefix + " "
}

上面就是一个完整的彩色log的代码 输出的效果:

##完整代码 完整的colorlog代码 测试代码 如果你需要在本地测试,请确保你搭建了正确的go开发环境,并且down下https://github.com/liyu4/chill这个项目。找到util单元

yourpath指的是你的项目路径。
cd yourpath/chill/util
go test -v

##后记 在其中 \x1b[ 实现CSI:
转换前景色为黑色,使用\x1b[30m
转换为红色,使用\x1b[31m
如果使用加粗参数,灰色写作\x1b[30;1m
获取红色加粗,使用\x1b[31;1m
重置颜色为缺省值,使用\x1b[39;49m (或者使用 \x1b[0m 重置所有属性) \033[0m 重置为正常
\033[1m 设置高亮度或加粗
\033[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[30m -- /33[37m 设置前景色
\033[40m -- /33[47m 设置背景色 控制符ESC的常用表示方法\e、\x1b(\x1B)、\033都可以
\e 指代Escape,对应八进制\033,对应十六进制\x1b

###参考文档 ansi转义序列 中文文档


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4321 次点击  ∙  2 赞  
加入收藏 微博
2 回复  |  直到 2017-01-09 02:18:54
williamZ
williamZ · #1 · 8年之前

赞赞赞

123GO
123GO · #2 · 8年之前
williamZwilliamZ #1 回复

赞赞赞

哈哈 谢谢你

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传