利用正则实现彩色控制台输出

近期忙了一阵less的二次开发的工作,期间遇到了不少须要向控制台输出彩色文字的需求。翻了下曾经同事的代码,发现要么自己拼转义字符串,要么使用一些不太好用的第三方库。总之都不是非常合自己的口味。

依照自己的口味,一个好的第三方库应该满足例如以下需求: 要支持丰富的颜色设置,同一时候设置颜色又不能太累赘,并且要支持console.log的通配符表示方法以降低拼字符串的工作。cli-color和colors的语法类似,都是採用方法来设定字符串颜色:

// colors
console.log("this is an error".error);

// cli-color
console.log(clc.red(‘red‘) + ‘ plain ‘ + clc.blue(‘blue‘));

假设字符串中的颜色比較多,并且字符串中还包括动态数据,那么就须要大量的拼字符串的工作,丑陋且easy出错。因此这样的坑爹的方案直接忽略。

既然这些现成的库不好用。干脆就自己写一个。作为一个前端平时自己接触的最多的是html,受html语法的启示。打算採用标签的形式来设置字符颜色,而不是採用方法的形式。比方要输出红绿两种颜色的文本,能够採用例如以下方式:Foo.log(‘<red>red
color <green>green color</green></red>‘)
。这样的方式有两个长处: 第一,便于表现丰富的颜色,尤其是颜色嵌套的情况。假设採用cli-color那种方式来表现多个颜色的嵌套,预计拼字符串会让你想吐;第二。省去了记忆方法名和拼字符串。

那么这样的设计是否easy实现呢? 在回答这个问题之前我们先简单说一下实现彩色输出的原理。向控制台输出彩色文字主要利用了ansi 中的转义字符(ANSI转义字符表)。

众多的转义字符中有一部分是设置控制台的渲染方式的,当中输出控制採用例如以下语法来声明:\x1b[nm

x1b的值是27,在ASC码表中表示转义字符。后面的[nm是模式设置,[和m是常量。n为变量。通过设置N的值能够实现不同的输出设置,以下为经常使用的N值

  • 0 開始以暗色模式显示文本, 文字颜色为用户设置的控制台默认颜色。一般为白色
  • 1 開始以亮色模式显示文本。 文字颜色为用户设置的控制台默认颜色。一般为白色
  • 30 ~ 27 分别以black、red、green、 yellow、blue、pink、cyan、white颜色来显示文本

须要特别注意的一点:过这些输出设置不仅对本次输出起效,并且将一直起效。直至遇到新的设置或控制台退出! 所以在使用的时候一定要记得重置颜色设置。免得影响后面的控制台输出。我们通过以下的demo来检验下这些转义字符的功能。注意划红线的语句部分。尽管这条语句中没有对输出进行不论什么设置,但由于上一条命令中设置了控制台颜色,所以这次输出依旧採用的上次的设置。

叙述了这么多。最终能够回答上面的那个问题了:那么这样的设计是否easy实现呢?答案是:非常easy。我们只须要用这则处理3类字符串就能够了: 转义字符、颜色開始tag。颜色结束tag。

处理策略也非常easy:

  • 遇到由斜线開始的转义字符, 直接返回斜线后面的字符
  • 遇到開始Tag, 查看是否为支持的颜色,若不支持。不做处理原样返回。若支持。返回tag相应到 颜色转义字符,并将该颜色转义字符压栈。
  • 遇到结束Tag。 查看是否是支持的颜色。若不支持。不做处理原样返回;若支持。弹栈并返回栈顶颜色相应的转义字符。若栈为空,则设置为系统默认颜色。
  • 其它情况一律不做处理,原样返回(这一步主要是预防自己没有预料的一些匹配出现,这个样例中应该用不到,为了保险起见还是留着吧)。
  • 为了防止用户标签没有闭合而影响其它控制台输出,在最后预防行的设置颜色为默认颜色。

这部分的逻辑已经封并公布到了npm的rich-console模块,以下为详细的实现代码和demo执行结果截图。顺便说一下ANSI中支持的转义内容还非常多比方设置背景色、设置加粗、下划线等,但这些支持的并不好,未能动物所下非常多都不支持,再加上这些功能更用的比較少。因此这些功能被有意忽略了。

/**
 * 获得带颜色转义字符的控制台输出模板.
 * @param  {String}tmpl        包括标签的模板字符串
 * @param  {boolean}isBright   是否高亮,default false
 * @return {String}
 * @public
 */
function getRichTmpl(tmpl, isBright){
    if(typeof tmpl == ‘object‘){ return tmpl; }

    var fontStyle = isBright == true ? ‘\u001b[1m‘ : ‘‘;
    var ESCAPES  = {
        black  : (fontStyle + ‘\u001b[30m‘),
        red    : (fontStyle + ‘\u001b[31m‘),
        green  : (fontStyle + ‘\u001b[32m‘),
        yellow : (fontStyle + ‘\u001b[33m‘),
        orange : (fontStyle + ‘\u001b[33m‘),
        blue   : (fontStyle + ‘\u001b[34m‘),
        pink   : (fontStyle + ‘\u001b[35m‘),
        cyan   : (fontStyle + ‘\u001b[36m‘),
        white  : (fontStyle + ‘\u001b[37m‘),
        noColor: ‘\u001b[0m‘
    }    

    var NO_COLOR = ESCAPES.noColor;
    var styleStack = [];
    var reg = new RegExp((
         ‘(\\\\.)‘     // 由\表示的转义字符
       + ‘|<(\\w+)>‘   // 样式開始标签
       + ‘|</(\\w+)>‘  // 样式结束标签
    ), ‘g‘);

    var handleTag = function(str){
        return str.replace(reg, function(m, $1, $2, $3){
            // 若是转义字符之间返回\后面的字符
            if ($1) { return $1.slice(1); }

            // 若为不支持的颜色直接忽略,否则返回样式開始字符并将样式压栈
            if ($2) {
                var style = ESCAPES[$2];
                if(style){
                    styleStack.push(style);
                    return style;
                }else{
                    return m;
                }
            }              

            // 若为不支持的颜色直接忽略,否则从样式栈中弹出当前样式并返回
            // 栈顶样式。若栈为空返回系统默认样式
            if ($3) {
                if(ESCAPES[$3]){
                    styleStack.pop();
                    var len = styleStack.length;
                    var topStyle = len > 0 ?

styleStack[len - 1] : null;
                    return (topStyle ? topStyle : NO_COLOR);
                }else{
                    return m;
                }
            }

            // others
            return m;
        }) + NO_COLOR; // 最末尾的两个重置用来防止用户标签不闭合进而污染整个控制台输出
    };

    return handleTag(tmpl);
}

/**
 * 向控制台输出彩色文字.
 * @param {String}cont
 * @example
 *   showColorText(
 *      ‘<red>%s <green>%s</green>! </red>‘,
 *      ‘hello‘,
 *      ‘wold‘
 *   );
 * @public
 */
function output(cont){
    // 若用户输入的是一个object则调用系统的console输出object结构
    if(typeof cont == ‘object‘){
        console.log(cont);
        return;
    }

    var moreArgs = [].slice.call(arguments, 1);
    moreArgs.unshift(getRichTmpl(cont));
    console.log.apply(console, moreArgs);
}

/**
 * 以红色文字向控制台输出错误信息.
 * @param  {String|Object}cont
 * @param  {Object...}
 * @public
 */
function outputError(cont){
    if(typeof cont == ‘object‘){
        console.log(cont);
    }else{
        var moreArgs = [].slice.call(arguments, 1);
        moreArgs.unshift(‘<red>‘ + cont + ‘</red>‘);
        output.apply(null, moreArgs);
    }
}

module.exports = {
    getRichTmpl: getRichTmpl,
    error: outputError,
    log: output
}
时间: 2024-10-29 19:12:05

利用正则实现彩色控制台输出的相关文章

python通过colorama模块在控制台输出彩色文字的方法

本文实例讲述了python通过colorama模块在控制台输出彩色文字的方法. colorama是一个python专门用来在控制台.命令行输出彩色文字的模块,可以跨平台使用,在windows下linux下都工作良好,如果你想让控制台的输出信息更漂亮一些,可以使用给这个模块. colorama官方地址:https://pypi.python.org/pypi/colorama 安装colorama模块 pip install colorama 用法: >>> from colorama i

spring boot在控制台输出彩色日志

阅读org.springframework.boot.context.config.AnsiOutputApplicationListener 源码发现,通过向JVM传递参数,可以在控制台打印彩色日志 向JVM传递参数:-Dspring.output.ansi.enabled=ALWAYS -Dconsole-available=true 或者在application.properties配置文件中增加上面两个配置项: 1 spring.output.ansi.enabled=ALWAYS 2

控制台输出彩色样式

没错,就是这么无聊,给console的文字添加样式.你以为你真的了解console.log吗?不,你只是把它当成了alert的替代品,多的是你不知道的事. 在正常模式下,一般只能向console 控制台输出简单的文字信息.为了让显示友好一点,可以用console.warn()来输出警告信息,也可以用console.error()来输出错误信息. 笔者以前也只是认为console只有这几种样式,无意中发现居然还能自己添加样式,顿时感觉发现了新大陆. 下面是console.log() API的官方文

前端不为人知的一面--前端冷知识集锦 前端已经被玩儿坏了!像console.log()可以向控制台输出图片

前端已经被玩儿坏了!像console.log()可以向控制台输出图片等炫酷的玩意已经不是什么新闻了,像用||操作符给变量赋默认值也是人尽皆知的旧闻了,今天看到Quora上一个帖子,瞬间又GET了好多前端技能,一些属于技巧,一些则是闻所未闻的冷知识,一时间还消化不过来.现分类整理出来分享给大家,也补充了一些平时的积累和扩展了一些内容. HTML篇 浏览器地址栏运行JavaScript代码 这个很多人应该还是知道的,在浏览器地址栏可以直接运行JavaScript代码,做法是以javascript:开

Python 2.7_爬取CSDN单页面利用正则提取博客文章及url_20170113

年前有点忙,没来的及更博,最近看爬虫正则的部分 巩固下 1.爬取的单页面:http://blog.csdn.net/column/details/why-bug.html 2.过程 解析url获得网站源代码 3.找到文章标题列表和文章url(a标签下'href'属性)组成列表 4.for循环取出 #解析用到的还是urlllib urllib2两个模块 并加了个header请求表头 代码及过程如下: #coding:utf-8 import re import urllib import urll

Qt控制台输出QString

有时候想在控制台输出我们想要的QString变量. 1.qDebug可以实现在控制台终端打印,但我们还是想使用C++中的std::cout<<variable This function does nothing if QT_NO_DEBUG_OUTPUT was defined during compilation. 2.网上说的方法利用QTextStream: Cpp代码   #include <QTextStream> QTextStream cin(stdin, QIODe

JS利用正则配合replace替换指定字符

替换指定字符的方法有很多,在本文为大家详细介绍下,JS利用正则配合replace是如何做到的,喜欢的朋友可以参考下 定义和用法 replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串. 语法 stringObject.replace(regexp,replacement) 参数 描述 regexp 必需.规定了要替换的模式的 RegExp 对象.请注意,如果该值是一个字符串,则将它作为要检索的直接量文本模式,而不是首先被转换为 RegExp 对象. re

【Java】控制异常在控制台输出

每次在Java程出现问题,总会抛出一大堆异常,让人眼花缭乱,在Javaweb编程的时候尤甚,让人很难找到出错的位置, 尤其在你网络工程文件多.插件多.框架的时候,各种插件.框架连锁,导致你更难找到出错的位置. 其实异常在控制台输出是可以控制的. 关键是利用到,这个方法与数组.对象都是java自带的,不用引入任何东西: StackTraceElement[] stacks = new Throwable().getStackTrace(); 这个操作. 先看一段程序, public static

springboot彩色日志输出乱码

<!--0. 日志格式和颜色渲染 --> <!-- 彩色日志依赖的渲染类 --> <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" /> <conversionRule conversionWord="wex" converterClas