开源夏令营之foldcolumn工具及解决方案(二)确定表格属性、绘制表格

确定表格宽度

表格宽度默认是终端的列数宽度(如果不能获取终端的列数,默认值是80个半角英文字符宽度),用户可以另指定,需要注意的是,为了表格能较优雅的输出,表格宽度=各列宽度之和+列分隔符占的宽度,在确定列宽的时候,表格宽度保持不变。

确定表格列数

表格的列数由表格第一行的列数确定,第一行是第一行非模式匹配原样输出的行。需要用户确保每行的列数相等,如果某行中列数如果多于表格列数,多于的列被忽略;如果某行列数少于表格的列数,以空列补齐。

确定表格列宽

考虑到中文等,为了表格的能正常显示,定义表格列的最小宽度为foco_COLWIDTH_MIN,其值大于等于2个半角英文字符宽度;同时要确保各列宽度与列分隔符宽度之和等于表格宽度

读取一遍文件确定列宽方法

这种情况下,可以指定某些列不需要换行输出,该列采用其各行中最宽的宽度为列宽(这显然需要先读入一遍文件确定,因此这只适合于从文件输入)。   

基本方法是读取一遍文件,统计每列的所有字符宽度,列宽就是此列的字符宽度占文件所有字符宽度的比例,原样输出的行和不换行的列不在统计范围之内,特别注意的是要确保各列宽度不小于表格列最小宽度,这里采用先为每列预留出最小宽度的方法。注意如果正常列的字符宽度和是0,此时这些列均分未分配的宽度。 

/* 代码参见libfoldcolumn/foldcolumn.c */
void foco_initColsWidthByReadFile(foco_t*pFoco,void**inFiles,foco_argv_t type,int fNum){
         for(每个文件中的一行数据){
                if(!该行原样输出){
                        if(还未确定表格列数)
                                表格列数 pFoco->colNum=本行列数;
                        for(该行中的每一列i)
                                if(用户指定该列不换行){
                                        pFoco->widths[i]=max(pFoco->widths[i],该行中第i列字符宽度);
                                }else{
                                        pFoco->widths[i]+=该行中第i列字符宽度;
                                        sumWidth+=该行中第i列字符宽度;
                                }
                }
        }
        /*表格未分配的宽度*/
        leftWidth=pFoco->width;
        /*确保各列宽度 大于等于 表格列最小宽度*/
        for(表格的每一列){
                if(用户指定该列不换行){
                        pFoco->widths[i]=max(pFoco->widths[i],列最小宽度);
                        leftWidth-=pFoco->widths[i];
                }else{
                        pFoco->widths[i]+=该行中第i列字符宽度;
                        sumWidth+=该行中第i列字符宽度;
                }
                /*正常列个数*/
                ++colNum;
        }
        /*为各正常列预留最小列宽*/
        leftWidth-= colNum*列最小宽度;
        /*减去列分隔符宽度*/
        leftWidth=foco_minusDeliWidth(pFoco,leftWidth);
        for(表格的每一正常列){
              if(width>0)
                     pFoco->widths[colIndex]=(double)pFoco->widths[colIndex]/width*leftWidth;
              else
                      pFoco->widths[colIndex]=leftWidth/notMatchNum;
              pFoco->widths[i]+=列最小宽度
        }
        为确保各列宽度与列分隔符和等于表格宽度,需将表格剩余宽度附加到最后一列
}

用户指定列宽

用户指定部分或全部列宽度,其余列均分剩余未分配的宽度,此方法适用性好,适用于从文件、管道等读入数据。

/*
 * 表格列数为pFoco->colNum
 * 用户指定的列宽数为pFoco->widthsNum
 * 用户指定的列宽存储在pFoco->widths中
 */
void foco_specifyColsWidth(foco_t*pFoco){
        /*判断列宽的有效性,如果有效返回table width - sum(pFoco->widths[i]);*/
        /*0=<i<用户指定的列宽数与表格的实际列宽数之间的较小者*/
        int leftWidth=foco_isValidColsWidth(pFoco);
        /*减去列分隔符宽度*/
        leftWidth=foco_minusDeliWidth(pFoco,leftWidth);
        /*用户已指定列宽的列数*/
        int i=pFoco->widthsNum;
        if(leftWidth<0){
            /*column width error*/
            exit(1);
        }
        /*注意最后一列列宽,确保表格宽度等于各列宽度与列分隔符宽度之和 */
        if(pFoco->colNum > pFoco->widthsNum){
            /*用户指定的列宽数小于表格的列数,未指定列均分剩余宽度*/
            average=leftWidth/(pFoco->colNum-pFoco->widthsNum);
            /*平均值小于最小列宽*/
            if(average<foco_COLWIDTH_MIN){
                /*column width error*/
                exit(1);
            }
            for(i;i<pFoco->colNum-1;++i)
                pFoco->widths[i]=average;
            /*last column width*/
            pFoco->widths[i]=leftWidth-average*(pFoco->colNum-pFoco->widthsNum-1);
        }else{
            /* 用户指定的列宽数大于表格的列数,将剩余宽度加在最后一列上*/
            pFoco->widths[pFoco->colNum-1]+=leftWidth;
        }
        pFoco->widthsNum=pFoco->colNum;
}

 
以上两种方法均存在超宽换行时,在单词中间换行的问题,一种的方法是在单词中间添加连字符,另一种是动态调整列宽,且动态调整列宽的方法只适合与从文件输入数据,这点我还在考虑怎样实现。  

表格列对齐方式的实现

用户可以指定每列的对齐方式,如果用户不指定,默认是数字采用右对齐,其他左对齐,对齐方式通过列内填充空格实现,同在考虑中。

注:列内补齐填充空格字符,行、列分隔符以及填充字符均是半角。

支持的表格样式

样式一

列间用space分隔,行间(文本行,不是表格行)采用空行分隔,如下图所示:

样式二

行间采用'-'分隔,列间采用space分隔,如下图所示:


样式三

列间采用'|'分隔,行间采用空行分隔,如下图所示:


样式四

采用box-drawing characters(参见开源夏令营之foldcolumn工具及解决方案之box-drawing character)画表,如下图所示:


表格绘制的实现

确定了表格的上述属性后,接下来就是循环读如一行数据,将数据以分隔符分列,然后 输出行分隔符,循环输出列、列分隔符进行表格输出。

下面是简单的结合表格样式和表格列宽的不同选择方法的简单测试,命令行参数-t选择表格样式,-w指定部分列宽,其余均分,不指定-w参数将先读入一遍文件进行列宽选择。

读一遍文件按字符宽度比例确定列宽







各列均分表格宽度







指定部分列宽








自动换行效果


右对齐实现


下一步计划

**目前程序对第一行的依赖很重,如表格列数取决与第一行,需要考虑一种比较好的解决办法;

**着重考虑换行断单词问题;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值