转自:https://my.oschina.net/jcseg/blog/178047

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

一. Linux终端色彩打印:

1. 属性介绍: 

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

\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;H                设置光标位置
\033[2J                 清屏
\033[K                  清除从光标到行尾的内容
\033[s                  保存光标位置
\033[u                  恢复光标位置
\033[?25l               隐藏光标
\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没用的)

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

运行效果如下:

(2). 加上色彩:

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

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

效果:

哈, 效果还不错呢.

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

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

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

效果:

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

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

1. progress.h头文件:

/**
* linux terminal progress bar (no thread safe).
* @package progress.h.
*
* @author chenxin <chenxin619315@gmail.com>
*/
#ifndef progress_h
#define progress_h #include <stdio.h> typedef struct {
char chr; /*tip char*/
char *title; /*tip string*/
int style; /*progress style*/
int max; /*maximum value*/
float offset;
char *pro;
} progress_t; #define PROGRESS_NUM_STYLE 0
#define PROGRESS_CHR_STYLE 1
#define PROGRESS_BGC_STYLE 2 extern void progress_init(progress_t *, char *, int, int); extern void progress_show(progress_t *, float); extern void progress_destroy(progress_t *); #endif /*ifndef*/

2. progress.c 源程序:

/**
* linux terminal progress bar (no thread safe).
* @package progress.c
*
* @author chenxin <chenxin619315@gmail.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include "progress.h" /**
* initialize the progress bar.
* @max = 0
* @val = 0
*
* @param style
* @param tip words.
*/
extern void progress_init(
progress_t *bar, char *title, int max, int style)
{
bar->chr = '#';
bar->title = title;
bar->style = style;
bar->max = max;
bar->offset = 100 / (float)max;
bar->pro = (char *) malloc(max+1);
if ( style == PROGRESS_BGC_STYLE )
memset(bar->pro, 0x00, max+1);
else {
memset(bar->pro, 32, max);
memset(bar->pro+max, 0x00, 1);
}
} extern void progress_show( progress_t *bar, float bit )
{
int val = (int)(bit * bar->max);
switch ( bar->style )
{
case PROGRESS_NUM_STYLE:
printf("\033[?25l\033[31m\033[1m%s%d%%\033[?25h\033[0m\r",
bar->title, (int)(bar->offset * val));
fflush(stdout);
break;
case PROGRESS_CHR_STYLE:
memset(bar->pro, '#', val);
printf("\033[?25l\033[31m\033[1m%s[%-s] %d%%\033[?25h\033[0m\r",
bar->title, bar->pro, (int)(bar->offset * val));
fflush(stdout);
break;
case PROGRESS_BGC_STYLE:
memset(bar->pro, 32, val);
printf("\033[?25l\033[31m\033[1m%s\033[41m %d%% %s\033[?25h\033[0m\r",
bar->title, (int)(bar->offset * val), bar->pro);
fflush(stdout);
break;
}
} //destroy the the progress bar.
extern void progress_destroy(progress_t *bar)
{
free(bar->pro);
}

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

/**
* program bar test program.
*
* @author chenxin <chenxin619315@gmail.com>
*/
#include "progress.h"
#include <unistd.h> int main(int argc, char *argv[] )
{
progress_t bar;
//progress_init(&bar, "", 50, PROGRESS_NUM_STYLE);
progress_init(&bar, "", 50, PROGRESS_CHR_STYLE);
//progress_init(&bar, "", 50, PROGRESS_BGC_STYLE); int i;
for ( i = 0; i <= 50; i++ ) {
progress_show(&bar, i/50.0f);
sleep(1);
}
printf("\n+-Done\n"); progress_destroy(&bar); return 0;
}

4. 测试效果:

(1). PROGRESS_NUM_STYLE效果:

(2). PROGRESS_CHR_STYLE效果:

(3). PROGRESS_BGC_STYLE效果:

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

Linux终端彩色打印+终端进度条【转】的更多相关文章

  1. Linux shell 下简单的进度条实现

    Linux shell 下简单的进度条实现 [root@db145 ~]# cat print_process.sh function Proceess(){ spa='' i= ] do print ...

  2. Linux中的小程序—— 进度条

    在说正事之前,首先科普一下在什么是回车什么是换行? 我们通常所说的回车就是从一行的末尾跳到另一行的开头,但事实上这却是由回车和换行两个动作所完成的,也就是键盘上<enter>所完成的工作. ...

  3. linux和pycharm下终端彩色打印输出

    实际上linux终端是调用ANSI控制码来实现终端彩色输出.终端的字符颜色由转义序列(Escape Sequence)控制,是文本模式下的系统显示功能,与具体语言无关. 转义序列以控制字符'ESC'开 ...

  4. 【451】python 同一行打印进度条

    参考:Python3 Print 同一行打印显示进度条效果 参考:\r\n, \r and \n what is the difference between them? [duplicate] 参考 ...

  5. (数据科学学习手札91)在Python中妥善使用进度条

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在日常运行程序的过程中常常涉及到循环迭代过程,对 ...

  6. 用 Python 写出这样的进度条,刷新了我对进度条的认知

    ❞ 1 简介 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的知识.那么针对这三类人,我给 ...

  7. 【Python】文本进度条

    1.0代码: import time#引入time库 scale=10#文本进度条宽度 print("------执行开始------") for i in range(scale ...

  8. python 实现各种进度条

    1. 时间进度条 class Tiao(object): def __init__(self): self.obj1 = datetime.timedelta(seconds=1) self.var ...

  9. Python进度条模块tqdm实现任务进度可视化

    一.前言 tqdm 是一个易用性强.扩展性高的 Python 进度条库,可以在 Python 长循环中添加一个进度提示信息,我们只需要封装任意的迭代器 tqdm(iterator) 即可. 二.安装 ...

随机推荐

  1. Codeforces Round #345 Div.1 D.Zip-line 动态最长上升子序列

    题意概述: 给出一个长度为N的序列和M组询问,问假设把某个位置的值改成另一个给出的值之后,序列的最长上升子序列的长度. N,M<=400000. 分析: 考虑某个位置的值改动后这个位置和最长上升 ...

  2. MySQL初识2

    用python调用mysql的一些方法总结: 1.编码声明: # encoding: UTF-8#!/usr/bin/python 在开头处进行声明,避免出现输入中文时,提示声明错误(当然输入中文出现 ...

  3. js调用本地office打开服务器的office文件预览

    本来是想做成直接在网页上在线预览office文件的,但是找了好多,要不是收费,要不就是要调用别人的API不安全,所以纠结了好久还是用调用本地的office预览office文件. 废话不多说,那么怎么调 ...

  4. HDU 1338 Game Prediction

    http://acm.hdu.edu.cn/showproblem.php?pid=1338 Problem Description Suppose there are M people, inclu ...

  5. 11大精选Android自学网站

    无论是从事什么开发,只要是软件行业,不断的更新迭代自己掌握的知识是少不了的.相信干过程序猿的童鞋都清楚,如果要在技术上有所提升,工作之余的不断学习是少不了的.今天小编为大家分享的就是一些比较有用的学习 ...

  6. [bzoj1052] [HAOI2007]覆盖问题

    Description 某人在山上种了N棵小树苗.冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄膜把这些小树遮盖起来,经过一番长久的思考,他决定用3个L * L的正方形塑料薄膜 ...

  7. [洛谷P3690]【模板】Link Cut Tree (动态树)

    题目大意:给定$n$个点以及每个点的权值,要你处理接下来的$m$个操作.操作有$4$种.操作从$0到3编号.点从1到n编号. $0,x,y$:代表询问从$x$到$y$的路径上的点的权值的$xor$和. ...

  8. 洛谷 P1268 树的重量 解题报告

    P1268 树的重量 题目描述 树可以用来表示物种之间的进化关系.一棵"进化树"是一个带边权的树,其叶节点表示一个物种,两个叶节点之间的距离表示两个物种的差异.现在,一个重要的问题 ...

  9. fastjson解析服务端返回的数据

    1.配置依赖 //fastjson api 'com.alibaba:fastjson:1.2.44' 2.设计服务端返回的数据 {},{},{}]} 3.编写bean类,特别注意,要和服务端返回的类 ...

  10. lwIP配置文件opt.h和lwipopts.h

    如何去配置lwip,使它去适合不同大小的脚,这就是lwIP的配置问题.尤其是内存的配置,配置多了浪费,配置少了跑不了或者不稳定(会出现的一大堆莫名奇妙的问题,什么打开网页的速度很慢啊?什么丢包啊,什么 ...