commit de641c02cf3534abc80eef4f44e9924b1dccc208
parent 16464c0b9c26c0d0af990e6f79ad4cd7d9074bd2
Author: Remy Noulin <loader2x@gmail.com>
Date: Mon, 31 Dec 2018 20:31:15 +0100
add boxen
README.md | 162 +++++++++++++++++-
boxen.c | 518 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
boxen.h | 185 ++++++++++++++++++++
boxenInternal.h | 7 +
main.c | 63 +++++++
package.yml | 32 ++++
6 files changed, 966 insertions(+), 1 deletion(-)
Diffstat:
| M | README.md | | | 162 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
| A | boxen.c | | | 518 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | boxen.h | | | 185 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | boxenInternal.h | | | 8 | ++++++++ |
| A | main.c | | | 63 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | package.yml | | | 32 | ++++++++++++++++++++++++++++++++ |
6 files changed, 967 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
@@ -1,2 +1,162 @@
+# Sheepy
+This is a sheepy package for [sheepy](https://github.com/RemyNoulin/sheepy) and using [libsheepy](https://github.com/RemyNoulin/libsheepy)
+
# boxen
-Create boxes in the terminal
+
+Create boxes in the terminal.
+
+This is the C implementation of [boxen javscript](https://github.com/sindresorhus/boxen), the API is similar.
+
+The output looks like this:
+
+```
+(single)
+┌─────────────┐
+│ │
+│ unicorn │
+│ │
+└─────────────┘
+
+(double)
+ ╔═════════════╗
+ ║ ║
+ ║ unicorn ║
+ ║ ║
+ ╚═════════════╝
+
+(single-double)
+╓───╖
+║foo║
+╙───╜
+
+(double-single)
+╒═══╕
+│foo│
+╘═══╛
+
+(classic)
++---+
+|foo|
++---+
+```
+
+# Usage
+
+Install with spm: `spm install boxen`
+
+Include header file:
+- `#include "shpPackages/boxen/boxen.h"`
+
+```c
+boxent *box = allocBoxen();
+
+char *s = boxO(box, "foo", NULL);
+puts(s);
+free(s);
+
+terminateO(box);
+```
+
+Usage examples are in `main.c`.
+
+## API
+
+## boxO(obj,input,opts)
+
+### input
+
+Type: `char *`
+
+Text inside the box.
+
+### Options
+
+Type: `char *`
+
+The string must represent a JSON.
+
+OPTIONS: (the values are case insensitive)
+
+```
+"{borderColor: 'Yellow',"
+ "borderStyle: 'double',"
+ "dimBorder: true,"
+ "padding: {top: 1, left: 2, right: 2, bottom: 2},"
+ "margin: {top: 1, left: 1, right: 1, bottom: 1},"
+ "float: 'right',"
+ "backgroundColor: 'green',"
+ "align: 'center'}"
+ ```
+
+
+#### borderColor
+
+- Type: `string`
+
+Values: black red green yellow blue magenta cyan white gray, a hex value like #ff0000 or reset for default terminal color
+
+Color of the box border.
+
+
+#### borderStyle
+
+- Type: `string` `object`
+- Default: single
+
+single, double, single-double, double-single, classic
+
+
+#### dimBorder
+
+- Type: `boolean`
+- Default: false
+
+Reduce opacity of the border.
+
+
+
+#### padding
+
+- Type: `number` `Object`
+- Default: 0
+
+Space between the text and box border.
+
+Accepts a number or an object with any of the top, right, bottom, left properties. When a number is specified, the left/right padding is 3 times the top/bottom to make it look nice.
+
+
+#### margin
+
+
+- Type: `number` `Object`
+- Default: 0
+
+Space around the box.
+
+Accepts a number or an object with any of the top, right, bottom, left properties. When a number is specified, the left/right margin is 3 times the top/bottom to make it look nice.
+
+
+#### float
+
+- Type: `string`
+- Values: right center left
+- Default: left
+
+Float the box on the available terminal screen space.
+
+
+#### backgroundColor
+
+- Type: `string`
+- Values: black red green yellow blue magenta cyan white gray, a hex value like #ff0000 or reset for default terminal color
+
+Color of the background.
+
+
+#### align
+
+- Type: `string`
+- Default: left
+- Values: left center right
+
+Align the text in the box based on the widest line.
diff --git a/boxen.c b/boxen.c
@@ -0,0 +1,518 @@
+
+
+/* Libsheepy documentation: http://spartatek.se/libsheepy/ */
+
+#include "libsheepyObject.h"
+#include "boxen.h"
+#include "boxenInternal.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+void initiateBoxen(boxent *self);
+void registerMethodsBoxen(boxenFunctionst *f);
+void initiateAllocateBoxen(boxent **self);
+void finalizeBoxen(void);
+boxent* allocBoxen(void);
+internal void freeBoxen(boxent *self);
+internal void terminateBoxen(boxent **self);
+internal char* toStringBoxen(boxent *self);
+internal boxent* duplicateBoxen(boxent *self);
+internal void smashBoxen(boxent **self);
+internal void finishBoxen(boxent **self);
+internal const char* helpBoxen(boxent *self);
+internal char *boxBoxen(boxent *self, char *input, char *opts);
+
+/* enable/disable logging */
+/* #undef pLog */
+/* #define pLog(...) */
+
+internal size_t widestLine(char **text);
+typ struct {u16 rows; u16 cols;} winSizet;
+internal winSizet wsize (void);
+
+// single
+internal borderStyleBoxent singleBorderStyle = {
+.topLeft= "┌",
+.topRight= "┐",
+.bottomLeft= "└",
+.bottomRight= "┘",
+.horizontal= "─",
+.vertical= "│"
+};
+
+// double
+internal borderStyleBoxent doubleBorderStyle = {
+.topLeft= "╔",
+.topRight= "╗",
+.bottomLeft= "╚",
+.bottomRight= "╝",
+.horizontal= "═",
+.vertical= "║"
+};
+
+// single-double
+internal borderStyleBoxent singleDoubleBorderStyle = {
+.topLeft= "╓",
+.topRight= "╖",
+.bottomLeft= "╙",
+.bottomRight= "╜",
+.horizontal= "─",
+.vertical= "║"
+};
+
+// double-single
+internal borderStyleBoxent doubleSingleBorderStyle = {
+.topLeft= "╒",
+.topRight= "╕",
+.bottomLeft= "╘",
+.bottomRight= "╛",
+.horizontal= "═",
+.vertical= "│"
+};
+
+
+// classic
+internal borderStyleBoxent classicBorderStyle = {
+.topLeft= "+",
+.topRight= "+",
+.bottomLeft= "+",
+.bottomRight= "+",
+.horizontal= "-",
+.vertical= "|"
+};
+
+void initiateBoxen(boxent *self) {
+
+ self->type = "boxen";
+ if (!boxenF) {
+ boxenF = malloc(sizeof(boxenFunctionst));
+ registerMethodsBoxen(boxenF);
+ pErrorNot0(atexit(finalizeBoxen));
+ }
+ self->f = boxenF;
+
+ self->borderColor = "";
+ self->borderStyle = singleBorderStyle;
+ self->dimBorder = "";
+ self->padding.top = 0;
+ self->padding.left = 0;
+ self->padding.right = 0;
+ self->padding.bottom = 0;
+ self->margin.top = 0;
+ self->margin.left = 0;
+ self->margin.right = 0;
+ self->margin.bottom = 0;
+ self->boxFloat = "left";
+ self->backgroundColor = "";
+ self->align = "left";
+}
+
+void registerMethodsBoxen(boxenFunctionst *f) {
+
+ f->free = freeBoxen;
+ f->terminate = terminateBoxen;
+ f->toString = toStringBoxen;
+ f->duplicate = duplicateBoxen;
+ f->smash = smashBoxen;
+ f->finish = finishBoxen;
+ f->help = helpBoxen;
+ f->box = boxBoxen;
+}
+
+void initiateAllocateBoxen(boxent **self) {
+
+ if (self) {
+ (*self) = malloc(sizeof(boxent));
+ if (*self) {
+ initiateBoxen(*self);
+ }
+ }
+}
+
+void finalizeBoxen(void) {
+
+ if (boxenF) {
+ free(boxenF);
+ boxenF = NULL;
+ }
+}
+
+boxent* allocBoxen(void) {
+ boxent *r = NULL;
+
+ initiateAllocateBoxen(&r);
+ ret r;
+}
+
+
+internal void freeBoxen(boxent *self) {
+}
+
+internal void terminateBoxen(boxent **self) {
+
+ freeBoxen(*self);
+ finishBoxen(self);
+}
+
+
+internal char* toStringBoxen(boxent *self) {
+
+ createSmallJson(j);
+
+ if (isBlankG(self->borderColor))
+ setG(&j , "borderColor" , "default");
+ else
+ setG(&j , "borderColor" , "set");
+
+ if (eqG(self->borderStyle.topLeft, "┌")) {
+ setG(&j , "borderStyle" , "single");
+ }
+ elif (eqG(self->borderStyle.topLeft, "╔")) {
+ setG(&j , "borderStyle" , "double");
+ }
+ elif (eqG(self->borderStyle.topLeft, "╓")) {
+ setG(&j , "borderStyle" , "single-double");
+ }
+ elif (eqG(self->borderStyle.topLeft, "╒")) {
+ setG(&j , "borderStyle" , "double-single");
+ }
+
+ setG(&j , "dimBorder" , (bool)self->dimBorder);
+
+ createSmallDict(d);
+ setG(&d , "top" , self->padding.top);
+ setG(&d , "left" , self->padding.left);
+ setG(&d , "right" , self->padding.right);
+ setG(&d , "bottom" , self->padding.bottom);
+ setG(&j , "padding" , &d);
+ initiateG(&d);
+ setG(&d , "top" , self->margin.top);
+ setG(&d , "left" , self->margin.left);
+ setG(&d , "right" , self->margin.right);
+ setG(&d , "bottom" , self->margin.bottom);
+ setG(&j , "margin" , &d);
+
+ setG(&j , "float" , self->boxFloat);
+
+ if (isBlankG(self->backgroundColor))
+ setG(&j , "backgroundColor" , "default");
+ else
+ setG(&j , "backgroundColor" , "set");
+
+ setG(&j , "align" , self->align);
+
+ var r = toStringG(&j);
+ freeG(&j);
+
+ ret r;
+}
+
+internal boxent* duplicateBoxen(boxent *self) {
+
+ createAllocateBoxen(dup);
+ dup->borderColor = self->borderColor;
+ dup->borderStyle = self->borderStyle;
+ dup->dimBorder = self->dimBorder;
+ dup->padding = self->padding;
+ dup->margin = self->margin;
+ dup->boxFloat = self->boxFloat;
+ dup->backgroundColor = self->backgroundColor;
+ dup->align = self->align;
+ ret dup;
+}
+
+internal void smashBoxen(boxent **self) {
+
+ finishBoxen(self);
+}
+
+#if NFreeStackCheck
+internal void finishBoxen(boxent **self) {
+
+ register u64 rsp asm("rsp");
+ if ((u64)*self > rsp) {
+ logW("Probably trying to free a smallArray on stack: "BLD"%p"RST" sp: "BLD"%p"RST, *self, rsp);
+ logBtrace;
+ }
+ else {
+ free(*self);
+ *self = NULL;
+ }
+}
+#else
+// #if NFreeStackCheck
+internal void finishBoxen(boxent **self) {
+
+ free(*self);
+ *self = NULL;
+}
+#endif
+// #if NFreeStackCheck
+
+internal const char* helpBoxen(boxent UNUSED *self) {
+ ret "TODO - boxen help";
+}
+
+#define border(bord) self->borderStyle.bord
+#define oborderColor(color, value)\
+ if (icEqG(getG(&j, rtChar, "borderColor"), color)) {\
+ self->borderColor = value;\
+ }
+#define oborderStyle(style, value)\
+ if (icEqG(getG(&j, rtChar, "borderStyle"), style)) {\
+ self->borderStyle = value;\
+ }
+#define opadding(where, value)\
+ self->padding.value = getG(&j, rtU32, "\"padding\".\""where"\"");
+#define omargin(where, value)\
+ self->margin.value = getG(&j, rtU32, "\"margin\".\""where"\"");
+#define oboxFloat(fl, value)\
+ if (icEqG(getG(&j, rtChar, "float"), fl)) {\
+ self->boxFloat = value;\
+ }
+#define obackgroundColor(color, value)\
+ if (icEqG(getG(&j, rtChar, "backgroundColor"), color)) {\
+ self->backgroundColor = value;\
+ }
+#define oalign(fl, value)\
+ if (icEqG(getG(&j, rtChar, "align"), fl)) {\
+ self->align = value;\
+ }
+
+internal char *boxBoxen(boxent *self, char *input, char *opts) {
+ if (!input) ret NULL;
+
+ char *r = NULL;
+
+ // TODO add utf8 support
+ // TODO
+ // hex colors
+ // remove control codes
+
+
+ // options
+ if (opts) {
+ createSmallJson(j);
+ parseG(&j, opts);
+ oborderColor ( "black" , BLK)
+ else oborderColor ( "red" , RED)
+ else oborderColor ( "green" , GRN)
+ else oborderColor ( "yellow" , YLW)
+ else oborderColor ( "blue" , BLU)
+ else oborderColor ( "magenta" , MGT)
+ else oborderColor ( "cyan" , CYN)
+ else oborderColor ( "white" , BLD WHT)
+ else oborderColor ( "gray" , WHT)
+ elif (isEStringG(&j, "borderColor")) {
+ // invalid value: reset
+ self->borderColor = "";
+ }
+
+ oborderStyle("single" , singleBorderStyle);
+ oborderStyle("double" , doubleBorderStyle);
+ oborderStyle("single-double" , singleDoubleBorderStyle);
+ oborderStyle("double-single" , doubleSingleBorderStyle);
+ oborderStyle("classic" , classicBorderStyle);
+
+ if (getG(&j, rtBool, "dimBorder"))
+ self->dimBorder = FNT;
+ else
+ self->dimBorder = "";
+
+ if (isEIntG(&j, "padding")) {
+ self->padding.top = getG(&j, rtU32, "padding");
+ self->padding.left = self->padding.top * 3;
+ self->padding.right = self->padding.top * 3;
+ self->padding.bottom = self->padding.top;
+ }
+ else {
+ opadding("top" , top);
+ opadding("left" , left);
+ opadding("right" , right);
+ opadding("bottom" , bottom);
+ }
+
+ if (isEIntG(&j, "margin")) {
+ self->margin.top = getG(&j, rtU32, "margin");
+ self->margin.left = self->margin.top * 3;
+ self->margin.right = self->margin.top * 3;
+ self->margin.bottom = self->margin.top;
+ }
+ else {
+ omargin("top" , top);
+ omargin("left" , left);
+ omargin("right" , right);
+ omargin("bottom" , bottom);
+ }
+
+ oboxFloat("left" , "left");
+ oboxFloat("center" , "center");
+ oboxFloat("right" , "right");
+
+ obackgroundColor ( "black" , BGBLK)
+ else obackgroundColor ( "red" , BGRED)
+ else obackgroundColor ( "green" , BGGRN)
+ else obackgroundColor ( "yellow" , BGYLW)
+ else obackgroundColor ( "blue" , BGBLU)
+ else obackgroundColor ( "magenta" , BGMGT)
+ else obackgroundColor ( "cyan" , BGCYN)
+ else obackgroundColor ( "white" , BGWHT) // TODO RGB?
+ else obackgroundColor ( "gray" , BGWHT)
+ elif (isEStringG(&j, "backgroundColor")) {
+ // invalid value: reset
+ self->backgroundColor = "";
+ }
+
+ oalign("left" , "left");
+ oalign("center" , "center");
+ oalign("right" , "right");
+
+ freeG(&j);
+ }
+
+ var lines = splitG(input, '\n');
+
+ var widest = widestLine(lines);
+
+ // align text
+ if (eqG(self->align, "center")) {
+ forEachCharP(lines, l) {
+ var algWidth = (widest - lenG(*l)) / 2;
+ range(i, algWidth) {
+ prependG(l, " ");
+ }
+ }
+ }
+ elif (eqG(self->align, "right")) {
+ forEachCharP(lines, l) {
+ var algWidth = widest - lenG(*l);
+ range(i, algWidth) {
+ prependG(l, " ");
+ }
+ }
+ }
+ // align left - no-op
+
+ // padding top
+ range(i, self->padding.top) {
+ prependG(&lines, "");
+ }
+ // padding bottom
+ range(i, self->padding.bottom) {
+ pushG(&lines, "");
+ }
+
+ var contentWidth = widest + self->padding.left + self->padding.right;
+ char *paddingLeft = NULL;
+ range(i, self->padding.left) {
+ pushG(&paddingLeft, " ");
+ }
+
+ winSizet sz = wsize(); // window cols
+
+ char *marginLeft = NULL;
+
+ // float
+ if (eqG(self->boxFloat, "center")) {
+ var padWidth = maxV((sz.cols - contentWidth) / 2, 0);
+ range(i, padWidth) {
+ pushG(&marginLeft, " ");
+ }
+ }
+ elif (eqG(self->boxFloat, "right")) {
+ var padWidth = maxV(sz.cols - contentWidth - self->margin.right - 2, 0);
+ range(i, padWidth) {
+ pushG(&marginLeft, " ");
+ }
+ }
+ else {
+ // left
+ range(i, self->margin.left) {
+ pushG(&marginLeft, " ");
+ }
+ }
+
+ // top
+ range(i, self->margin.top) {
+ pushG(&r, '\n');
+ }
+ pushG(&r, marginLeft);
+ pushG(&r, self->dimBorder);
+ pushG(&r, self->borderColor);
+ pushG(&r, border(topLeft));
+ range(i, contentWidth) {
+ pushG(&r, border(horizontal));
+ }
+ pushG(&r, border(topRight));
+ pushG(&r, RST"\n");
+
+ // middle
+ forEachS(lines, l) {
+ pushG(&r, marginLeft);
+ pushG(&r, self->dimBorder);
+ pushG(&r, self->borderColor);
+ pushG(&r, border(vertical));
+ pushG(&r, RST);
+ pushG(&r, self->backgroundColor);
+ pushG(&r, paddingLeft);
+ pushG(&r, l);
+ char *paddingRight = NULL;
+ range(i, contentWidth - lenG(l) - self->padding.left) {
+ pushG(&paddingRight, " ");
+ }
+ pushNFreeG(&r, paddingRight);
+ pushG(&r, RST);
+ pushG(&r, self->dimBorder);
+ pushG(&r, self->borderColor);
+ pushG(&r, border(vertical));
+ pushG(&r, RST);
+ pushG(&r, '\n');
+ }
+
+ // bottom
+ pushG(&r, marginLeft);
+ pushG(&r, self->dimBorder);
+ pushG(&r, self->borderColor);
+ pushG(&r, border(bottomLeft));
+ range(i, contentWidth) {
+ pushG(&r, border(horizontal));
+ }
+ pushG(&r, border(bottomRight));
+ pushG(&r, RST);
+ range(i, self->margin.bottom) {
+ pushG(&r, '\n');
+ }
+
+ // free
+ freeG(lines);
+ free(paddingLeft);
+ free(marginLeft);
+
+ ret r;
+}
+
+internal size_t widestLine(char **text) {
+ size_t r = 0;
+ if (!text) ret 0;
+ forEachS(text, l) {
+ r = MAX(r, lenG(l));
+ }
+ ret r;
+}
+
+/* terminal window size */
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+internal winSizet wsize (void)
+{
+ struct winsize w;
+ ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
+
+ return (winSizet){w.ws_row, w.ws_col};
+}
+//-----------------------
+
+// vim: set expandtab ts=2 sw=2:
diff --git a/boxen.h b/boxen.h
@@ -0,0 +1,185 @@
+#pragma once
+
+/* Libsheepy documentation: http://spartatek.se/libsheepy/ */
+
+/*
+OPTIONS: (the values are case insensitive)
+
+"{borderColor: 'Yellow',"
+ "borderStyle: 'double',"
+ "dimBorder: true,"
+ "padding: {top: 1, left: 2, right: 2, bottom: 2},"
+ "margin: {top: 1, left: 1, right: 1, bottom: 1},"
+ "float: 'right',"
+ "backgroundColor: 'green',"
+ "align: 'center'}"
+
+
+borderColor
+
+Type: string
+Values: black red green yellow blue magenta cyan white gray, a hex value like #ff0000 or reset for default terminal color
+
+Color of the box border.
+
+
+borderStyle
+
+Type: string object
+Default: single
+single, double, /round,/ single-double, double-single, classic
+
+
+dimBorder
+
+Type: boolean
+Default: false
+
+Reduce opacity of the border.
+
+
+
+padding
+
+Type: number Object
+Default: 0
+
+Space between the text and box border.
+
+Accepts a number or an object with any of the top, right, bottom, left properties. When a number is specified, the left/right padding is 3 times the top/bottom to make it look nice.
+
+
+margin
+
+
+Type: number Object
+Default: 0
+
+Space around the box.
+
+Accepts a number or an object with any of the top, right, bottom, left properties. When a number is specified, the left/right margin is 3 times the top/bottom to make it look nice.
+
+
+float
+
+Type: string
+Values: right center left
+Default: left
+
+Float the box on the available terminal screen space.
+
+
+backgroundColor
+
+Type: string
+Values: black red green yellow blue magenta cyan white gray, a hex value like #ff0000 or reset for default terminal color
+
+Color of the background.
+
+
+align
+
+Type: string
+Default: left
+Values: left center right
+
+Align the text in the box based on the widest line.
+*/
+
+
+
+#define boxO(obj, input, opts) (obj)->f->box(obj, input, opts)
+
+typ struct {
+ char *topLeft;
+ char *topRight;
+ char *bottomLeft;
+ char *bottomRight;
+ char *horizontal;
+ char *vertical;
+} borderStyleBoxent;
+
+/* Class boxen */
+typ struct boxen boxent;
+
+/* for object inheriting boxen, cast to boxen to be able to use this class functions and generics*/
+#define cBoxen(self) ( (boxent*) self )
+
+typ void (*freeBoxenFt) (boxent *self);
+typ void (*terminateBoxenFt) (boxent **self);
+typ char* (*toStringBoxenFt) (boxent *self);
+typ boxent* (*duplicateBoxenFt) (boxent *self);
+typ void (*smashBoxenFt) (boxent **self);
+
+/**
+ * free boxen
+ */
+typ void (*finishBoxenFt) (boxent **self);
+
+typ const char* (*helpBoxenFt) (boxent *self);
+
+typ char * (*boxBoxenFt) (boxent *self, char *input, char *opts);
+
+
+/**
+ * class functions
+ * allocated once for all objects
+ *
+ * freed with finalizeBoxen
+ */
+
+/**
+ * use this define in child classes and add the new function after this class functions
+ *
+ * in this define, add the methods after <finishBoxenFt finish;>
+ *
+ * Example:
+ * #define RINGFUNCTIONST \n * BOXENFUNCTIONST; \n * setSizeRingFt setSize
+ */
+#define BOXENFUNCTIONST \
+ helpBoxenFt help;\
+ boxBoxenFt box
+
+typ struct {
+ freeBoxenFt free;
+ terminateBoxenFt terminate;
+ toStringBoxenFt toString;
+ duplicateBoxenFt duplicate;
+ smashBoxenFt smash;
+ finishBoxenFt finish;
+ BOXENFUNCTIONST;
+} boxenFunctionst;
+
+/**
+ * class
+ */
+struct boxen {
+ const char *type;
+ boxenFunctionst *f;
+
+ char *borderColor;
+ borderStyleBoxent borderStyle;
+ char *dimBorder;
+ struct {u32 top; u32 left; u32 right; u32 bottom;} padding;
+ struct {u32 top; u32 left; u32 right; u32 bottom;} margin;
+ char *boxFloat;
+ char *backgroundColor;
+ char *align;
+};
+
+/* boxen */
+
+#define createBoxen(obj) ;boxent obj; initiateBoxen(&obj)
+#define createAllocateBoxen(obj) ;boxent *obj; initiateAllocateBoxen(&obj)
+
+void initiateBoxen(boxent *self);
+void initiateAllocateBoxen(boxent **self);
+void finalizeBoxen(void);
+
+/* initialize class methods, call registerMethodsBoxen from classes inheriting this class */
+void registerMethodsBoxen(boxenFunctionst *f);
+
+boxent* allocBoxen(void);
+
+/* end class boxen*/
+// vim: set expandtab ts=2 sw=2:
diff --git a/boxenInternal.h b/boxenInternal.h
@@ -0,0 +1,7 @@
+#pragma once
+
+static boxenFunctionst *boxenF = NULL;
+
+/* TODO declare structs for private data and add a void pointer to the private data in the class declaration */
+
+// vim: set expandtab ts=2 sw=2:+
\ No newline at end of file
diff --git a/main.c b/main.c
@@ -0,0 +1,63 @@
+#! /usr/bin/env sheepy
+/* or direct path to sheepy: #! /usr/local/bin/sheepy */
+
+/* Libsheepy documentation: http://spartatek.se/libsheepy/ */
+#include "libsheepyObject.h"
+#include "boxen.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_FUNC);
+
+ createBoxen(box);
+
+ logNFree(boxO(&box, "unicorn", NULL));
+ logNFree(boxO(&box, "unicorn\nand\nthe sheepy",
+ "{borderColor: 'Yellow',\n\
+ borderStyle: 'double',\n\
+ dimBorder: true,\n\
+ padding: {top: 1, left: 2, right: 2, bottom: 2},\n\
+ margin: {top: 1, left: 1, right: 1, bottom: 1},\n\
+ float: 'right',\n\
+ backgroundColor: 'green',\n\
+ align: 'center'}"));
+ // options are optional
+ logNFree(boxO(&box, "unicorn\nand\nthe sheepy",
+ "{borderStyle: 'double',\n\
+ dimBorder: false,\n\
+ padding: 4,\n\
+ margin: 1,\n\
+ float: 'left',\n\
+ align: 'center'}"));
+ // options are stored, use 'reset' value to reset colors
+ logNFree(boxO(&box, "unicorn\nand\nthe sheepy",
+ "{borderColor: 'reset',\n\
+ float: 'right',\n\
+ backgroundColor: 'reset',\n\
+ align: 'left'}"));
+
+ // defaults
+ initiateBoxen(&box);
+
+ // change box style
+ logNFree(boxO(&box, "unicorn", "{dimBorder: true, padding: {top:1, left:3, right:3, bottom:1}}"));
+
+ initiateBoxen(&box);
+ logNFree(boxO(&box, "unicorn", "{borderStyle: 'single-double'}"));
+ logNFree(boxO(&box, "unicorn", "{borderStyle: 'double-single'}"));
+ logNFree(boxO(&box, "unicorn", "{borderStyle: 'classic'}"));
+
+ logNFree(toStringO(&box));
+}
+
+// vim: set expandtab ts=2 sw=2:
diff --git a/package.yml b/package.yml
@@ -0,0 +1,32 @@
+---
+ name: boxen
+ version: 0.0.1
+ description: "Create boxes in the terminal"
+ bin: ./boxen.c
+ #cflags: -DA -ggdb -std=gnu11 -fPIC -pipe
+ #lflags: -lpcre
+ repository:
+ type: git
+ url: git+https://github.com/RemyNoulin/boxen.git
+ keywords:
+ - utility
+ - box
+ author: Remy Noulin
+ license: MIT
+ bugs:
+ url: https://github.com/RemyNoulin/boxen/issues
+ homepage: https://github.com/RemyNoulin/boxen#readme
+ #compileHelp: # text displayed when there is a compilation error
+ #dependencies:
+ # md4c:
+ # Test configuration:
+ #testBin: ./testBoxen.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: ./memcheckBoxen.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