首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >彩色打印- ANSI逃逸序列控制台编写器迷你库

彩色打印- ANSI逃逸序列控制台编写器迷你库
EN

Code Review用户
提问于 2016-09-21 02:47:16
回答 1查看 75关注 0票数 3

这是我很久以前写的。我回到那里,决定把它弄干净一点。

它使用预处理器和C99 anon structs来制作灵活的类python API来调用其函数。

着色剂c

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>

#include "colorprint.h"

static const char *numch = "0123456789";

static void
apply_effect(char *out, enum fx fx)
{/*{{{*/
    char buf[3] = { numch[fx - 1], ';' };

    strcat(out, buf);
}/*}}}*/

static void
apply_fg(char *out, enum color c)
{/*{{{*/
    char buf[4] = { '3', numch[c - 1], 'm' };

    strcat(out, buf);
}/*}}}*/

static void
apply_bg(char *out, enum color c)
{/*{{{*/
    char buf[4] = { '4', numch[c - 1], ';' };

    strcat(out, buf);
}/*}}}*/

static void
apply_fx(char *out, enum fx *fx)
{/*{{{*/
    for(int i = 0; fx[i]; i++)
        apply_effect(out, fx[i]);
}/*}}}*/

static void
apply_colors(char *out, struct cpoptions *cpo)
{/*{{{*/
    if(cpo->bg)
        apply_bg(out, cpo->bg);

    if(cpo->fg)
        apply_fg(out, cpo->fg);
}/*}}}*/

void
_cprint(struct cpoptions *cpo)
{/*{{{*/
    char options[30] = "";

    apply_fx(options, cpo->fx);
    apply_colors(options, cpo);

    if(!cpo->fg && !cpo->bg && !cpo->fx[0])
         fputs(cpo->string, stdout);
    else
        printf("\e[%s%s\e[0m", options, cpo->string);
}/*}}}*/

void
_cputs(struct cpoptions *cpo)
{/*{{{*/
    _cprint(cpo);
    putchar('\n');
}/*}}}*/

着色剂h

代码语言:javascript
复制
#define func(name, type, ...) \
    name(&(type){.header = 0, __VA_ARGS__})

enum color {
    color_invalid,
    color_black,
    color_red, 
    color_green,
    color_yellow,
    color_blue,
    color_purple,
    color_aqua, 
    color_white
};

enum fx {
    fx_invalid,
    fx_plain,
    fx_bold,
    fx_dark,
    fx_italic,
    fx_underline,
    fx_light,
    fx_light2,
    fx_reverse,
    fx_blink,
    fx_strike
};

struct cpoptions {
    char header;
    char *string;
    enum fx fx[10];
    enum color fg;
    enum color bg;
};

void _cprint(struct cpoptions *cpo);
void _cputs(struct cpoptions *cpo);

#define cprint(...) func(_cprint, struct cpoptions, __VA_ARGS__)
#define cputs(...) func(_cputs, struct cpoptions, __VA_ARGS__)

/* Example: 
 *      cprint("Hello World", .fg = color_green, .fx = {fx_bold, fx_italic, fx_strike});
 * Or: 
 *      struct cpoptions cpo = {
 *          .string = "Hello World",
 *          .fg = color_green,
 *          .fx = {
 *              fx_bold,
 *              fx_italic,
 *              fx_strike
 *          }
 *      };
 *      _cprint(&cpo);
 */

它的使用范围在复杂性范围内

代码语言:javascript
复制
cputs("Hello World"); // prints "Hello World\n"

代码语言:javascript
复制
cputs( .string = "Hello World",
       .fg = color_green,
       .bg = color_red,
       .fx = {
           fx_bold,
           fx_strike,
           fx_italic
        }
); // prints "\e[1;9;3;41;32mHello World\e[0m\n", which appears as "Hello World" with a red background, green foreground, with bold+strikethrough+italic effects

在我看来,这种函数调用方法比可怕的va_args更加类型安全和通用。这也很好,因为它允许五颜六色的输出,而不需要ncursestermcap的开销。

EN

回答 1

Code Review用户

回答已采纳

发布于 2016-09-22 01:33:33

  1. 体系结构: IMO,相信char *缓冲区不会溢出的时间已经过去了。传入一个size_t size并检查函数调用中的有效大小。
  2. static const char *numch = "0123456789";没有什么价值,它的应用会在不受约束的输入上造成UB。与其将其转换为数字字符,不如添加'0',根据需要进行偏移。numch[fx - 1] -> fx - 1 + '0'
  3. 使用_的全局函数是实现的保留。用不同的名字。// void _cprint( *cpo) void cp_print( *cpo)
  4. \e是一个非标准的转义序列.使用\033或. // printf(“\e][%S%S\e[0m”#define 27 printf)(%c[%1996%\e]e[0m“,ESC )
  5. colorprint.h应该有一个保护性的#ifndef来应对再中心性。#ifndef colorprint_h #定义colorprint_h . //现有内容#endif
  6. 我发现Nth项枚举颜色{ color_invalid,color_white,color_N // add };if (value >= color_N) Handle_InvalidValue(value);
  7. 很高兴在.h文件中使用示例。建议使用#if 0括号,因为它不会停止语法突出显示。
  8. 迂回:size_t是用于数组索引的类型,而不是int。相应地编写代码,请记住size_t是一些无符号类型。
  9. 名称空间colorprint.hcolor_...fx_...cp...一起滥用名称空间。建议一个更统一的前缀。cp...并不是很糟糕,但是可以使用cp.h
  10. 避免神奇的数字-为什么是30?除了-1,0,1,2,也许还有42以外,其他数字都值得一个宏或const对象。char选项30= "";
  11. 不要在"colorprint.h"之前包含文件。"colorprint.c"应该这样做,以确保"colorprint.h"不依赖于某些<*.h>文件。
  12. 整理,移除/*{{{*/等。
  13. 很好地使用了static函数。
  14. 类似打印的函数应该返回int。/ void _cprint( int _cprint( .)int i= printf("\e[%s%s\e[0m",options,cpo->string);返回i;}
  15. func非常常见,不能用作宏名// #定义函数(名称、类型、.)\#定义cp_func(名称、类型、.)\
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/141985

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档