summaryrefslogtreecommitdiff
path: root/src/util/hbar.c
diff options
context:
space:
mode:
authordavidovski <david@davidovski.xyz>2022-06-27 01:14:42 +0100
committerdavidovski <david@davidovski.xyz>2022-06-27 01:14:42 +0100
commit7bba6cd7612293796e905885f9ed3072877798ab (patch)
treedd01942dbdd474a4df62ecf74479f5e78d83f1c8 /src/util/hbar.c
parent79fb6f41104cd0d88891598ddfc3c30d1bb0352d (diff)
added shmk, building all with shmk
Diffstat (limited to 'src/util/hbar.c')
-rw-r--r--src/util/hbar.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/util/hbar.c b/src/util/hbar.c
new file mode 100644
index 0000000..59cf888
--- /dev/null
+++ b/src/util/hbar.c
@@ -0,0 +1,171 @@
+/*
+ * hbar
+ *
+ * create a horizontal progres bar across the screen
+ */
+
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <unistr.h>
+#include <stdbool.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "colors.h"
+
+#define DEFAULT_COLOR BLACK BG_WHITE
+#define DEFAULT_RESET WHITE BG_DEFAULT
+
+#define SAVE_POS "\033[s"
+#define LOAD_POS "\033[u"
+
+void human_format(int bytes, char *output) {
+ char *suffix[] = {"B", "KB", "MB", "GB", "TB"};
+ char length = sizeof(suffix) / sizeof(suffix[0]);
+
+ int i = 0;
+ double dblBytes = bytes;
+
+ if (bytes > 1024) {
+ for (i = 0; (bytes / 1024) > 0 && i<length-1; i++, bytes /= 1024)
+ dblBytes = bytes / 1024.0;
+ }
+
+ sprintf(output, "%.0lf%s", dblBytes, suffix[i]);
+}
+
+size_t len(char *s) {
+ size_t len = 0;
+ for (; *s; s++)
+ if ((*s & 0XC0) != 0x80)
+ len++;
+ return len;
+}
+
+void printat(char *s, size_t index) {
+ index++;
+ for (; *s; s++) {
+ if ((*s & 0XC0) != 0x80) {
+ if (index <= 0)
+ return;
+ index--;
+ }
+ if (index <= 0) {
+ fwrite(s, 1, 1, stdout);
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ struct winsize w;
+ ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
+ int width = w.ws_col;
+
+ char *text = "";
+ char *unit = "";
+ int total = 0;
+ int completed = 0;
+ int line = 0;
+ bool terminate = false;
+ bool human = false;
+
+ char *color = DEFAULT_COLOR;
+ char *reset = DEFAULT_RESET;
+
+ int opt;
+ int option_index = 0;
+
+ const char *optstring = "T:u:c:r:l:th";
+ static const struct option opts[] = {
+ {"text", required_argument, 0, 'T'},
+ {"unit", optional_argument, 0, 'u'},
+ {"color", optional_argument, 0, 'c'},
+ {"reset", optional_argument, 0, 'r'},
+ {"line", optional_argument, 0, 'l'},
+ {"terminate", no_argument, 0, 't'},
+ {"human-readable", no_argument, 0, 'h'}
+ };
+
+ while ((opt = getopt_long(argc, argv, optstring, opts, &option_index)) != -1) {
+ switch (opt) {
+ case 'T':
+ text = optarg;
+ break;
+ case 'c':
+ color = optarg;
+ break;
+ case 'r':
+ reset = optarg;
+ break;
+ case 'u':
+ unit = optarg;
+ break;
+ case 't':
+ terminate = true;
+ break;
+ case 'h':
+ human = true;
+ break;
+ case 'l':
+ line = atoi(optarg);
+ break;
+ }
+ }
+
+
+ if (argc < optind + 2) {
+ printf(RESET "\n");
+ return 1;
+ }
+
+ completed = atoi(argv[optind]);
+ total = atoi(argv[optind+1]);
+
+ if (line != -1)
+ printf("\033[%dA", line, 0);
+
+ char *count = malloc(width);
+ if (human) {
+ char *c = malloc(width);
+ char *t = malloc(width);
+ human_format(completed, c);
+ human_format(total, t);
+ sprintf(count, "[%s%s/%s%s]", c, unit, t, unit);
+ } else {
+ sprintf(count, "[%d%s/%d%s]", completed, unit, total, unit);
+ }
+
+ printf(RESET "\r");
+ printf(color);
+ for (int i = 0; i <= width; i++) {
+ int reset_at = 0;
+ if (total > 0) {
+ float percent = (float) completed / (float) total;
+ reset_at = percent * width;
+ }
+
+ if (i == reset_at) {
+ printf(reset);
+ }
+
+ if (text && i < len(text)) {
+ printat(text, i);
+ } else if (i + 1 > width - len(count)) {
+ printat(count, i - width + len(count));
+ } else {
+ printf(" ");
+ }
+ }
+
+ if (line != -1) {
+ printf("\033[%dB", line);
+ }
+ if (terminate) {
+ printf(RESET "\n");
+ }
+
+ return 0;
+}
+