Annotation of embedaddon/pimd/libite/progress.c, revision 1.1

1.1     ! misho       1: /* Simple termios based progress bar
        !             2:  *
        !             3:  * Copyright (c) 2012-2015  Joachim Nilsson <troglobit@gmail.com>
        !             4:  *
        !             5:  * Permission to use, copy, modify, and/or distribute this software for any
        !             6:  * purpose with or without fee is hereby granted, provided that the above
        !             7:  * copyright notice and this permission notice appear in all copies.
        !             8:  *
        !             9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            16:  */
        !            17: 
        !            18: #include <limits.h>            /* INT_MAX */
        !            19: #include <stdio.h>
        !            20: #include <string.h>
        !            21: 
        !            22: #include "conio.h"
        !            23: 
        !            24: #define SPINNER_THROB   ".oOo"
        !            25: #define SPINNER_PULSAR  ".oO°Oo."
        !            26: #define SPINNER_ARROW   "v<^>"
        !            27: #define SPINNER_STAR    ".oO@*"
        !            28: #define SPINNER_DEFAULT "|/-\\"
        !            29: 
        !            30: static char spinner(char *style)
        !            31: {
        !            32:        size_t num;
        !            33:        static unsigned int i = 0;
        !            34: 
        !            35:        if (!style)
        !            36:                style = SPINNER_DEFAULT;
        !            37:        num = strlen(style);
        !            38: 
        !            39:        return style[i++ % num]; /* % Number of states in style */
        !            40: }
        !            41: 
        !            42: /**
        !            43:  * progress - Advanced ASCII progress bar with spinner
        !            44:  * @percent: Start first call with this set to 0, end with 100
        !            45:  * @max_width: Max width of progress bar, in total characters.
        !            46:  *
        !            47:  * This function draws an advanced ASCII progressbar at the current
        !            48:  * line.  It always start from the first column.
        !            49:  *
        !            50:  * The progress bar will hide the cursor if started with @percent 0 and
        !            51:  * show it again at the end, when called with @percent 100.
        !            52:  *
        !            53:  * While being called with the same percentage the spinner will spin,
        !            54:  * to show the user the process hasn't frozen.
        !            55:  *
        !            56:  * If the output TTY cannot interpret control characters, like \r, it is
        !            57:  * advised to instead used the progress_simple() function.
        !            58:  */
        !            59: void progress(int percent, int max_width)
        !            60: {
        !            61:        int i, bar;
        !            62: 
        !            63:        /* Adjust for progress bar overhead */
        !            64:        max_width -= 10;
        !            65: 
        !            66:        if (0 == percent)
        !            67:                hidecursor();
        !            68: 
        !            69:        fprintf(stderr, "\r%3d%% %c [", percent, spinner(NULL));
        !            70: 
        !            71:        bar = percent * max_width / 100;
        !            72:        for (i = 0; i < max_width; i++) {
        !            73:                if (i > bar)
        !            74:                        fputc(' ', stderr);
        !            75:                else if (i == bar)
        !            76:                        fputc('>', stderr);
        !            77:                else
        !            78:                        fputc('=', stderr);
        !            79:        }
        !            80: 
        !            81:        fprintf(stderr, "]");
        !            82:        if (100 == percent) {
        !            83:                showcursor();
        !            84:                fputc('\n', stderr);
        !            85:        }
        !            86: }
        !            87: 
        !            88: void progress_simple(int percent)
        !            89: {
        !            90:        static int last = 1;
        !            91:        int ratio, numout;
        !            92: 
        !            93:        if (!percent && last) {
        !            94:                last = 0;
        !            95:                fputs("0%       25%       50%       75%       100%\n"
        !            96:                      "|---------+---------+---------+---------|\n"
        !            97:                      "|", stderr);
        !            98:                return;
        !            99:        }
        !           100: 
        !           101:        ratio = 40 * percent / 100;
        !           102:        numout = ratio - last;
        !           103: 
        !           104:        if (ratio <= last)
        !           105:                return;
        !           106: 
        !           107:        last = ratio;
        !           108: 
        !           109:        while (numout--) {
        !           110:                if (ratio != 40 || numout)
        !           111:                        putc('=', stderr);
        !           112:                else
        !           113:                        putc('|', stderr);
        !           114:        }
        !           115: }
        !           116: 
        !           117: #ifdef UNITTEST
        !           118: #include <stdlib.h>            /* atexit() */
        !           119: #include <unistd.h>            /* usleep() */
        !           120: 
        !           121: #define MAX_WIDTH    80
        !           122: #define msleep(msec) usleep(msec * 1000)
        !           123: 
        !           124: static void bye(void)
        !           125: {
        !           126:        showcursor();
        !           127: }
        !           128: 
        !           129: static void testit(int fn, int percent)
        !           130: {
        !           131:        if (fn)
        !           132:                progress(percent, MAX_WIDTH);
        !           133:        else
        !           134:                progress_simple(percent);
        !           135: }
        !           136: 
        !           137: static void test(int fn)
        !           138: {
        !           139:        int i, percent, block = 0, num = 85;
        !           140: 
        !           141:        while (block < num) {
        !           142:                percent = block * 100 / num;
        !           143:                for (i = 0; i < 10; i++) {
        !           144:                        testit(fn, percent);
        !           145:                        msleep(5);
        !           146:                }
        !           147:                block++;
        !           148:                msleep(10);
        !           149:        }
        !           150:        testit(fn, 100);
        !           151: }
        !           152: 
        !           153: int main(void)
        !           154: {
        !           155:        atexit(bye);
        !           156:        hidecursor();
        !           157: 
        !           158:        printf("\nAdvanced:\n");
        !           159:        test(1);
        !           160:        printf("\nSimple:\n");
        !           161:        test(0);
        !           162:        printf("\n");
        !           163: 
        !           164:        return 0;
        !           165: }
        !           166: #endif /* UNITTEST */
        !           167: 
        !           168: /**
        !           169:  * Local Variables:
        !           170:  *  compile-command: "make V=1 -f progress.mk"
        !           171:  *  version-control: t
        !           172:  *  indent-tabs-mode: t
        !           173:  *  c-file-style: "linux"
        !           174:  * End:
        !           175:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>