首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >彩色印刷.第2部分

彩色印刷.第2部分
EN

Code Review用户
提问于 2016-09-22 19:37:19
回答 1查看 54关注 0票数 0

这是上一次审查遵循元规则的后续行动。

最后,我发布了一个名为colorprint的小型库,并从他的回答中的chux获得了一些有用的指针。

着色剂c

代码语言:javascript
复制
#include "colorprint.h"

#include <stdio.h>
#include <string.h>

#define CP_BUFSZ ((3 * 2) + (2 * (CP_FX_END - 1)) + 1)

enum validate_error {
    VE_OK,
    VE_FXTOOLARGE,
    VE_TOOMANYFX,
    VE_FGTOOLARGE,
    VE_BGTOOLARGE,
    VE_BADSTRING,
    VE_END
};

const char *validate_error_str[VE_END] = {
    [VE_FXTOOLARGE] = "(.fx) one or more effect values are out of bounds",
    [VE_TOOMANYFX]  = "(.fx) too many effects (the \"trap\" effect was set)",
    [VE_FGTOOLARGE] = "(.fg) foreground color out of bounds",
    [VE_BGTOOLARGE] = "(.bg) background color out of bounds",
    [VE_BADSTRING]  = "(.string) no string provided"
};

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

    strcat(out, buf);
}

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

    strcat(out, buf);
}

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

    strcat(out, buf);
}

static void
apply_fx(char *out, enum fx *fx)
{
    for(int i = 0; i < CP_FX_END - 1 && 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);
}

static enum validate_error
validate_cpo(struct cpoptions *cpo)
{
    for(int i = 0; i < CP_FX_END - 1 && cpo->fx[i]; i++)
        if(cpo->fx[i] >= CP_FX_END)
            return VE_FXTOOLARGE;

    if(cpo->fx[CP_FX_END - 1] != CP_FX_INVALID)
        return VE_TOOMANYFX;

    if(cpo->fg >= CP_COLOR_END)
        return VE_FGTOOLARGE;

    if(cpo->bg >= CP_COLOR_END)
        return VE_BGTOOLARGE;

    if(cpo->string == NULL)
        return VE_BADSTRING;

    return VE_OK;
}

int
cprint_default(struct cpoptions *cpo)
{
    char options[CP_BUFSZ] = "";
    enum validate_error ve;

    if((ve = validate_cpo(cpo)) != VE_OK){
        fprintf(stderr, "colorprint: An error occurred. Details: E%03u (%s)\n", ve, validate_error_str[ve]);
        return -1;
    }

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

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

int
cputs_default(struct cpoptions *cpo)
{
    int ret = cprint_default(cpo);

    putchar('\n');
    return ret;
}

着色剂h

代码语言:javascript
复制
#ifndef COLORPRINT_H
#define COLORPRINT_H

#define CPFUNC(name, type, ...) \
    name(&(type){__VA_ARGS__})

enum color {
    CP_COLOR_INVALID,
    CP_COLOR_BLACK,
    CP_COLOR_RED, 
    CP_COLOR_GREEN,
    CP_COLOR_YELLOW,
    CP_COLOR_BLUE,
    CP_COLOR_PURPLE,
    CP_COLOR_AQUA, 
    CP_COLOR_WHITE,
    CP_COLOR_END
};

enum fx {
    CP_FX_INVALID,
    CP_FX_PLAIN,
    CP_FX_BOLD,
    CP_FX_DARK,
    CP_FX_ITALIC,
    CP_FX_UNDERLINE,
    CP_FX_LIGHT,
    CP_FX_LIGHT2,
    CP_FX_REVERSE,
    CP_FX_BLINK,
    CP_FX_STRIKE,
    CP_FX_END
};

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

int cprint_default(struct cpoptions *cpo);
int cputs_default(struct cpoptions *cpo);

#define cprint(...) CPFUNC(cprint_default, struct cpoptions, __VA_ARGS__)
#define cputs(...) CPFUNC(cputs_default, struct cpoptions, __VA_ARGS__)

#if 0

Example: 

    cprint("Hello World", .fg = CP_COLOR_GREEN, .fx = {CP_FX_BOLD, CP_FX_ITALIC, CP_FX_STRIKE});

Or... 

    struct cpoptions cpo = {
        .string = "Hello World",
        .fg = CP_COLOR_GREEN,
        .fx = {
            CP_FX_BOLD,
            CP_FX_ITALIC,
            CP_FX_STRIKE
        }
    };

    cprint_default(&cpo);

#endif

#endif

我要说的是,我不是#if 0风格评论的粉丝,这是由chux在他的回答中提出的。我个人觉得这个更容易读懂:

代码语言:javascript
复制
/*
 *
 *  Example: 
 *
 *      cprint("Hello World", .fg = CP_COLOR_GREEN, .fx = {CP_FX_BOLD, CP_FX_ITALIC, CP_FX_STRIKE});
 *
 *  Or... 
 *
 *      struct cpoptions cpo = {
 *          .string = "Hello World",
 *          .fg = CP_COLOR_GREEN,
 *          .fx = {
 *              CP_FX_BOLD,
 *              CP_FX_ITALIC,
 *              CP_FX_STRIKE
 *          }
 *      };
 *
 *      cprint_default(&cpo);
 *
 */

因为左侧的*创建了一个边距,使得垂直扫描和查看注释的开始和结束位置变得非常容易。

所以我可能会在某个时候把它改回来。

EN

回答 1

Code Review用户

发布于 2016-09-22 20:30:36

我发现了一些问题,并且已经解决了。因此,我将在这里张贴他们的回答风格,而不是打破规则和编辑的问题。

1. fx枚举值不是完全准确的

56 (LIGHT, LIGHT2)实际上产生眨眼效应,而8 (BLINK)则产生“不可见”的效果。

代码语言:javascript
复制
// CP_FX_LIGHT,
// CP_FX_LIGHT2,
CP_FX_BLINK,
CP_FX_BLINK2,
...
// CP_FX_BLINK,
CP_FX_HIDDEN

2. Bug:仅应用背景色会破坏转义序列

代码语言:javascript
复制
cputs("Hello World", .bg = CP_COLOR_BLUE);
// "?[44;Hello World?[0m"

谨慎的做法是检查这一点:

代码语言:javascript
复制
if(cpo->fg)
    apply_fg(out, cpo->fg);
else
    // terminate the escape sequence
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

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

复制
相关文章

相似问题

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