Linux终端彩色打印+终端进度条

开发的一个应用程序选择了终端界面, 为了使软件稍微好看些, 研究下Linux终端的彩色打印, 并且基于这个彩色打印实现了几种进度条, 在此总结下: (更多的是觉得这个东西挺好玩的... )

一. Linux终端色彩打印:

1. 属性介绍:

(1). 来自网络的ANSI属性控制码: 

1\033[0m                 关闭所有属性 2\033[1m                 设置高亮度 3\033[4m                 下划线 4\033[5m                 闪烁 5\033[7m                 反显 6\033[8m                 消隐 7\033[30m -- \033[37m    设置前景色 8\033[40m -- \033[47m    设置背景色 9\033[nA                 光标上移n行 10\033[nB                 光标下移n行 11\033[nC                 光标右移n列 12\033[nD                 光标左移n列 13\033[y;H                设置光标位置 14\033[2J                 清屏 15\033[K                  清除从光标到行尾的内容 16\033[s                  保存光标位置 17\033[u                  恢复光标位置 18\033[?25l               隐藏光标 19\033[?25h               显示光标

(2). 文字背景色彩数字: (颜色范围:40 - 49)

40:    黑色
41:    深红色
42:    绿色
43:    黄色
44:    蓝色
45:    紫色
46:    深绿色
47:    白色

(3). 文字前景色数字: (颜色范围: 30 - 39)

30:    黑色
31:    红色
32:    绿色
33:    黄色
34:    蓝色
35:    紫色
36:    深绿色
37:    白色

2. 使用例子:

Linux终端会解析这些控制码, 并且依据控制码来设置终端的绘制属性, 所以, 只要输出流中包含ANSI控制码就可以工作, 这里使用linux的echo命令来演示:  (你可以使用任何你熟悉的语言来代替...)

(1). 字体红色输出:   

查看上面的ANSI控制码可以知道: \033[30m -- \033[37m是控制前景色, 并且红色使用31表示, 即: 红色ANSI控制码为:  \033[31m

echo -e "\33[31m红色字体\33[0m"     #需要加上-e参数

从\033[31m处开始使用"红色"作为字体的前景色, 后面全部的绘制都使用红色, 直到遇到属性关闭控制码. 所以: 后面使用\033[0m来关闭属性, 要不然终端后面的输入的文字将全部是红色的. 效果图:

(2). 使用多个控制码产生叠加效果:  红色+高亮

echo -e "\033[31m\033[1m红色+高亮\033[0m"   #高亮控制码为: \033[1m

效果:

(3). 红底+白字+高亮+下划线:

echo -e "\033[41m\033[37m\033[1m\033[4m红底+白字+高亮+下划线\033[0m"

效果:

多个控制码可以一起使用, 从而看到叠加的效果, 控制码之间的顺序无所谓, 例如: 上面的高亮和下划线.  其他的控制码就可以自己试试了.

二. Linux终端进度条的实现:

了解了上面的Linux终端彩色打印, 就可以开始做出漂亮的终端进度条了.

1. 利用\r backspace符来制作进度条:

(1). 一个php例子如下:  (注意, php要使用printf, echo没用的)

1<?php 2for ($i = 0; $i <= 50; $i++) { 3 printf("mprogress: %d%% %s\r", $i * 2, str_repeat('#',$i) ); 4 usleep(1000 * 100); 5} 6echo "\n", "Done.\n"; 7?>

运行效果如下:

(2). 加上色彩:

(3). 进一步美化, 使用背景并且使用空格代替'#'字符:

1<?php 2for ($i = 0; $i <= 50; $i++) { 3 printf("mprogress: \033[41m\033[1m %d%% %s\r\033[0m", $i * 2, str_repeat(' ',$i) ); 4 usleep(1000 * 100); 5} 6echo "\n", "Done.\n"; 7?>

效果:

哈, 效果还不错呢.

(4). 终极美化, 将光标隐藏:

这个只要在里面加上隐藏光标的ANSI控制码就ok了, 不过记得要在后面将光标回复显示, 要不然后面终端就看不到光标了:

1<?php 2for ($i = 0; $i <= 50; $i++) { 3 printf("\033[?25lmprogress: \033[41m\033[1m %d%% %s\r\033[0m", $i * 2, str_repeat(' ',$i) ); 4 usleep(1000 * 100); 5} 6printf("\nDone.\n\033[?25h"); 7?>

效果:

到此Linux终端进度条制作完毕.

三. 一个C的进度条封装: 

1. progress.h头文件: 

1/** 2 * linux terminal progress bar (no thread safe). 3 * @package progress.h. 4 * 5 * @author chenxin <chenxin619315@gmail.com> 6 */ 7#ifndef progress_h 8#define progress_h 9 10#include <stdio.h> 11 12typedef struct { 13 char chr; /*tip char*/ 14 char *title; /*tip string*/ 15 int style; /*progress style*/ 16 int max; /*maximum value*/ 17 float offset; 18 char *pro; 19} progress_t; 20 21#define PROGRESS_NUM_STYLE 0 22#define PROGRESS_CHR_STYLE 1 23#define PROGRESS_BGC_STYLE 2 24 25extern void progress_init(progress_t *, char *, int, int); 26 27extern void progress_show(progress_t *, float); 28 29extern void progress_destroy(progress_t *); 30 31#endif /*ifndef*/

2. progress.c 源程序:

1/** 2 * linux terminal progress bar (no thread safe). 3 * @package progress.c 4 * 5 * @author chenxin <chenxin619315@gmail.com> 6 */ 7#include <stdio.h> 8#include <stdlib.h> 9#include <string.h> 10 11#include "progress.h" 12 13/** 14 * initialize the progress bar. 15 * @max = 0 16 * @val = 0 17 * 18 * @param style 19 * @param tip words. 20 */ 21extern void progress_init( 22 progress_t *bar, char *title, int max, int style) 23{ 24 bar->chr = '#'; 25 bar->title = title; 26 bar->style = style; 27 bar->max = max; 28 bar->offset = 100 / (float)max; 29 bar->pro = (char *) malloc(max+1); 30 if ( style == PROGRESS_BGC_STYLE ) 31 memset(bar->pro, 0x00, max+1); 32 else { 33 memset(bar->pro, 32, max); 34 memset(bar->pro+max, 0x00, 1); 35 } 36} 37 38extern void progress_show( progress_t *bar, float bit ) 39{ 40 int val = (int)(bit * bar->max); 41 switch ( bar->style ) 42 { 43 case PROGRESS_NUM_STYLE: 44 printf("\033[?25l\033[31m\033[1m%s%d%%\033[?25h\033[0m\r", 45 bar->title, (int)(bar->offset * val)); 46 fflush(stdout); 47 break; 48 case PROGRESS_CHR_STYLE: 49 memset(bar->pro, '#', val); 50 printf("\033[?25l\033[31m\033[1m%s[%-s] %d%%\033[?25h\033[0m\r", 51 bar->title, bar->pro, (int)(bar->offset * val)); 52 fflush(stdout); 53 break; 54 case PROGRESS_BGC_STYLE: 55 memset(bar->pro, 32, val); 56 printf("\033[?25l\033[31m\033[1m%s\033[41m %d%% %s\033[?25h\033[0m\r", 57 bar->title, (int)(bar->offset * val), bar->pro); 58 fflush(stdout); 59 break; 60 } 61} 62 63//destroy the the progress bar. 64extern void progress_destroy(progress_t *bar) 65{ 66 free(bar->pro); 67}

3. tst-pro.c测试程序:

1/** 2 * program bar test program. 3 * 4 * @author chenxin <chenxin619315@gmail.com> 5 */ 6#include "progress.h" 7#include <unistd.h> 8 9int main(int argc, char *argv[] ) 10{ 11 progress_t bar; 12 //progress_init(&bar, "", 50, PROGRESS_NUM_STYLE); 13 progress_init(&bar, "", 50, PROGRESS_CHR_STYLE); 14 //progress_init(&bar, "", 50, PROGRESS_BGC_STYLE); 15 16 int i; 17 for ( i = 0; i <= 50; i++ ) { 18 progress_show(&bar, i/50.0f); 19 sleep(1); 20 } 21 printf("\n+-Done\n"); 22 23 progress_destroy(&bar); 24 25 return 0; 26}

4. 测试效果: 

(1). PROGRESS_NUM_STYLE效果:

(2). PROGRESS_CHR_STYLE效果:

(3). PROGRESS_BGC_STYLE效果:

完毕. 代码托管到: http://git.oschina.net/lionsoul/ltpro

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )