Linux終端彩色打印+終端進度條

開發的一個應用程序選擇了終端界面, 爲了使軟件稍微好看些, 研究下Linux終端的彩色打印, 而且基於這個彩色打印實現了幾種進度條, 在此總結下: (更多的是以爲這個東西挺好玩的... ) php

一. 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:    白色 linux

(3). 文字前景色數字: (顏色範圍: 30 - 39)

30:    黑色
31:    紅色
32:    綠色
33:    黃色
34:    藍色
35:    紫色
36:    深綠色
37:    白色 git

2. 使用例子:

Linux終端會解析這些控制碼, 而且依據控制碼來設置終端的繪製屬性, 因此, 只要輸出流中包含ANSI控制碼就能夠工做, 這裏使用linux的echo命令來演示:  (你能夠使用任何你熟悉的語言來代替...) shell

(1). 字體紅色輸出:    網絡

查看上面的ANSI控制碼能夠知道: \033[30m -- \033[37m是控制前景色, 而且紅色使用31表示, 即: 紅色ANSI控制碼爲:  \033[31m 測試

echo -e "\33[31m紅色字體\33[0m"     #須要加上-e參數


從\033[31m處開始使用"紅色"做爲字體的前景色, 後面所有的繪製都使用紅色, 直到遇到屬性關閉控制碼. 因此: 後面使用\033[0m來關閉屬性, 要否則終端後面的輸入的文字將所有是紅色的. 效果圖: 字體

(2). 使用多個控制碼產生疊加效果:  紅色+高亮 spa

echo -e "\033[31m\033[1m紅色+高亮\033[0m"   #高亮控制碼爲: \033[1m

效果: .net

(3). 紅底+白字+高亮+下劃線: code

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

相關文章
相關標籤/搜索