ervy

Bring charts to terminal.
git clone https://noulin.net/git/ervy.git
Log | Files | Refs | README | LICENSE

commit 91faf1d7c8c56ea1ca8ad8ad55ab41f42167dbb8
parent 3774ac899b83777408be7219200d9174f3c444a2
Author: Remy Noulin <loader2x@gmail.com>
Date:   Sat,  9 Feb 2019 15:22:42 +0100

add bar

.gitignore   |  11 ++++++
README.md    |  19 ++++++++++-
bar.c        | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
bar.h        |   5 +++
ervy.c       |   0
ervy.h       |   3 ++
example.c    |  49 +++++++++++++++++++++++++++
imgs/bar.png | Bin 0 -> 1171 bytes
package.yml  |  37 ++++++++++++++++++++
utils.c      |  55 ++++++++++++++++++++++++++++++
utils.h      |  13 +++++++
11 files changed, 300 insertions(+), 1 deletion(-)

Diffstat:
M.gitignore | 11+++++++++++
MREADME.md | 19++++++++++++++++++-
Abar.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abar.h | 5+++++
Aervy.c | 0
Aervy.h | 3+++
Aexample.c | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Aimgs/bar.png | 0
Apackage.yml | 37+++++++++++++++++++++++++++++++++++++
Autils.c | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Autils.h | 13+++++++++++++
11 files changed, 300 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore @@ -1,3 +1,14 @@ +# Vim +*.sw* + +# Debug +.gdb_history + +# Coverage +*.gcov +*.gcda +*.gcno + # Prerequisites *.d diff --git a/README.md b/README.md @@ -1,2 +1,19 @@ +# Sheepy +This is a sheepy package for [sheepy](https://github.com/RemyNoulin/sheepy) and using [libsheepy](https://github.com/RemyNoulin/libsheepy) + # ervy -Bring charts to terminal. + +Bring charts to terminal. (inspired by [chunqiuyiyu/ervy](https://github.com/chunqiuyiyu/ervy.git)) + +# Usage + +Install with spm: `spm install ervy` + +Include header file: +- `#include "shpPackages/ervy/ervy.h"` + +See `example.c` for an example. + +## Supported Chart types +### Bar +![](/imgs/bar.png) diff --git a/bar.c b/bar.c @@ -0,0 +1,109 @@ + +#include "bar.h" +#include "math.h" +#include "limits.h" + +char *bar(char *data, char *opts) { + var dat = verifyData(data); + if (!dat) ret NULL; + + createSmallJson(newOpts); + parseG(&newOpts, "{\ + barWidth: 3,\ + left: 1,\ + height: 6,\ + padding: 3,\ + style: '*'\ + }"); + + createAllocateSmallJson(oopts); + if (opts) { + parseG(oopts, opts); + } + + mergeNSmashG(&newOpts, oopts); + + var barWidth = getG(&newOpts, rtI64, "barWidth"); + var left = getG(&newOpts, rtI64, "left"); + var height = getG(&newOpts, rtI64, "height"); + var padding = getG(&newOpts, rtI64, "padding"); + var style = getG(&newOpts, rtChar, "style"); + + var result = repeatS(PAD, left); + + + createSmallArray(values); + + iter(dat, V) { + cast(smallDictt*, v, V); + pushG(&values, getNumG(v, "value")); + } + + var max = getG(&values, rtF64, 0); + + range(i, lenG(&values)) { + max = maxV(max, getNumG(&values, i)); + } + var length = lenG(dat); + + range(i, height + 2) { + range(j, length) { + var tmp = getG(dat, rtSmallDictt, j); + var valStr = toStringG((i64)getNumG(tmp, "value")); + var curStyle = style; + if (hasG(tmp, "style")) curStyle = getG(tmp, rtChar, "style"); + + var ratio = height - (height * getNumG(tmp, "value") / max); + + var padChar = ratio > (i + 2) ? PAD + : round(ratio) == i + ? valStr + : round(ratio) < i + ? curStyle : PAD; + + if (eqG(padChar, valStr)) { + var pad = repeatS(PAD, padding); + var mid = padMid(valStr, barWidth); + iAppendManyS(&result, mid, pad); + freeManyS(pad, mid); + goto cont; + } + + if (i != height + 1) { + var pad = repeatS(padChar, barWidth); + var pad2 = repeatS(PAD, padding); + + iAppendManyS(&result, pad, pad2); + freeManyS(pad, pad2); + } else { + if (lenG(getG(tmp, rtChar, "key")) > barWidth) { + var s = padEndS(getG(tmp, rtChar, "key"), barWidth + padding, PAD); + iAppendS(&result, s); + free(s); + } + else { + var pad = repeatS(PAD, padding); + var mid = padMid(getG(tmp, rtChar, "key"), barWidth); + iAppendManyS(&result, mid, pad); + freeManyS(pad, mid); + } + } + + cont: + free(valStr); + finishG(tmp); + } + + if (i != height + 1) { + var pad = repeatS(PAD, left); + iAppendManyS(&result, EOL, pad); + free(pad); + } + } + + freeManyG(&newOpts, &values); + terminateG(dat); + + ret result; +} +// vim: set expandtab ts=2 sw=2: diff --git a/bar.h b/bar.h @@ -0,0 +1,5 @@ +#pragma once + +#include "utils.h" + +char *bar(char *data, char *opts); diff --git a/ervy.c b/ervy.c diff --git a/ervy.h b/ervy.h @@ -0,0 +1,3 @@ +#pragma once + +#include "bar.h" diff --git a/example.c b/example.c @@ -0,0 +1,49 @@ +#! /usr/bin/env sheepy +/* or direct path to sheepy: #! /usr/local/bin/sheepy */ + +/* Libsheepy documentation: http://spartatek.se/libsheepy/ */ +#include "libsheepyObject.h" +#include "ervy.h" + +int argc; char **argv; + +/* enable/disable logging */ +/* #undef pLog */ +/* #define pLog(...) */ + +int main(int ARGC, char** ARGV) { + + argc = ARGC; argv = ARGV; + + initLibsheepy(ARGV[0]); + setLogMode(LOG_VERBOSE); + //setLogSymbols(LOG_UTF8); + + + char *barData = "[\ + { key: 'A', value: 5.3, style: '*' },\ + { key: 'B', value: 3.1, style: '+' },\ + { key: 'C', value: 11 },\ + { key: 'D', value: 1, style: '"BGRED " "RST"' },\ + { key: 'E', value: 5, style: '"BGGRN " "RST"' },\ + { key: 'F', value: 7, style: '"BGBLU " "RST"', padding: 1 }\ + ]"; + /* char *barData = "[\ */ + /* { key: 'Aqweqwe ', value: 5, style: '*' },\ */ + /* { key: 'Bxcvxcvcvv ', value: 3, style: '+' },\ */ + /* { key: 'C', value: 11 },\ */ + /* { key: 'D', value: 1, style: '"BGRED " "RST"' },\ */ + /* { key: 'E', value: 5, style: '"BGGRN " "RST"' },\ */ + /* { key: 'F', value: 7, style: '"BGBLU " "RST"', padding: 1 }\ */ + /* ]"; */ + + + puts(bar(barData, NULL)); + + + /* char *opts = "{barWidth: 12, left: 0, height: 30, padding: 5, style: '~'}"; */ + /* */ + /* puts(bar(barData, opts)); */ + +} +// vim: set expandtab ts=2 sw=2: diff --git a/imgs/bar.png b/imgs/bar.png Binary files differ. diff --git a/package.yml b/package.yml @@ -0,0 +1,37 @@ +--- + name: ervy + version: 0.0.3 + description: "bring chart to terminal" + bin: ./ervy.c + #cflags: -DA -ggdb -std=gnu11 -fPIC -pipe + lflags: -lm -rdynamic + repository: + type: git + url: git+https://github.com/RemyNoulin/ervy.git + keywords: + - utility + - library + - char + - ascii + - terminal + - console + - data-visualization + author: Remy + license: MIT + bugs: + url: https://github.com/RemyNoulin/ervy/issues + homepage: https://github.com/RemyNoulin/ervy#readme + #compileHelp: # text displayed when there is a compilation error + #dependencies: + # md4c: + # Test configuration: + #testBin: ./testervy.c + #testCflags: -ggdb -std=gnu11 -fPIC -pipe -fprofile-arcs -ftest-coverage -Wall -Wextra + #testLflags: -lcheck_pic -lrt -lm -lsubunit -fprofile-arcs -ftest-coverage -rdynamic + # Memcheck configuration: + #memcheckBin: ./memcheckervy.c + #memcheckCmd: valgrind --leak-check=full --show-leak-kinds=all + #memcheckCflags: -ggdb -std=gnu11 -fPIC -pipe + #memcheckLflags: -rdynamic + #documentationCmd: # command for generating the documentation with spm doc + private: false # true for private package diff --git a/utils.c b/utils.c @@ -0,0 +1,55 @@ + +#include "utils.h" +#include "math.h" + +char *padMid(char *str, size_t width) { + var mid = round((double)(width - lenG(str)) / 2); + + if (lenG(str) > width) { + ret dupG(str); + } + else { + var pmid = repeatS(PAD, mid); + var pmid2 = repeatS(PAD, mid + ((mid * 2 + lenG(str)) > width ? -1 : 0)); + var r = catS(pmid, str, pmid2); + freeManyS(pmid, pmid2); + ret r; + } +} + +smallJsont* verifyData(char *data) { + + createAllocateSmallJson(r); + + parseG(r, data); + + var top = getTopTypeG(r); + + if (!eqG(top, "array") or !lenG(r)) goto fail; + + bool allHaveKeyValue = true; + + range(i, lenG(r)) { + var d = getG(r, rtSmallDictt, i); + if (!d) { + allHaveKeyValue = false; + break; + } + if (!hasG(d, "key") or !hasG(d, "value")) { + finishG(d); + allHaveKeyValue = false; + break; + } + finishG(d); + } + + if (!allHaveKeyValue) goto fail; + + ret r; + + fail: + logC("Invalid data: %s", data); + terminateG(r); + ret NULL; +} +// vim: set expandtab ts=2 sw=2: diff --git a/utils.h b/utils.h @@ -0,0 +1,13 @@ +#pragma once + +#include "libsheepyObject.h" + +#define PAD " " +#define EOL "\n" + +char *bg(char *color, size_t length); + +char *padMid(char *str, size_t width); + +smallJsont* verifyData(char *data); +// vim: set expandtab ts=2 sw=2: