diff --git a/README.md b/README.md index 83dc7fc..fcbf5a2 100644 --- a/README.md +++ b/README.md @@ -463,20 +463,17 @@ Default value: `false` Option: `padding`\ Default value: `1` -#### Alignment +#### Format and Alignment Option: `alignment`\ Values: -* `nullptr` -* `left` (default) -* `right` -* `internal` (integer and floating-point types only) +* (default) +* `std::ios_base::left` +* `std::ios_base::right` +* `std::ios_base::internal` (integer and floating-point types only) -#### bool to alpha - -Option: `boolalpha`\ -Default value: `false` +See [`ios_base::fmtflags`](https://en.cppreference.com/w/cpp/io/ios_base/fmtflags) for full available options. Use `std::ios_base::boolalpha` for bool to alpha. #### Title @@ -507,6 +504,17 @@ Values: 7. `style_heavy_dashed`: Heavy Dashed ![](images/heavy%20dashed%20table.png) +#### Output stream + +Option: `ostr`\ +Values: + +* `std::cout` (default) +* `std::cerr` +* `std::clog` + +Any other subclass of `ostream`, including `iostream`, `ofstream` and `ostringstream` + #### Check size Option: `check`\ @@ -949,6 +957,17 @@ This option is only used when plotting a single array and when graphing a single ![](images/graph%20colors.png) +#### Output stream + +Option: `ostr`\ +Values: + +* `std::cout` (default) +* `std::cerr` +* `std::clog` + +Any other subclass of `ostream`, including `iostream`, `ofstream` and `ostringstream` + #### Check size Option: `check`\ @@ -967,7 +986,6 @@ Pull requests welcome! Ideas for contributions: Both: * Add more options * Add options to word wrap and truncate long text in table cells - * Add option to center text in table cells * Add more examples * Improve the performance * Handle newlines and tabs in the tables @@ -979,5 +997,6 @@ Both: * Port to other languages (C, Java, Rust, etc.) C++: +* Add option to center text in table cells * Update the CI to test with more compilers * Support tables with the `wchar_t`, `char16_t` and `char32_t` C data types and the `wstring`, `u16string` and `u32string` C++ data types. diff --git a/graphs.hpp b/graphs.hpp index f7edcf1..d32855d 100644 --- a/graphs.hpp +++ b/graphs.hpp @@ -165,6 +165,7 @@ namespace graphs const char *title = nullptr; style_type style = style_light; color_type color = color_red; + ostream &ostr = cout; bool check = true; }; @@ -176,7 +177,7 @@ namespace graphs if (iscntrl(c)) { cerr << "\nError: Control character in string.\n"; - cout << "Control character: " << (int)c << '\n'; + cerr << "Control character: " << (int)c << '\n'; } size_t length = mbstowcs(nullptr, str.c_str(), 0); @@ -493,18 +494,20 @@ namespace graphs setlocale(LC_ALL, ""); if (title and title[0] != '\0') - cout << wrap(title, awidth) << '\n'; + aoptions.ostr << wrap(title, awidth) << '\n'; const char *const *astyle = styles[aoptions.style]; + ostringstream strm; + if (border) { - cout << astyle[2]; + strm << astyle[2]; for (size_t k = 0; k < awidth; ++k) - cout << astyle[0]; + strm << astyle[0]; - cout << astyle[4] << '\n'; + strm << astyle[4] << '\n'; } for (size_t i = 0; i < height; i += ai) @@ -539,7 +542,7 @@ namespace graphs } if (border) - cout << astyle[1]; + strm << astyle[1]; for (size_t j = 0; j < width; j += aj) { @@ -552,19 +555,19 @@ namespace graphs { if (axaxis and ayaxis) { - cout << astyle[6]; + strm << astyle[6]; output = true; } else if (axaxis) { if (!i) { - cout << astyle[4]; + strm << astyle[4]; output = true; } else if (i >= (height - ai)) { - cout << astyle[10]; + strm << astyle[10]; output = true; } else if (axistick) @@ -575,14 +578,14 @@ namespace graphs { if (i <= k and (i + ai) > k) { - cout << astyle[xaxis >= aj ? 7 : 5]; + strm << astyle[xaxis >= aj ? 7 : 5]; output = true; } } } if (!output) { - cout << astyle[1]; + strm << astyle[1]; output = true; } } @@ -590,12 +593,12 @@ namespace graphs { if (!j) { - cout << astyle[2]; + strm << astyle[2]; output = true; } else if (j >= (width - aj)) { - cout << astyle[4]; + strm << astyle[4]; output = true; } else if (axistick) @@ -606,25 +609,25 @@ namespace graphs { if (j <= k and (j + aj) > k) { - cout << astyle[yaxis <= (height - ai) ? 3 : 9]; + strm << astyle[yaxis <= (height - ai) ? 3 : 9]; output = true; } } } if (!output) { - cout << astyle[0]; + strm << astyle[0]; output = true; } } else if (yaxislabel and xaxislabel and axistick and axisunitslabel and ymin <= 0 and ymax >= 0 and xmin <= 0 and xmax >= 0) { - cout << '0'; + strm << '0'; output = true; } else if ((xaxis <= (width - aj) ? j >= (width - aj) : !j) and yaxislabel and axislabel) { - cout << 'x'; + strm << 'x'; output = true; } else if (yaxislabel and axistick and axisunitslabel) @@ -651,12 +654,12 @@ namespace graphs { output = false; - ostringstream strm; - size_t length = outputlabel(label, aoptions.xunits, strm); + ostringstream astrm; + size_t length = outputlabel(label, aoptions.xunits, astrm); length *= aj; if ((j >= xaxis or (j + length) < (ymin <= 0 and ymax >= 0 and xmin <= 0 and xmax >= 0 ? xaxis - ai : xaxis)) and (j + length) < (width - aj) and (xaxis <= (width - aj) or j > aj)) { - cout << strm.str(); + strm << astrm.str(); if (length > aj) j += length - aj; @@ -670,12 +673,12 @@ namespace graphs } else if ((yaxis >= ai ? !i : i >= (height - ai)) and xaxislabel and axislabel) { - cout << 'y'; + strm << 'y'; output = true; } else if (ylabellength and (xaxis < aj ? xaxislabel : j < (xaxis - ylabellength) and (j + aj) >= (xaxis - ylabellength)) and (yaxis >= ai or i < (height - ai)) and axistick and axisunitslabel) { - cout << ylabelstrm.str(); + strm << ylabelstrm.str(); output = true; if (ylabellength > aj) j += ylabellength - aj; @@ -718,34 +721,35 @@ namespace graphs --color; if (color) - cout << colors[color]; + strm << colors[color]; - cout << (type == type_histogram ? bars[dot] : type == type_block ? blocks[dot] + strm << (type == type_histogram ? bars[dot] : type == type_block ? blocks[dot] : dots[dot]); if (color) - cout << colors[0]; + strm << colors[0]; } } if (border) - cout << astyle[1]; + strm << astyle[1]; if (i < (height - ai) or border) - cout << '\n'; + strm << '\n'; } if (border) { - cout << astyle[8]; + strm << astyle[8]; for (size_t k = 0; k < awidth; ++k) - cout << astyle[0]; + strm << astyle[0]; - cout << astyle[10]; + strm << astyle[10]; } - cout << '\n'; + strm << '\n'; + aoptions.ostr << strm.str(); return 0; } diff --git a/python/README.md b/python/README.md index 86090e6..9e193ed 100644 --- a/python/README.md +++ b/python/README.md @@ -198,14 +198,18 @@ Default value: `False` Option: `padding`\ Default value: `1` -#### Alignment +#### Format and Alignment Option: `alignment`\ Values: -* `None` (default) -* `False` (left) -* `True` (right) +* `""` (default) +* `"<"` (left) +* `">"` (right) +* `"="` (internal, numeric types only) +* `"^"` (center) + +See the [Python documentation](https://docs.python.org/3/library/string.html#formatspec) for the full available options. #### Title @@ -236,6 +240,16 @@ Values: 7. `style_types.heavy_dashed`: Heavy Dashed ![](../images/heavy%20dashed%20table.png) +#### Output file + +Option: `file`\ +Values: + +* `sys.stdout` (default) +* `sys.stderr` + +Any other text [file object](https://docs.python.org/3/glossary.html#term-file-object). + #### Check size Option: `check`\ @@ -542,6 +556,16 @@ This option is only used when plotting a single array and when graphing a single ![](../images/graph%20colors.png) +#### Output file + +Option: `file`\ +Values: + +* `sys.stdout` (default) +* `sys.stderr` + +Any other text [file object](https://docs.python.org/3/glossary.html#term-file-object). + #### Check size Option: `check`\ diff --git a/python/graphs.py b/python/graphs.py index 64be088..6f94d1c 100644 --- a/python/graphs.py +++ b/python/graphs.py @@ -10,7 +10,7 @@ import textwrap from datetime import datetime, timezone from enum import Enum, IntEnum, auto from fractions import Fraction -from typing import Callable, List, Optional, Sequence, Tuple +from typing import Callable, List, Optional, Sequence, TextIO, Tuple if sys.platform != "win32": import ctypes @@ -298,7 +298,7 @@ def outputlabel(label: float, units: units_types) -> Tuple[int, str]: return length, strm -def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, array: List[List[int]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, atype: type_types = type_types.braille, style: style_types = style_types.light, title: Optional[str] = None, check: bool = True) -> int: +def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, array: List[List[int]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, atype: type_types = type_types.braille, style: style_types = style_types.light, title: Optional[str] = None, file: TextIO = sys.stdout, check: bool = True) -> int: """Output graph.""" if not array: return 1 @@ -344,7 +344,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: ydivisor = 2 * ai * ((((4 * height) // ai) // 160) + 2) if title: - print(textwrap.fill(title, width=awidth)) + print(textwrap.fill(title, width=awidth), file=file) astyle = styles[style] @@ -521,12 +521,12 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: if border: strm += astyle[8] + (astyle[0] * awidth) + astyle[10] - print(strm) + print(strm, file=file) return 0 -def histogram(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarray: Sequence[float], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None, check: bool = True) -> int: +def histogram(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarray: Sequence[float], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None, file: TextIO = sys.stdout, check: bool = True) -> int: """Convert one or more arrays to graph and output.""" if not aarray: return 1 @@ -594,10 +594,10 @@ def histogram(height: int, width: int, xmin: float, xmax: float, ymin: float, ym aaarray[x][y] = acolor y += 1 - return graph(height, width, xmin, xmax, ymin, ymax, aaarray, border, axis, axislabel, axistick, axisunitslabel, xunits, yunits, type_types.histogram, style, title) + return graph(height, width, xmin, xmax, ymin, ymax, aaarray, border, axis, axislabel, axistick, axisunitslabel, xunits, yunits, type_types.histogram, style, title, file) -def plots(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarrays: Sequence[Sequence[Sequence[float]]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, atype: type_types = type_types.braille, mark: mark_types = mark_types.dot, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None, check: bool = True) -> int: +def plots(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarrays: Sequence[Sequence[Sequence[float]]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, atype: type_types = type_types.braille, mark: mark_types = mark_types.dot, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None, file: TextIO = sys.stdout, check: bool = True) -> int: """Convert one or more arrays to graph and output.""" if not aarrays: return 1 @@ -673,15 +673,15 @@ def plots(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: else: aaarray[x][y] = acolor - return graph(height, width, xmin, xmax, ymin, ymax, aaarray, border, axis, axislabel, axistick, axisunitslabel, xunits, yunits, atype, style, title) + return graph(height, width, xmin, xmax, ymin, ymax, aaarray, border, axis, axislabel, axistick, axisunitslabel, xunits, yunits, atype, style, title, file) -def plot(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarray: Sequence[Sequence[float]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, atype: type_types = type_types.braille, mark: mark_types = mark_types.dot, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None) -> int: +def plot(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarray: Sequence[Sequence[float]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, atype: type_types = type_types.braille, mark: mark_types = mark_types.dot, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None, file: TextIO = sys.stdout, check: bool = True) -> int: """Convert single array to graph and output.""" - return plots(height, width, xmin, xmax, ymin, ymax, [aarray], border, axis, axislabel, axistick, axisunitslabel, xunits, yunits, atype, mark, style, color, title) + return plots(height, width, xmin, xmax, ymin, ymax, (aarray,), border, axis, axislabel, axistick, axisunitslabel, xunits, yunits, atype, mark, style, color, title, file, check) -def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, afunctions: Sequence[Callable[[float], float]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, atype: type_types = type_types.braille, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None, check: bool = True) -> int: +def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, afunctions: Sequence[Callable[[float], float]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, atype: type_types = type_types.braille, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None, file: TextIO = sys.stdout, check: bool = True) -> int: """Convert one or more functions to graph and output.""" if not afunctions: return 1 @@ -747,9 +747,9 @@ def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ym else: array[ax][ay] = acolor - return graph(height, width, xmin, xmax, ymin, ymax, array, border, axis, axislabel, axistick, axisunitslabel, xunits, yunits, atype, style, title) + return graph(height, width, xmin, xmax, ymin, ymax, array, border, axis, axislabel, axistick, axisunitslabel, xunits, yunits, atype, style, title, file) -def function(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, afunction: Callable[[float], float], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, atype: type_types = type_types.braille, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None) -> int: +def function(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, afunction: Callable[[float], float], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, atype: type_types = type_types.braille, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None, file: TextIO = sys.stdout, check: bool = True) -> int: """Convert single function to function array and output.""" - return functions(height, width, xmin, xmax, ymin, ymax, [afunction], border, axis, axislabel, axistick, axisunitslabel, xunits, yunits, atype, style, color, title) + return functions(height, width, xmin, xmax, ymin, ymax, (afunction,), border, axis, axislabel, axistick, axisunitslabel, xunits, yunits, atype, style, color, title, file, check) diff --git a/python/tables.py b/python/tables.py index ccf55a7..2d5cb26 100644 --- a/python/tables.py +++ b/python/tables.py @@ -8,7 +8,7 @@ import shutil import sys import textwrap from enum import IntEnum, auto -from typing import Any, Callable, List, Optional, Sequence +from typing import Any, Callable, List, Optional, Sequence, TextIO if sys.platform != "win32": import ctypes @@ -66,7 +66,7 @@ def strcol(astr: str) -> int: def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, - padding: int = 1, alignment: Optional[bool] = None, title: Optional[str] = None, style: style_types = style_types.light, check: bool = True) -> int: + padding: int = 1, alignment: str = "", title: Optional[str] = None, style: style_types = style_types.light, file: TextIO = sys.stdout, check: bool = True) -> int: """Output char array as table.""" if not array: return 1 @@ -91,7 +91,7 @@ def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool = return 1 if title: - print(textwrap.fill(title, width=width)) + print(textwrap.fill(title, width=width), file=file) astyle = styles[style] @@ -124,9 +124,9 @@ def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool = awidth = columnwidth[j] - (strcol(array[i][j]) - len(array[i][j])) if (not i and headerrow) or (not j and headercolumn): - strm += (" " * padding) + "\033[1m" + array[i][j].center(awidth) + "\033[22m" + (" " * padding) + strm += (" " * padding) + "\033[1m" + f"{array[i][j]:^{awidth}}" + "\033[22m" + (" " * padding) else: - strm += (" " * padding) + (f"{array[i][j]:{awidth}}" if alignment is None else array[i][j].rjust(awidth) if alignment else array[i][j].ljust(awidth)) + (" " * padding) + strm += (" " * padding) + f"{array[i][j]:{alignment}{awidth}}" + (" " * padding) if tableborder: strm += astyle[1] @@ -177,12 +177,12 @@ def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool = strm += astyle[10] - print(strm) + print(strm, file=file) return 0 -def array(aarray: Sequence[Sequence[Any]], aheaderrow: Optional[Sequence[str]] = None, aheadercolumn: Optional[Sequence[str]] = None, headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: Optional[bool] = None, title: Optional[str] = None, style: style_types = style_types.light) -> int: +def array(aarray: Sequence[Sequence[Any]], aheaderrow: Optional[Sequence[str]] = None, aheadercolumn: Optional[Sequence[str]] = None, headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: str = "", title: Optional[str] = None, style: style_types = style_types.light, file: TextIO = sys.stdout, check: bool = True) -> int: """Convert array to char array and output as table.""" if not aarray: return 1 @@ -228,10 +228,10 @@ def array(aarray: Sequence[Sequence[Any]], aheaderrow: Optional[Sequence[str]] = j = 1 if aheadercolumn else 0 aaarray[i][j:] = map(str, aarray[ii][:columns - j]) - return table(aaarray, headerrow, headercolumn, tableborder, cellborder, padding, alignment, title, style) + return table(aaarray, headerrow, headercolumn, tableborder, cellborder, padding, alignment, title, style, file, check) -def functions(xmin: float, xmax: float, xstep: float, afunctions: Sequence[Callable[[float], float]], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: Optional[bool] = None, title: Optional[str] = None, style: style_types = style_types.light) -> int: +def functions(xmin: float, xmax: float, xstep: float, afunctions: Sequence[Callable[[float], float]], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: str = "", title: Optional[str] = None, style: style_types = style_types.light, file: TextIO = sys.stdout, check: bool = True) -> int: """Convert one or more functions to array and output as table.""" if not afunctions: return 1 @@ -261,9 +261,9 @@ def functions(xmin: float, xmax: float, xstep: float, afunctions: Sequence[Calla aarray[i][1:] = [function(temp) for function in afunctions] - return array(aarray, aheaderrow, None, headerrow, headercolumn, tableborder, cellborder, padding, alignment, title, style) + return array(aarray, aheaderrow, None, headerrow, headercolumn, tableborder, cellborder, padding, alignment, title, style, file, check) -def function(xmin: float, xmax: float, xstep: float, afunction: Callable[[float], float], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: Optional[bool] = None, title: Optional[str] = None, style: style_types = style_types.light) -> int: +def function(xmin: float, xmax: float, xstep: float, afunction: Callable[[float], float], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: str = "", title: Optional[str] = None, style: style_types = style_types.light, file: TextIO = sys.stdout, check: bool = True) -> int: """Convert single function to array and output as table.""" - return functions(xmin, xmax, xstep, [afunction], headerrow, headercolumn, tableborder, cellborder, padding, alignment, title, style) + return functions(xmin, xmax, xstep, (afunction,), headerrow, headercolumn, tableborder, cellborder, padding, alignment, title, style, file, check) diff --git a/tables.cpp b/tables.cpp index 8101dec..58c67fe 100644 --- a/tables.cpp +++ b/tables.cpp @@ -405,8 +405,8 @@ int main() array[i][j] = rand() % 2; tables::options aoptions; - aoptions.boolalpha = true; - // tables::options aoptions = {.boolalpha = true}; + aoptions.alignment |= ios_base::boolalpha; + // tables::options aoptions = {.alignment |= ios_base::boolalpha}; for (const tables::style_type style : tables::style_types) { diff --git a/tables.hpp b/tables.hpp index 71998a2..fb7723b 100644 --- a/tables.hpp +++ b/tables.hpp @@ -58,10 +58,10 @@ namespace tables bool tableborder = true; bool cellborder = false; unsigned padding = 1; - ios_base &(*alignment)(ios_base &) = left; - bool boolalpha = false; + ios_base::fmtflags alignment; const char *title = nullptr; style_type style = style_light; + ostream &ostr = cout; bool check = true; }; @@ -75,7 +75,7 @@ namespace tables if (iscntrl(c)) { cerr << "\nError: Control character in string.\n"; - cout << "Control character: " << (int)c << '\n'; + cerr << "Control character: " << (int)c << '\n'; } size_t length = mbstowcs(nullptr, str.c_str(), 0); @@ -92,7 +92,6 @@ namespace tables if (width == -1) throw range_error("Error: wcswidth failed. Nonprintable wide character."); - return width; } @@ -194,45 +193,45 @@ namespace tables } if (title and title[0] != '\0') - cout << wrap(title, width) << '\n'; - - if (aoptions.alignment) - cout << aoptions.alignment; + aoptions.ostr << wrap(title, width) << '\n'; const char *const *astyle = styles[aoptions.style]; + ostringstream strm; + strm << setiosflags(aoptions.alignment); + if (tableborder) { - cout << astyle[2]; + strm << astyle[2]; for (size_t j = 0; j < columns; ++j) { for (size_t k = 0; k < (2 * padding) + columnwidth[j]; ++k) - cout << astyle[0]; + strm << astyle[0]; if (j < (columns - 1)) { if (cellborder or headerrow or (!j and headercolumn)) - cout << astyle[3]; + strm << astyle[3]; else - cout << astyle[0]; + strm << astyle[0]; } } - cout << astyle[4] << '\n'; + strm << astyle[4] << '\n'; } for (size_t i = 0; i < rows; ++i) { if (tableborder) - cout << astyle[1]; + strm << astyle[1]; for (size_t j = 0; j < columns; ++j) { if ((j and cellborder) or (!i and j and headerrow) or (j == 1 and headercolumn)) - cout << astyle[1]; + strm << astyle[1]; else if (j and (tableborder or (i and headerrow) or headercolumn)) - cout << ' '; + strm << ' '; const int difference = columnwidth[j] - strcol(array[i][j]); @@ -240,48 +239,48 @@ namespace tables { const int apadding = (difference / 2); - cout << string(padding + apadding, ' ') << "\e[1m" << array[i][j] << "\e[22m" << string(padding + (difference - apadding), ' '); + strm << string(padding + apadding, ' ') << "\e[1m" << array[i][j] << "\e[22m" << string(padding + (difference - apadding), ' '); } else { - cout << string(padding, ' ') << setw(difference + array[i][j].length()) << array[i][j] << string(padding, ' '); + strm << string(padding, ' ') << setw(difference + array[i][j].length()) << array[i][j] << string(padding, ' '); } } if (tableborder) - cout << astyle[1]; + strm << astyle[1]; if (i < (rows - 1) or tableborder) - cout << '\n'; + strm << '\n'; if ((i < (rows - 1) and cellborder) or (!i and headerrow) or (i < (rows - 1) and headercolumn)) { if (tableborder) { if (cellborder or (!i and headerrow) or headercolumn) - cout << astyle[5]; + strm << astyle[5]; } for (size_t j = 0; j < columns; ++j) { if (cellborder or (!i and headerrow) or (!j and headercolumn)) for (size_t k = 0; k < (2 * padding) + columnwidth[j]; ++k) - cout << astyle[0]; + strm << astyle[0]; else if (headercolumn) - cout << string((2 * padding) + columnwidth[j], ' '); + strm << string((2 * padding) + columnwidth[j], ' '); if (j < (columns - 1)) { if (cellborder or ((!i and headerrow) and (!j and headercolumn))) - cout << astyle[6]; + strm << astyle[6]; else if (!i and headerrow) - cout << astyle[9]; + strm << astyle[9]; else if (headercolumn) { if (!j) - cout << astyle[7]; + strm << astyle[7]; else - cout << ' '; + strm << ' '; } } } @@ -289,37 +288,38 @@ namespace tables if (tableborder) { if (cellborder or (!i and headerrow)) - cout << astyle[7]; + strm << astyle[7]; else if (headercolumn) - cout << astyle[1]; + strm << astyle[1]; } - cout << '\n'; + strm << '\n'; } } if (tableborder) { - cout << astyle[8]; + strm << astyle[8]; for (size_t j = 0; j < columns; ++j) { for (size_t k = 0; k < (2 * padding) + columnwidth[j]; ++k) - cout << astyle[0]; + strm << astyle[0]; if (j < (columns - 1)) { if (cellborder or (!j and headercolumn)) - cout << astyle[9]; + strm << astyle[9]; else - cout << astyle[0]; + strm << astyle[0]; } } - cout << astyle[10]; + strm << astyle[10]; } - cout << '\n'; + strm << '\n'; + aoptions.ostr << strm.str(); return 0; } @@ -379,9 +379,7 @@ namespace tables for (size_t jj = 0; j < columns; ++j) { ostringstream strm; - - if (aoptions.boolalpha) - strm << boolalpha; + strm << setiosflags(aoptions.alignment); strm << aarray[ii][jj]; aaarray[i][j] = strm.str();