自定义输入内容样式

前言

好久没来园子写文章了!😂,现在博客迁移到 github blog了,所以没怎么在这里写了。

思路来源

最近体验了下blade ,一个轻量级MVC框架,看源码时候看到一个比较有意思的类 com.hellokaton.blade.kit.Ansi

package com.hellokaton.blade.kit;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.hellokaton.blade.kit.SystemKit.isWindows;

/**
 *
 * @author dain
 */
public final class Ansi {

    // Color code strings from:
    // http://www.topmudsites.com/forums/mud-coding/413-java-ansi.html
    public static final String SANE = "\u001B[0m";

    public static final String HIGH_INTENSITY = "\u001B[1m";
    public static final String LOW_INTENSITY  = "\u001B[2m";

    public static final String ITALIC         = "\u001B[3m";
    public static final String UNDERLINE      = "\u001B[4m";
    public static final String BLINK          = "\u001B[5m";
    public static final String RAPID_BLINK    = "\u001B[6m";
    public static final String REVERSE_VIDEO  = "\u001B[7m";
    public static final String INVISIBLE_TEXT = "\u001B[8m";

    public static final String BLACK   = "\u001B[30m";
    public static final String RED     = "\u001B[31m";
    public static final String GREEN   = "\u001B[32m";
    public static final String YELLOW  = "\u001B[33m";
    public static final String BLUE    = "\u001B[34m";
    public static final String MAGENTA = "\u001B[35m";
    public static final String CYAN    = "\u001B[36m";
    public static final String WHITE   = "\u001B[37m";

    public static final String BACKGROUND_BLACK   = "\u001B[40m";
    public static final String BACKGROUND_RED     = "\u001B[41m";
    public static final String BACKGROUND_GREEN   = "\u001B[42m";
    public static final String BACKGROUND_YELLOW  = "\u001B[43m";
    public static final String BACKGROUND_BLUE    = "\u001B[44m";
    public static final String BACKGROUND_MAGENTA = "\u001B[45m";
    public static final String BACKGROUND_CYAN    = "\u001B[46m";
    public static final String BACKGROUND_WHITE   = "\u001B[47m";

    public static final Ansi HighIntensity = new Ansi(HIGH_INTENSITY);
    public static final Ansi Bold          = HighIntensity;
    public static final Ansi LowIntensity  = new Ansi(LOW_INTENSITY);
    public static final Ansi Normal        = LowIntensity;

    public static final Ansi Italic     = new Ansi(ITALIC);
    public static final Ansi Underline  = new Ansi(UNDERLINE);
    public static final Ansi Blink      = new Ansi(BLINK);
    public static final Ansi RapidBlink = new Ansi(RAPID_BLINK);

    public static final Ansi Black   = new Ansi(BLACK);
    public static final Ansi Red     = new Ansi(RED);
    public static final Ansi Green   = new Ansi(GREEN);
    public static final Ansi Yellow  = new Ansi(YELLOW);
    public static final Ansi Blue    = new Ansi(BLUE);
    public static final Ansi Magenta = new Ansi(MAGENTA);
    public static final Ansi Cyan    = new Ansi(CYAN);
    public static final Ansi White   = new Ansi(WHITE);

    public static final Ansi BgBlack   = new Ansi(BACKGROUND_BLACK);
    public static final Ansi BgRed     = new Ansi(BACKGROUND_RED);
    public static final Ansi BgGreen   = new Ansi(BACKGROUND_GREEN);
    public static final Ansi BgYellow  = new Ansi(BACKGROUND_YELLOW);
    public static final Ansi BgBlue    = new Ansi(BACKGROUND_BLUE);
    public static final Ansi BgMagenta = new Ansi(BACKGROUND_MAGENTA);
    public static final Ansi BgCyan    = new Ansi(BACKGROUND_CYAN);
    public static final Ansi BgWhite   = new Ansi(BACKGROUND_WHITE);

    final private String[] codes;
    final private String   codes_str;

    public Ansi(String... codes) {
        this.codes = codes;
        String _codes_str = "";
        for (String code : codes) {
            _codes_str += code;
        }
        codes_str = _codes_str;
    }

    public Ansi and(Ansi other) {
        List<String> both = new ArrayList<String>();
        Collections.addAll(both, codes);
        Collections.addAll(both, other.codes);
        return new Ansi(both.toArray(new String[]{}));
    }

    public String colorize(String original) {
        return codes_str + original + SANE;
    }

    public String format(String template, Object... args) {
        if (isWindows()) {
            if (null == args || args.length == 0) {
                return template;
            }
            return String.format(template, args);
        }
        String text = (null == args || args.length == 0) ? template : String.format(template, args);
        return colorize(text);
    }

}

没错,就是这个类,能控制输出字体颜色,但是没有自定义简单颜色类型,我很好奇这样就能自定义输出内容背景字体样式 ?测试了下,的确可以,本着搞清楚原因去看了源码中

给出的链接地址 http://www.topmudsites.com/forums/mud-coding/413-java-ansi.html

自定义控制台输出颜色

Java自带两种输出流输出的颜色

System.out.println(System.getProperty("java.version"));
System.err.println(System.getProperty("java.version"));

java-version-color

浏览器中输出不同颜色

console.log(window.navigator.appVersion)
console.warn(window.navigator.appVersion)
console.info(window.navigator.appVersion)
console.error(window.navigator.appVersion)

js-version-color

当然浏览器console 对象支持自定义背景色,


console.log("%c%s","background-color:teal;color:#fff;padding:3px;font-size:50px;font-family:'宋体',","Hello world")

js-print-version-01.png

但是Java不支持这种写法,但是可以通过ANSI 转码方式控制输出样式

Java简单封装自定义输出颜色

参考blade中源码,发现其中样式还是不够灵活,查了下ANSI表现形式,

发现不局限于语言,意思就是任何语言都支持这种写法。因此就十分有必要了解下了。

package com.wuxin;


/**
 * @author: wuxin0011
 * @Description:
 */
public class CustomColor {

    public static void main(String[] args) throws Exception {
        testColor();
    }


    public static void testColor() throws Exception {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(200);
            System.out.println(backgroundColor("java.version=", System.getProperty("java.version")));
        }
        System.out.println("==========================");
        for (int i = 0; i < 10; i++) {
            Thread.sleep(200);
            System.out.println(fontColor("java.version=", System.getProperty("java.version")));
        }
        System.out.println("==========================");
        for (int i = 0; i < 10; i++) {
            Thread.sleep(200);
            System.out.println(colorTemplate(new MyColor(), new MyColor(), "java.version=", System.getProperty("java.version")));
        }
        Thread.sleep(200);
        System.out.println("==============custom color ============");
        System.out.println(colorTemplate(new MyColor(0, 0, 0), new MyColor(255, 255, 255), "java.version=", System.getProperty("java.version")));
    }

    private static final int RGB_VALUE_MAX = 255;
    private static final int BACKGROUND_COLOR = 48;
    private static final int FONT_COLOR = 38;
    private static final String CLEAR_COLOR = "\u001B[0m";


    public static class MyColor {
        public int R;
        public int G;
        public int L;

        public MyColor(int r, int g, int l) {
            this.R = r;
            this.G = g;
            this.L = l;
        }

        public MyColor() {
            this.R = randomColorValue();
            this.G = randomColorValue();
            this.L = randomColorValue();
        }
    }


    public static int randomColorValue() {
        return (int) Math.floor(Math.random() * RGB_VALUE_MAX);
    }

    public static String fontColor(String... content) {
        int R = randomColorValue();
        int G = randomColorValue();
        int L = randomColorValue();
        return fontColor(R, G, L, content);
    }

    public static String fontColor(MyColor myColor, String... content) {
        return fontColor(myColor.R, myColor.G, myColor.L, content);
    }

    public static String fontColor(int R, int G, int L, String... content) {
        return colorTemplate(FONT_COLOR, R, G, L, content);
    }

    public static String backgroundColor(String... content) {
        int R = randomColorValue();
        int G = randomColorValue();
        int L = randomColorValue();
        return backgroundColor(R, G, L, content);
    }

    public static String backgroundColor(MyColor myColor, String... content) {
        return backgroundColor(myColor.R, myColor.G, myColor.L, content);
    }

    public static String backgroundColor(int R, int G, int L, String... content) {
        return colorTemplate(BACKGROUND_COLOR, R, G, L, content);
    }


    public static String colorTemplate(int type, int R, int G, int L, String... content) {
        valid(R, G, L);
        StringBuilder s = new StringBuilder();
        for (String s1 : content) {
            s.append(s1);
        }
        return String.format("\u001B[%d;2;%d;%d;%dm%s\u001B[0m", type, R, G, L, s.toString());
    }

    public static String colorTemplate(int R1, int G1, int L1, int R2, int G2, int L2, String... content) {
        valid(R1, G1, L1, R2, G2, L2);
        StringBuilder s = new StringBuilder();
        for (String s1 : content) {
            s.append(s1);
        }
        return String.format("\u001B[%s;2;%d;%d;%dm\u001B[%s;2;%d;%d;%dm%s\u001B[0m", BACKGROUND_COLOR, R1, G1, L1, FONT_COLOR, R2, G2, L2, s.toString());
    }

    public static String colorTemplate(MyColor bc, MyColor fc, String... content) {
        return colorTemplate(bc.R, bc.G, bc.L, fc.R, fc.G, fc.L, content);
    }


    public static void valid(MyColor... myColors) {
        for (MyColor myColor : myColors) {
            valid(myColor.R, myColor.G, myColor.L);
        }
    }

    public static void valid(int... ints) {
        for (int result : ints) {
            if (result > RGB_VALUE_MAX) {
                throw new RuntimeException("color value max is " + RGB_VALUE_MAX);
            }
        }
    }
}

关于\u001B[%s;2;%d;%d;%dm%s\u001B[0m含义

  • \u001B[ 开启颜色模式

  • %s表示是字体颜色(38)还是背景颜色(48)

  • 2 是启用rgb模式,用5表示启用#000 这种形式颜色,上面没有封装#xxx这种形式

  • 三个%d分别对应 rgb三个位置数值

  • %s 表示输出内容,就是你传入字符串

  • \u001B[0m表示还原,这样就不影响后续输出了

执行测试结果

java-version-print-02

将编译好文件上传到Linux环境中测试

java-run-linux-print

JS简单封装自定义输出颜色

function backgroundColor(...str){
	
	function colorRandom(l=255){
		return Math.floor(Math.random()*l)
	}

	let r = colorRandom();
	let g = colorRandom();
	let l = colorRandom();
	let printColor = (...m)=>console.log(`\u001B[48;2;${r};${g};${l}m ${m} \u001B[0m`)
    printColor(str)

}


function fontColor(...str){
	function colorRandom(l=255){
		return Math.floor(Math.random()*l)
	}

	let r = colorRandom();
	let g = colorRandom();
	let l = colorRandom();
	let printColor = (...m)=>console.log(`\u001B[38;2;${r};${g};${l}m ${m} \u001B[0m`)
    printColor(str)
}

Array.from({length:10}).forEach(()=>{
    fontColor("hello world")
    console.log('=============================')
    backgroundColor("hello world")
})

这里只是简单写了下,意思到了就行,就是说明可以自定义。

在浏览器中执行就是代码测试

执行测试结果

测试浏览器是Edge浏览器

edge-print-color.png

经测试在firefox中测试无效!说明兼容性不是很好

firefox-print-fail.png

简单处理下兼容性问题

function isFirefox() {
    // 顺便兼容下node环境
	try {
		if (typeof window !== undefined) {
			return window.navigator.userAgent.indexOf("Firefox") !== -1;
		}
	} catch (error) {
        // ignore 
	}
	return false
}
function backgroundColor(...str) {

	function colorRandom(l = 255) {
		return Math.floor(Math.random() * l)
	}

	let r = colorRandom();
	let g = colorRandom();
	let l = colorRandom();
	let printColor = (...m) => {
		if (isFirefox()) {
			console.log(`%c${m}`, `background-color: rgb(${r}, ${g}, ${l})`)
		}
		else {
			console.log(`\u001B[48;2;${r};${g};${l}m ${m} \u001B[0m`)
		}
	}
	printColor(str)

}


function fontColor(...str) {
	function colorRandom(l = 255) {
		return Math.floor(Math.random() * l)
	}

	let r = colorRandom();
	let g = colorRandom();
	let l = colorRandom();
	let printColor = (...m) => {
		if (isFirefox()) {
			console.log(`%c${m}`, `color: rgb(${r}, ${g}, ${l})`)
		} else {
			console.log(`\u001B[38;2;${r};${g};${l}m ${m} \u001B[0m`)
		}
	}
	return printColor(str)
}


Array.from({ length: 10 }).forEach(() => {
	fontColor("hello world")
	console.log('=============================')
	backgroundColor("hello world")
})

firefox-print-success.png

node 中执行

node-print-color.png

C封装

作为万物起源,C当然也支持了!



#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define COLOR_MAX 255
#define COLOR_BACKGROUND 48
#define COLOR_FONT 38


/*define */
typedef struct CustomColor
{

		int R;
		int G;
		int L;

}CustomColor;



void backgroundColorPrint(int R,int G,int L,char* ch);
void colorPrintTemplate(int type ,int R,int G,int L,char* ch);
void fontColorAndBackgroundTemplate(int R,int G,int L,int R1,int G1,int L1,char* ch);
void backgroundColorPrint(int R,int G,int L,char* ch);
void fontColorPrint(int R,int G,int L,char* ch);
int randomValue();
bool valid(int c);
CustomColor genCustomColor(int R,int G,int L);
void printRGL(int R,int G,int L);
void warning(char* ch);
void info(char* ch);
void error(char* ch);
void success(char* ch);

/******************************************************************************************/



int main(){
	char ch[] = "c language print color !";
	
	warning(ch);
	info(ch);
	error(ch);
	success(ch);


	for(int i = 0;i<30;i++){
		int R = randomValue();
		int G = randomValue();
		int L = randomValue();
		int R1 = randomValue();
		int G1 = randomValue();
		int L1 = randomValue();
		// printRGL(R,G,L);
		backgroundColorPrint(R,G,L,ch);
		fontColorPrint(R1,G1,L1,ch);
	}
	return 0;
}





int randomValue(){
	return rand() % COLOR_MAX;
}

bool valid(int c){
	return 0<=c && c<=COLOR_MAX;
}



void colorPrintTemplate(int type ,int R,int G,int L,char* ch){
	if( !(valid(R) && valid(G) && valid(L))){
		// if valid fail use default print
		printf("%s\n",ch);
		return;
	}
	printf("\u001B[%d;2;%d;%d;%dm %s\u001B[0m\n",type,R,G,L,ch);
}

void fontColorAndBackgroundTemplate(int R,int G,int L,int R1,int G1,int L1,char* ch){
	if( !(valid(R) && valid(G) && valid(L) && valid(R1) && valid(G1) && valid(L1))){
		// if valid fail use default print
		printf("%s\n",ch);
		return;
	}
	printf("\u001B[%d;2;%d;%d;%dm\u001B[%d;2;%d;%d;%dm%s\u001B[0m\n",COLOR_BACKGROUND,R,G,L,COLOR_FONT,R1,G1,L1,ch);
}



void backgroundColorPrint(int R,int G,int L,char* ch){
  colorPrintTemplate(COLOR_BACKGROUND,R,G,L,ch);
}

void fontColorPrint(int R,int G,int L,char* ch){
  colorPrintTemplate(COLOR_FONT,R,G,L,ch);
}

void printRGL(int R,int G,int L){
	printf("R = %d,G = %d,L = %d\n",R,G,L);
}


CustomColor genCustomColor(int R,int G,int L){
	CustomColor cs = {R,G,L};
	return cs;
}



void warning(char* ch){
  fontColorAndBackgroundTemplate(51, 43, 0,181, 157, 38,ch);
}

void error(char* ch){
  fontColorAndBackgroundTemplate(41, 0, 0,255, 128, 95,ch);
}

void info(char* ch){
  fontColorAndBackgroundTemplate(0,0,0,255,255,255,ch);
}

void success(char* ch){
  fontColorAndBackgroundTemplate(68, 144, 54,255,255,255,ch);
}

测试结果

c-success.png

color 命令

window cmd 控制台中有这样一个命令 color
cmd-00

当然也可以通过属性调整

cmd-01

可以通过这种方式手动控制CMD控制台颜色,不过这种方式不太推荐。

原文链接

posted @ 2023-10-04 23:24  wuxin001  阅读(18)  评论(0编辑  收藏  举报