From 1909dd475c27a9d12f1b408be70eb423c225ebf7 Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Sun, 23 Aug 2015 13:03:13 +0200 Subject: [PATCH] progress(): Very simple ASCII progress bar from troglobit/toolbox@f98c5d0 This patch adds a very simple progress bar I wrote once. It's revision f98c5d0 from https://github.com/troglobit/toolbox Also included in this patch is conio.h, a neat little set of macros for manipulating your terminal using ANSI escape seequences. Signed-off-by: Joachim Nilsson --- Makefile | 2 +- conio.h | 81 ++++++++++++++++++++++++++++++++++++++++++ progress.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 conio.h create mode 100644 progress.c diff --git a/Makefile b/Makefile index ad965bf..e1129ea 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ CPPFLAGS += -W -Wall DISTFILES = README LICENSE HEADERS = lite.h OBJS := chomp.o copyfile.o dir.o fexist.o fisdir.o fmode.o fsendfile.o -OBJS += ifconfig.o makepath.o pidfile.o pidfilefn.o rsync.o +OBJS += ifconfig.o makepath.o pidfile.o pidfilefn.o progress.o rsync.o OBJS += strlcpy.o strlcat.o strtonum.o tempfile.o tree.o DEPS := $(OBJS:.o=.d) JUNK = *~ *.bak *.map .*.d *.d DEADJOE semantic.cache *.gdb *.elf core core.* diff --git a/conio.h b/conio.h new file mode 100644 index 0000000..63dcb29 --- /dev/null +++ b/conio.h @@ -0,0 +1,81 @@ +/* A conio.h like implementation for VTANSI displays. + * + * Copyright (c) 2009-2013 Joachim Nilsson + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef CONIO_H_ +#define CONIO_H_ + +#include + +/* Attributes */ +#define RESETATTR 0 +#define BRIGHT 1 +#define DIM 2 +#define UNDERSCORE 4 +#define BLINK 5 /* May not work on all displays. */ +#define REVERSE 7 +#define HIDDEN 8 + +/* Colors for text and background */ +#define BLACK 0x0 +#define RED 0x1 +#define GREEN 0x2 +#define BROWN 0x3 +#define BLUE 0x4 +#define MAGENTA 0x5 +#define CYAN 0x6 +#define LIGHTGREY 0x7 + +#define DARKGREY 0x10 +#define LIGHTRED 0x11 +#define LIGHTGREEN 0x12 +#define YELLOW 0x13 +#define LIGHTBLUE 0x14 +#define LIGHTMAGENTA 0x15 +#define LIGHTCYAN 0x16 +#define WHITE 0x17 + +/* Esc[2JEsc[1;1H - Clear screen and move cursor to 1,1 (upper left) pos. */ +#define clrscr() fputs ("\e[2J\e[1;1H", stdout) +/* Esc[K - Erases from the current cursor position to the end of the current line. */ +#define clreol() fputs ("\e[K", stdout) +/* Esc[2K - Erases the entire current line. */ +#define delline() fputs ("\e[2K", stdout) +/* Esc[Line;ColumnH - Moves the cursor to the specified position (coordinates) */ +#define gotoxy(x,y) printf("\e[%d;%dH", y, x) +/* Esc[?25l (lower case L) - Hide Cursor */ +#define hidecursor() fputs ("\e[?25l", stdout) +/* Esc[?25h (lower case H) - Show Cursor */ +#define showcursor() fputs ("\e[?25h", stdout) + +/* Esc[Value;...;Valuem - Set Graphics Mode */ +#define __set_gm(attr,color,val) \ + if (!color) \ + printf("\e[%dm", attr); \ + else \ + printf("\e[%d;%dm", color & 0x10 ? 1 : 0, (color & 0xF) + val) +#define textattr(attr) __set_gm(attr, 0, 0) +#define textcolor(color) __set_gm(RESETATTR, color, 30) +#define textbackground(color) __set_gm(RESETATTR, color, 40) + +#endif /* CONIO_H_ */ + +/** + * Local Variables: + * version-control: t + * c-file-style: "ellemtel" + * End: + */ diff --git a/progress.c b/progress.c new file mode 100644 index 0000000..6d969c5 --- /dev/null +++ b/progress.c @@ -0,0 +1,102 @@ +/* Very simple termios based progress bar + * + * Copyright (c) 2012, 2013 Joachim Nilsson + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include /* INT_MAX */ +#include + +#include "conio.h" + +static char spinner(void) +{ + static int i = INT_MAX; + char *states = "|/-\\"; +// char *states = ".oOo"; +// char *states = ".oO°Oo."; +// char *states = "v<^>"; +// char *states = ".oO@*"; + + /* Subtract to get clockwise spinning. */ + return states[i-- % 4]; /* % Number of states */ +} + +void progress(int percent, int max_width) +{ + int i, bar = percent * max_width / 100; + + if (0 == percent) + hidecursor(); + + fprintf(stderr, "\r%3d%% %c [", percent, spinner()); + + for (i = 0; i < max_width; i++) { + if (i > bar) + fputc(' ', stderr); + else if (i == bar) + fputc('>', stderr); + else + fputc('=', stderr); + } + + fprintf(stderr, "]"); + if (100 == percent) { + showcursor(); + fputc('\n', stderr); + } +} + +#ifdef UNITTEST +#include /* atexit() */ +#include /* usleep() */ + +#define MAX_WIDTH 80 +#define msleep(msec) usleep(msec * 1000) + +static void bye(void) +{ + showcursor(); +} + +int main(int argc __attribute__((unused)), char const *argv[] __attribute__((unused))) +{ + int i, percent, block = 0, num = 85; + + atexit(bye); + hidecursor(); + + while (block < num) { + percent = block * 100 / num; + for (i = 0; i < 10; i++) { + progress(percent, MAX_WIDTH); + msleep(2); + } + block++; + msleep(50); + } + progress(100, MAX_WIDTH); + + return 0; +} +#endif /* UNITTEST */ + +/** + * Local Variables: + * compile-command: "gcc -g -I../../include -o unittest -DUNITTEST progress.c; and ./unittest" + * version-control: t + * indent-tabs-mode: t + * c-file-style: "linux" + * End: + */