From 65f7f8c1f339e11ed7867eb1c19fa4692976221a Mon Sep 17 00:00:00 2001 From: Peter Mikkelsen Date: Fri, 14 Jan 2022 21:56:26 +0000 Subject: Rework the array printer. It allocates A LOT, and doesn't add vertical padding yet, but it is better. --- print.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 133 insertions(+), 19 deletions(-) (limited to 'print.c') diff --git a/print.c b/print.c index 8c3dbbf..1ebdecb 100644 --- a/print.c +++ b/print.c @@ -4,6 +4,9 @@ #include "apl9.h" +void strdims(Rune *, int *, int *); +Rune *printborder(Rune *, int *, int, int); + Rune * ppdatum(Datum d) { @@ -59,40 +62,95 @@ Rune * pparray(Array *a) { Rune **elemstrs = malloc(sizeof(Rune *) * a->size); + int rowcount = 1; + if(a->rank > 0){ + for(int i = 0; i < a->rank-1; i++) + rowcount *= a->shape[i]; + } + Rune **rowstrs = mallocz(sizeof(Rune *) * rowcount, 1); + int boxing = a->type == AtypeArray; + + char *align = a->type == AtypeArray ? "-" : ""; for(int i = 0; i < a->size; i++){ if(a->type == AtypeArray){ Rune *arrstr = pparray(a->arraydata[i]); - elemstrs[i] = runesmprint("[%S]", arrstr); + elemstrs[i] = runesmprint("%S", arrstr); free(arrstr); }else if(a->type == AtypeInt) elemstrs[i] = runesmprint("%lld", a->intdata[i]); } - /* Should do some width and height padding here */ - Rune *res = runesmprint(""); - Rune *tmp; + int lastdim = a->rank ? a->shape[a->rank-1] : 1; + int *widths = mallocz(sizeof(int) * lastdim, 1); for(int i = 0; i < a->size; i++){ - tmp = res; - res = runesmprint("%S%S", res, elemstrs[i]); + int w,h; + strdims(elemstrs[i], &w, &h); + if(w > widths[i%lastdim]) + widths[i%lastdim] = w; + } + + /* Should do height padding here as well */ + for(int i = 0; i < a->size; i++){ + if(i%lastdim == 0) + rowstrs[i/lastdim] = runesmprint("%S", boxing ? L"│" : L""); + Rune *tmp = rowstrs[i/lastdim]; + char *fmt = smprint("%%%s%dS", align, widths[i%lastdim]); + Rune *elem = runesmprint(fmt, elemstrs[i]); + Rune *spacing; + if((i+1)%lastdim == 0) + spacing = boxing ? L"│" : L""; + else + spacing = boxing ? L"│" : L" "; + rowstrs[i/lastdim] = runesmprint("%S%S%S", tmp, elem, spacing); free(tmp); + free(elem); + free(fmt); free(elemstrs[i]); + } + free(elemstrs); + + if(rowstrs[0] == nil) + rowstrs[0] = runestrdup(L""); + + if(rowcount == 1 && !boxing) + return rowstrs[0]; + + Rune *res = runesmprint(""); + Rune *tmp; + for(int i = 0; i < rowcount; i++){ + if(i == 0 && boxing) + res = printborder(res, widths, lastdim, 0); int j = 1; - int spaceprinted = 0; - for(int dim = 0; dim < a->rank && i+1 != a->size; dim++){ - j *= a->shape[a->rank-dim-1]; + int blanks = 0; + for(int dim = 0; dim < a->rank - 1 && i+1 != a->size; dim++){ + j *= a->shape[a->rank-dim-2]; + if(i%j == 0) + blanks++; + } + if(i != 0 && blanks == 0 && boxing) + res = printborder(res, widths, lastdim, 1); + if(i != 0 && blanks > 0 && boxing) + res = printborder(res, widths, lastdim, 2); + + for(int b = 0; i != 0 && b < blanks; b++){ tmp = res; - if((i+1)%j == 0){ - spaceprinted = 1; - res = runesmprint("%S\n", res); - free(tmp); - }else if(!spaceprinted){ - spaceprinted = 1; - res = runesmprint("%S ", res); - free(tmp); - } - } + res = runesmprint("%S\n", tmp); + free(tmp); + } + + if(blanks > 0 && i != 0 && i < rowcount-1 && boxing) + res = printborder(res, widths, lastdim, 0); + + tmp = res; + res = runesmprint("%S%S\n", tmp, rowstrs[i]); + free(tmp); + + if(i == rowcount-1 && boxing) + res = printborder(res, widths, lastdim, 2); + } + res[runestrlen(res)-1] = 0; /* remove trailing newline */ return res; } @@ -113,4 +171,60 @@ ppoperator(Operator op) free(left); free(right); return res; +} + +void +strdims(Rune *s, int *width, int *height) +{ + int currentwidth = 0; + *width = 0; + *height = 1; + + int len = runestrlen(s); + int i; + for(i = 0; i < len; i++){ + if(s[i] == '\n'){ + (*height)++; + if(currentwidth > *width) + *width = currentwidth; + currentwidth = 0; + }else + currentwidth++; + } + if(currentwidth > *width) + *width = currentwidth; +} + +Rune * +printborder(Rune *input, int *widths, int lastdim, int type) +{ + Rune *borderchars = L"????"; + switch(type){ + case 0: borderchars = L"┌─┬┐"; break; + case 1: borderchars = L"├─┼┤"; break; + case 2: borderchars = L"└─┴┘"; break; + } + + int width = 1; + for(int i = 0; i < lastdim; i++) + width += widths[i]+1; + Rune *border = malloc(sizeof(Rune) * width + 1); + border[width] = 0; + + border[0] = borderchars[0]; + border[width-1] = borderchars[3]; + for(int i = 1; i < width-1; i++) + border[i] = borderchars[1]; + + int offset = 1; + for(int i = 0; i < lastdim-1; i++){ + offset += widths[i]; + border[offset] = borderchars[2]; + offset++; + } + + Rune *result = runesmprint("%S%S\n", input, border); + //free(border); + //free(input); + return result; } \ No newline at end of file -- cgit v1.2.3