There are three formatters so far in this library
- for
std::complex<T>
. - for
fmt::text_style
to allow you to introduce a colour/style change anywhere in yourformat_string
. - for
fmtextras::reset_colour
to put the colours etc back after changing using afmt::text_style
argument.
I'm releasing this under the LGPL version 3 see the LICENCE.md file, or COPYING for plain text
This is my formatter<std::complex<T>, Char>
class for the {fmt} library soon to be std::format
For std::complex<T>
then the format spec is as follows:
replacement_field ::= "{" [arg_id] [":" cmplx_format_spec] "}"
arg_id ::= integer | identifier
integer ::= digit+
digit ::= "0"..."9"
identifier ::= id_start id_continue*
id_start ::= "a"..."z" | "A"..."Z" | "_"
id_continue ::= id_start | digit
all standard except for cmplx_format_spec
which is as follows
cmplx_format_spec ::= cmplx_form [ format_spec_for_T ]
cmplx_form ::= [ three_char_cmplx_spec ]
three_char_cmplx_spec ::= [ style_spec ] three_char_cmplx_spec
| [ spacing ] three_char_cmplx_spec
| [ bracket ] three_char_cmplx_spec
style_spec ::= '$' | ',' | '*' | '|'
spacing ::= '_' | ';'
bracket ::= '@' | '~'
where
$
means expresion style (i.e. num plus_or_minus numi ).,
means pair style (i.e. (num, num) ).- NB: this style overrides brackets i.e.
@
as no brackets makes no sense for this style
- NB: this style overrides brackets i.e.
*
means star style (i.e. num plus_or_minus num *i ), some people like this apperently.|
means lisp style (i.e. #C(num, num) ), this syle is used in common lisp.- NB: this style overrides brackets i.e.
@
as no brackets makes no sense for this style
- NB: this style overrides brackets i.e.
_
space the,
or+
or-
;
don't space,
or+
or-
@
don't surround with brackets.~
surround with brackets.
and format_spec_for_T
is the format_specifier
for the type T.
NB: I only accept 3 chars in the three_char_cmplx_spec.
To compile the the test program testcmplx just run
$ g++ -std=c++20 -o testcmplx testcmplx.cpp -lfmt
or
$ clang++ -std=c++20 -o testcmplx testcmplx.cpp -lfmt
where $
is your prompt or use some sort of make/build system like cmake or what ever.
or
$ cmake -S . -B build # if you have just cloned from git assumming you are in the fmtextras dir
$ CC=gcc CXX=g++ cmake --build ./build --config Release
or
$ CC=clang CXX=clang++ cmake --build ./build --config Release
There are 2 colour/style formatters
- for
fmt::text_style
to allow you to introduce a colour/style change anywhere in yourformat_string
. - for
fmtextras::reset_colour
to put the colours etc back after changing using afmt::text_style
argument. - for americans there is
fmtexras::reset_color
which is an alias tofmtextras::reset_colour
.
NB: The colour stuff 1. & 2. can work with the forms of fmt::format and fmt::print and friends but 3.
(i.e. fmtextras::reset_colour
) is redundant as they do a reset any way at the end of their call, also
this works with operator""_format()
where as there is no such fuctionality by default.
Also Note: each colour/style change requires a format specifier {}
will do and a coresponding argumet of
type fmt::text_style
, be aware that the formater will ignore anything after the :
as I don't need anything.
#include "complexfmt.h"
#include "colourfmt.h"
#include "fmt/color.h"
#include <ios>
#include <vector>
#include <numeric>
#include <string>
#include <iostream>
#include <fstream>
#include <iomanip>
int main(int argc, char *argv[]){
using std::complex_literals::operator""i;
using std::complex_literals::operator""if;
using std::complex_literals::operator""il;
using std::literals::string_literals::operator""s;
using namespace fmt::literals;
std::complex<double> z = 3.1415926536 + 2.71828182845i;
std::cout << fmt::format("z == {0:,0.10} == {0:@0.10}\n{1}z {5}=={1} {0:$@;0.10} {3}=={4} {0:,;0.10}{2}\nz == {0:*;0.10} == {0}"s, z,
fg(fmt::color::green) | bg(fmt::color::red) | fmt::emphasis::bold, fmtextras::reset_colour(),
fg(fmt::color::blue) | bg(fmt::color::red) | fmt::emphasis::bold,
fg(fmt::color::yellow) | bg(fmt::color::red) | fmt::emphasis::bold,
fg(fmt::color::blue) | bg(fmt::color::red) | fmt::emphasis::bold) << std::endl;
std::cout << fmt::format("z == {:@*0^{}.{}f}", z, 25, 20) << std::endl;
std::cout << fmt::format("z == {:@ >{}.{}f}", z, 25, 20) << std::endl;
std::complex<double> w = 4.98 - 34.765i;
std::cout << fmt::format("w == {:{}.{}}", w, 25, 20) << std::endl;
std::cout << fmt::format("w == {:@*0^{}.{}f}", w, 25, 20) << std::endl;
std::cout << fmt::format("w == {:@ >{}.{}f}", w, 25, 20) << std::endl;
std::cout << fmt::format("w == {0:,0.10} == {0:@0.10}\nw == {0:$@;0.10} == {0:,;0.10}\nw == {0:*;0.10} == {0}"s, w) << std::endl;
std::cout << fmt::format("z == {z:,{width}.{precis}}", "z"_a=z, "width"_a=25, "precis"_a=20) << std::endl;
std::cout << fmt::format(fg(fmt::color::green) | bg(fmt::color::brown) | fmt::emphasis::bold,
"w == {thecomplex:$_{width}.{precis}}", "thecomplex"_a=w, "width"_a=20, "precis"_a=20) << std::endl;
std::cout << fmt::format("w == {thecomplex:,_{width}.{precis}}", "thecomplex"_a=w, "width"_a=20, "precis"_a=20) << std::endl;
std::cout << fmt::format("w == {thecomplex:|_{width}.{precis}}", "thecomplex"_a=w, "width"_a=20, "precis"_a=20) << std::endl;
fmt::print(fg(fmt::color::green) | bg(fmt::color::blue) | fmt::emphasis::bold,
"z == {thecomplex:|_{width}.{precis}}\n", "thecomplex"_a=z, "width"_a=20, "precis"_a=20);
std::cout << "w == {:|_{}.{}}"_format(w, 20, 20) << std::endl;
return 0;
}
Either of the two compiler calls will work I did both to show, I have no idea about other compilers.