boxen

Create boxes in the terminal
git clone https://noulin.net/git/boxen.git
Log | Files | Refs | README | LICENSE

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:
MREADME.md | 162++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Aboxen.c | 518+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aboxen.h | 185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AboxenInternal.h | 8++++++++
Amain.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage.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