Update format.cpp & format.h + Update format tests
This commit is contained in:
parent
092b8889e4
commit
a7910e1fe7
3 changed files with 458 additions and 161 deletions
|
@ -4,49 +4,85 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
|||
|
||||
Author: Soonho Kong
|
||||
*/
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include "format.h"
|
||||
#include "test.h"
|
||||
#include "sexpr_funcs.h"
|
||||
|
||||
using namespace lean;
|
||||
|
||||
void color(const char *s, int n) {
|
||||
std::cout << "\e[" << (31 + n % 7) << "m" << s << "\e[0m";
|
||||
}
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
static void tst1() {
|
||||
format f_atom1("foo");
|
||||
format f_atom2("bar");
|
||||
format f_atom3(1);
|
||||
format f_atom4(3.1415);
|
||||
format f1(f_atom1, f_atom2);
|
||||
format f2(f1);
|
||||
format f3 = choice(f1, f2);
|
||||
format f1(highlight(f_atom1), f_atom2);
|
||||
// format f2{f_atom1, f_atom2, highlight(f_atom3, format::format_color::ORANGE), f_atom4};
|
||||
format f2{f_atom1, highlight(f_atom3, format::format_color::ORANGE)};
|
||||
format f3 = compose(f1, f2);
|
||||
format f4 = nest(3, f3);
|
||||
format f5 = line();
|
||||
format f6(f4, f5);
|
||||
format f7(f6, f3);
|
||||
format f7 = nest(10, format{f6, f4, f6, f4});
|
||||
// format f8(f_atom1, nest(3, format(line(), f_atom1)));
|
||||
format f8 = f7;
|
||||
format f9 = f7 + f8;
|
||||
format f10;
|
||||
f10 += f6 + f5 + f3;
|
||||
format f11 = above(f1, above(above(f2, f3), f4));
|
||||
|
||||
std::cout << "f_atom1 = " << f_atom1 << std::endl
|
||||
<< "f_atom2 = " << f_atom2 << std::endl
|
||||
<< "f_atom3 = " << f_atom3 << std::endl
|
||||
<< "f_atom4 = " << f_atom4 << std::endl
|
||||
;
|
||||
std::vector<std::pair<std::string, format> > v =
|
||||
{{"f1", f1},
|
||||
{"f2", f2},
|
||||
{"f3", f3},
|
||||
{"f4", f4},
|
||||
{"f5", f5},
|
||||
{"f6", f6},
|
||||
{"f7", f7},
|
||||
{"f8", f8},
|
||||
{"f9", f9},
|
||||
{"f10", f10},
|
||||
{"f11", f11},
|
||||
};
|
||||
|
||||
std::cout << "f1 = " << f1 << std::endl
|
||||
<< "f2 = " << f2 << std::endl
|
||||
<< "f3 = " << f3 << std::endl
|
||||
<< "f4 = " << f4 << std::endl
|
||||
<< "f5 = " << f5 << std::endl
|
||||
<< "f6 = " << f6 << std::endl
|
||||
<< "f7 = " << f7 << std::endl
|
||||
;
|
||||
std::for_each(v.begin(), v.end(),
|
||||
[](std::pair<std::string, format> const & p) {
|
||||
cout << "---- " << p.first << " ----------" << endl
|
||||
<< p.second << endl
|
||||
<< "--------------------" << endl << endl;
|
||||
});
|
||||
|
||||
color("This ", 0);
|
||||
color("is ", 1);
|
||||
color("how ", 2);
|
||||
color("we ", 3);
|
||||
color("work.", 4);
|
||||
std::cout << std::endl;
|
||||
// std::vector<std::string> ss = {"Last", "weekend's", "revelation", "that", "J.K.", "Rowling", "is", "the", "author", "of", "the", "critically", "acclaimed", "and", "--", "until", "now", "--", "commercially", "unsuccessful", "crime", "novel", "The", "Cuckoo's", "Calling", "has", "electrified", "the", "book", "world", "and", "solidified", "Rowling's", "reputation", "as", "a", "genuine", "writing", "talent:", "After", "all,", "if", "she", "can", "impress", "the", "critics", "without", "the", "benefit", "of", "her", "towering", "reputation,", "then", "surely", "her", "success", "is", "deserved."};
|
||||
|
||||
std::vector<std::string> ss = {"Last", "weekend's", "revelation", "that", "J.K.", "Rowling", "is", "the", "author", "of", "the", "critically", "acclaimed"};
|
||||
|
||||
std::vector<format> sl = {f1, f2, f3, f4};
|
||||
|
||||
cout << "fill" << endl;
|
||||
cout << std::string(40, '=') << endl;
|
||||
pretty(cout, 60, fill(sl.begin(), sl.end()));
|
||||
cout << endl;
|
||||
cout << std::string(40, '=') << endl;
|
||||
|
||||
|
||||
cout << "stack" << endl;
|
||||
cout << std::string(40, '=') << endl;
|
||||
pretty(cout, 60, stack(sl.begin(), sl.end()));
|
||||
cout << endl;
|
||||
cout << std::string(40, '=') << endl;
|
||||
|
||||
cout << "spread" << endl;
|
||||
cout << std::string(40, '=') << endl;
|
||||
pretty(cout, 60, spread(sl.begin(), sl.end()));
|
||||
cout << endl;
|
||||
cout << std::string(40, '=') << endl;
|
||||
|
||||
// cout << fill(ss.begin(), ss.end()) << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
|
|
@ -1,96 +1,245 @@
|
|||
/*
|
||||
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
|
||||
Author: Soonho Kong
|
||||
Author: Soonho Kong
|
||||
*/
|
||||
#include <cstring>
|
||||
#include "sexpr.h"
|
||||
#include "format.h"
|
||||
#include "sexpr_funcs.h"
|
||||
|
||||
namespace lean {
|
||||
std::ostream & layout(std::ostream & out, sexpr const & s) {
|
||||
if(is_cons(s)) {
|
||||
sexpr v = cdr(s);
|
||||
|
||||
switch (to_int(car(s))) {
|
||||
case format::format_kind::NIL:
|
||||
out << "NIL";
|
||||
break;
|
||||
case format::format_kind::NEST:
|
||||
out << "NEST("
|
||||
<< car(v)
|
||||
<< ", ";
|
||||
layout(out, cdr(v));
|
||||
out << ")";
|
||||
break;
|
||||
case format::format_kind::COMPOSE:
|
||||
out << "COMPOSE(";
|
||||
layout(out, car(v));
|
||||
out << ", ";
|
||||
layout(out, cdr(v));
|
||||
out << ")";
|
||||
break;
|
||||
case format::format_kind::CHOICE:
|
||||
out << "CHOICE(";
|
||||
layout(out, car(v));
|
||||
out << ", ";
|
||||
layout(out, cdr(v));
|
||||
out << ")";
|
||||
break;
|
||||
case format::format_kind::LINE:
|
||||
out << "LINE()";
|
||||
break;
|
||||
static int default_width = 78;
|
||||
|
||||
std::ostream & layout(std::ostream & out, sexpr const & s) {
|
||||
lean_assert(!is_nil(s));
|
||||
switch (format::sexpr_kind(s)) {
|
||||
case format::format_kind::NEST:
|
||||
case format::format_kind::CHOICE:
|
||||
case format::format_kind::COMPOSE:
|
||||
lean_unreachable();
|
||||
break;
|
||||
|
||||
case format::format_kind::NIL:
|
||||
out << "";
|
||||
break;
|
||||
|
||||
case format::format_kind::LINE:
|
||||
out << std::endl;
|
||||
break;
|
||||
|
||||
case format::format_kind::TEXT:
|
||||
{
|
||||
sexpr const & v = cdr(s);
|
||||
if(is_string(v)) {
|
||||
out << to_string(v);
|
||||
} else {
|
||||
out << v;
|
||||
}
|
||||
} else {
|
||||
out << s;
|
||||
break;
|
||||
}
|
||||
|
||||
case format::format_kind::COLOR_BEGIN:
|
||||
{
|
||||
format::format_color c = static_cast<format::format_color>(to_int(cdr(s)));
|
||||
out << "\e[" << (31 + c % 7) << "m";
|
||||
break;
|
||||
}
|
||||
|
||||
case format::format_kind::COLOR_END:
|
||||
out << "\e[0m";
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, format const & f) {
|
||||
return layout(out, f.m_value);
|
||||
std::ostream & layout_list(std::ostream & out, sexpr const & s) {
|
||||
foreach(s, [&out](sexpr const & s) {
|
||||
layout(out, s);
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
sexpr flatten(sexpr const & s) {
|
||||
if(is_cons(s)) {
|
||||
sexpr v = cdr(s);
|
||||
switch (to_int(car(s))) {
|
||||
case format::format_kind::NIL:
|
||||
/* flatten NIL = NIL */
|
||||
return s;
|
||||
format compose(format const & f1, format const & f2) {
|
||||
return format(format::sexpr_compose({f1.m_value, f2.m_value}));
|
||||
}
|
||||
format nest(int i, format const & f) {
|
||||
return format(format::sexpr_nest(i, f.m_value));
|
||||
}
|
||||
format highlight(format const & f, format::format_color const c) {
|
||||
return format(format::sexpr_highlight(f.m_value, c));
|
||||
}
|
||||
format line() {
|
||||
return format(format::sexpr_line());
|
||||
}
|
||||
|
||||
case format::format_kind::NEST:
|
||||
/* flatten (NEST i x) = flatten x */
|
||||
return flatten(cdr(v));
|
||||
|
||||
case format::format_kind::COMPOSE:
|
||||
/* flatten (x <> y) = flatten x <> flatten y */
|
||||
return sexpr(format::format_kind::COMPOSE,
|
||||
sexpr(flatten(car(v)),
|
||||
flatten(cdr(v))));
|
||||
|
||||
case format::format_kind::CHOICE:
|
||||
/* flatten (x <|> y) = flatten x */
|
||||
return flatten(car(v));
|
||||
|
||||
case format::format_kind::LINE:
|
||||
return sexpr(" ");
|
||||
|
||||
}
|
||||
sexpr format::flatten(sexpr const & s) {
|
||||
lean_assert(is_cons(s));
|
||||
switch (sexpr_kind(s)) {
|
||||
case format_kind::NIL:
|
||||
/* flatten NIL = NIL */
|
||||
return s;
|
||||
case format_kind::NEST:
|
||||
/* flatten (NEST i x) = flatten x */
|
||||
return flatten(sexpr_nest_s(s));
|
||||
case format_kind::COMPOSE:
|
||||
/* flatten (s_1 <> ... <> s_n ) = flatten s_1 <> ... <> flatten s_n */
|
||||
return sexpr_compose(map(sexpr_compose_list(s),
|
||||
[](sexpr const & s) {
|
||||
return flatten(s);
|
||||
}));
|
||||
case format_kind::CHOICE:
|
||||
/* flatten (x <|> y) = flatten x */
|
||||
return flatten(sexpr_choice_1(s));
|
||||
case format_kind::LINE:
|
||||
return sexpr_text(sexpr(" "));
|
||||
case format_kind::TEXT:
|
||||
case format_kind::COLOR_BEGIN:
|
||||
case format_kind::COLOR_END:
|
||||
return s;
|
||||
}
|
||||
lean_unreachable();
|
||||
return s;
|
||||
}
|
||||
|
||||
format flatten(format const & f){
|
||||
format format::flatten(format const & f){
|
||||
return format(flatten(f.m_value));
|
||||
}
|
||||
|
||||
format group(format const & f) {
|
||||
return choice(flatten(f), f);
|
||||
return choice(format::flatten(f), f);
|
||||
}
|
||||
format above(format const & f1, format const & f2) {
|
||||
return format{f1, line(), f2};
|
||||
}
|
||||
format bracket(std::string const l, format const & x, std::string const r) {
|
||||
return group(format{format(l),
|
||||
nest(2, format(line(), x)),
|
||||
line(),
|
||||
format(r)});
|
||||
}
|
||||
|
||||
// wrap = <+/>
|
||||
// wrap x y = x <> (text " " :<|> line) <> y
|
||||
format wrap(format const & f1, format const & f2) {
|
||||
return format{f1,
|
||||
choice(format(" "), line()),
|
||||
f2};
|
||||
}
|
||||
bool format::fits(int w, sexpr const & s) {
|
||||
lean_assert(is_list(s));
|
||||
if (is_nil(s))
|
||||
return true;
|
||||
if (w < 0)
|
||||
return false;
|
||||
|
||||
sexpr const & x = car(s);
|
||||
switch (sexpr_kind(x)) {
|
||||
case format_kind::NIL:
|
||||
case format_kind::COLOR_BEGIN:
|
||||
case format_kind::COLOR_END:
|
||||
return fits(w, cdr(s));
|
||||
|
||||
case format_kind::TEXT:
|
||||
{
|
||||
sexpr const & v = sexpr_text_t(x);
|
||||
int l = to_string(v).length();
|
||||
if(l > w)
|
||||
return false;
|
||||
else
|
||||
return fits(w - l, cdr(s));
|
||||
}
|
||||
|
||||
case format_kind::LINE:
|
||||
return true;
|
||||
|
||||
case format_kind::COMPOSE:
|
||||
case format_kind::NEST:
|
||||
case format_kind::CHOICE:
|
||||
lean_unreachable();
|
||||
break;
|
||||
}
|
||||
lean_unreachable();
|
||||
return false;
|
||||
}
|
||||
|
||||
sexpr format::be(int w, int k, sexpr const & s, sexpr const & r) {
|
||||
/* be w k [] = Nil */
|
||||
if(is_nil(s)) {
|
||||
if(is_nil(r)) {
|
||||
// s == Nil && r == Nil
|
||||
return sexpr();
|
||||
} else {
|
||||
// s == Nil && r != Nil
|
||||
return be(w, k, car(r), cdr(r));
|
||||
}
|
||||
}
|
||||
|
||||
void pp(lean::format const & n) { std::cout << "pp" << "\n"; }
|
||||
/* s = (i, v) :: z, where h has the type int x format */
|
||||
sexpr const & h = car(s);
|
||||
sexpr const & z = cdr(s);
|
||||
int i = to_int(car(h));
|
||||
sexpr const & v = cdr(h);
|
||||
|
||||
switch (sexpr_kind(v)) {
|
||||
case format_kind::NIL:
|
||||
return be(w, k, z, r);
|
||||
case format_kind::COLOR_BEGIN:
|
||||
case format_kind::COLOR_END:
|
||||
return sexpr(v, be(w, k, z, r));
|
||||
case format_kind::COMPOSE:
|
||||
{
|
||||
sexpr const & list = sexpr_compose_list(v);
|
||||
sexpr const & list_ = map(list,
|
||||
[i](sexpr const & s) {
|
||||
return sexpr(i, s);
|
||||
});
|
||||
return be(w, k, list_, sexpr(z, r));
|
||||
}
|
||||
case format_kind::NEST:
|
||||
{
|
||||
int j = sexpr_nest_i(v);
|
||||
sexpr const & x = sexpr_nest_s(v);
|
||||
return be(w, k, sexpr(sexpr(i + j, x), z), r);
|
||||
}
|
||||
case format_kind::TEXT:
|
||||
{
|
||||
sexpr const & l = sexpr_text_t(v);
|
||||
return sexpr(v, be(w, k + to_string(l).length(), z, r));
|
||||
}
|
||||
case format_kind::LINE:
|
||||
return sexpr(v, sexpr(sexpr_text(std::string(i, ' ')), be(w, i, z, r)));
|
||||
case format_kind::CHOICE:
|
||||
{
|
||||
sexpr const & x = sexpr_choice_1(v);
|
||||
sexpr const & y = sexpr_choice_2(v);;
|
||||
sexpr const & s1 = be(w, k, sexpr(sexpr(i, x), z), r);
|
||||
if (fits(w - k, s1)) {
|
||||
return s1;
|
||||
} else {
|
||||
sexpr const & s2 = be(w, k, sexpr(sexpr(i, y), z), r);
|
||||
return s2;
|
||||
}
|
||||
}
|
||||
}
|
||||
lean_unreachable();
|
||||
return sexpr();
|
||||
}
|
||||
|
||||
sexpr format::best(int w, int k, sexpr const & s) {
|
||||
return be(w, k, sexpr{sexpr(0, s)}, sexpr());
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, format const & f)
|
||||
{
|
||||
return pretty(out, default_width, f);
|
||||
}
|
||||
|
||||
format operator+(format const & f1, format const & f2) {
|
||||
return format{f1, format(" "), f2};
|
||||
}
|
||||
|
||||
std::ostream & pretty(std::ostream & out, unsigned w, format const & f) {
|
||||
sexpr const & b = format::best(w, 0, f.m_value);
|
||||
return layout_list(out, b);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@ Author: Soonho Kong
|
|||
*/
|
||||
#pragma once
|
||||
#include "sexpr.h"
|
||||
#include "debug.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
namespace lean {
|
||||
/**
|
||||
|
@ -14,88 +16,198 @@ namespace lean {
|
|||
|
||||
uses `sexpr` as an internal representation.
|
||||
|
||||
nil = nil sexpr
|
||||
text s = ("TEXT" s )
|
||||
nest f = ("NEST" f )
|
||||
choice f1 f2 = ("CHOICE" f1 f2)
|
||||
compose f1 f2 = ("COMPOSE" f1 f2)
|
||||
line = ("LINE")
|
||||
nest n f = ("NEST" n f)
|
||||
|
||||
nil = ["NIL"]
|
||||
text s = ("TEXT" . s)
|
||||
choice f1 f2 = ("CHOICE" f1 . f2)
|
||||
compose f1 ... fn = ["COMPOSE" f1 ... fn]
|
||||
line = ["LINE"]
|
||||
nest n f = ("NEST" n . f)
|
||||
highlight c f = ("HIGHLIGHT" c . f)
|
||||
*/
|
||||
|
||||
class format {
|
||||
sexpr m_value;
|
||||
|
||||
public:
|
||||
enum format_kind { NIL, NEST, COMPOSE, CHOICE, LINE, TEXT };
|
||||
enum format_kind { NIL, NEST, COMPOSE, CHOICE, LINE, TEXT, COLOR_BEGIN, COLOR_END};
|
||||
enum format_color {RED, GREEN, ORANGE, BLUE, PINK, CYAN, GREY};
|
||||
private:
|
||||
sexpr m_value;
|
||||
static sexpr flatten(sexpr const & s);
|
||||
static format flatten(format const & f);
|
||||
|
||||
format():m_value(sexpr()) {}
|
||||
explicit format(sexpr const & v):m_value(v) {}
|
||||
explicit format(char const * v):m_value(v) {}
|
||||
explicit format(std::string const & v):m_value(v) {}
|
||||
explicit format(int v):m_value(v) {}
|
||||
explicit format(double v):m_value(v) {}
|
||||
explicit format(name const & v):m_value(v) {}
|
||||
explicit format(mpz const & v):m_value(v) {}
|
||||
explicit format(mpq const & v):m_value(v) {}
|
||||
format(format const & f1, format const & f2) {
|
||||
m_value = sexpr(sexpr(COMPOSE), sexpr(f1.m_value, f2.m_value));
|
||||
// Functions for the internal sexpr representation
|
||||
static inline format_kind sexpr_kind(sexpr const & s) {
|
||||
lean_assert(is_cons(s));
|
||||
return static_cast<format_kind>(to_int(car(s)));
|
||||
}
|
||||
format(format const & f):m_value(f.m_value) {}
|
||||
|
||||
format_kind kind() const {
|
||||
if(is_nil(m_value)) {
|
||||
return NIL;
|
||||
}
|
||||
if(is_cons(m_value)) {
|
||||
/* CHOICE, COMPOSE, LINE, NEST */
|
||||
return static_cast<format_kind>(to_int(car(m_value)));
|
||||
}
|
||||
return TEXT;
|
||||
static inline sexpr sexpr_compose(sexpr const & l) {
|
||||
lean_assert(is_list(l));
|
||||
return sexpr(sexpr(format_kind::COMPOSE), l);
|
||||
}
|
||||
static inline sexpr sexpr_compose(std::initializer_list<sexpr> const & l) {
|
||||
return sexpr_compose(sexpr(l));
|
||||
}
|
||||
static inline sexpr const & sexpr_compose_list(sexpr const & s) {
|
||||
lean_assert(sexpr_kind(s) == format_kind::COMPOSE);
|
||||
return cdr(s);
|
||||
}
|
||||
static inline sexpr sexpr_choice(sexpr const & s1, sexpr const & s2) {
|
||||
return sexpr(sexpr(format_kind::CHOICE), sexpr(s1, s2));
|
||||
}
|
||||
static inline sexpr const & sexpr_choice_1(sexpr const & s) {
|
||||
return car(cdr(s));
|
||||
}
|
||||
static inline sexpr const & sexpr_choice_2(sexpr const & s) {
|
||||
return cdr(cdr(s));
|
||||
}
|
||||
static inline sexpr sexpr_nest(int i, sexpr const & s) {
|
||||
return sexpr(sexpr(format_kind::NEST), sexpr(i, s));
|
||||
}
|
||||
static inline int sexpr_nest_i(sexpr const & s) {
|
||||
lean_assert(sexpr_kind(s) == format_kind::NEST);
|
||||
return to_int(car(cdr(s)));
|
||||
}
|
||||
static inline sexpr const & sexpr_nest_s(sexpr const & s) {
|
||||
lean_assert(sexpr_kind(s) == format_kind::NEST);
|
||||
return cdr(cdr(s));
|
||||
}
|
||||
static inline sexpr sexpr_text(sexpr const & s) {
|
||||
return sexpr(sexpr(format_kind::TEXT), s);
|
||||
}
|
||||
static inline sexpr const & sexpr_text_t(sexpr const & s) {
|
||||
lean_assert(sexpr_kind(s) == format_kind::TEXT);
|
||||
return cdr(s);
|
||||
}
|
||||
static inline sexpr sexpr_text(std::string const & s) {
|
||||
return sexpr(sexpr(format_kind::TEXT), sexpr(s));
|
||||
}
|
||||
static inline sexpr sexpr_color_begin(format_color c) {
|
||||
return sexpr(sexpr(format_kind::COLOR_BEGIN), sexpr(c));
|
||||
}
|
||||
static inline format_color sexpr_color_begin(sexpr const & s) {
|
||||
lean_assert(sexpr_kind(s) == format_kind::TEXT);
|
||||
return static_cast<format_color>(to_int(cdr(s)));
|
||||
}
|
||||
static inline sexpr sexpr_color_end() {
|
||||
return sexpr{sexpr(format_kind::COLOR_END)};
|
||||
}
|
||||
static inline sexpr sexpr_highlight(sexpr const & s, format_color c) {
|
||||
return sexpr_compose({sexpr_color_begin(c), s, sexpr_color_end()});
|
||||
}
|
||||
static inline sexpr sexpr_nil() {
|
||||
return sexpr{sexpr(format::format_kind::NIL)};
|
||||
}
|
||||
static inline sexpr sexpr_line() {
|
||||
return sexpr{sexpr(format::format_kind::LINE)};
|
||||
}
|
||||
|
||||
unsigned hash() const { return m_value.hash(); }
|
||||
// Functions used inside of pretty printing
|
||||
static bool fits(int w, sexpr const & s);
|
||||
static sexpr better(int w, int k, sexpr const & s1, sexpr const & s2);
|
||||
static sexpr be(int w, int k, sexpr const & s, sexpr const & r);
|
||||
static sexpr best(int w, int k, sexpr const & s);
|
||||
|
||||
format & operator=(format const & s);
|
||||
format & operator=(format&& s);
|
||||
template<typename T>
|
||||
format & operator=(T const & v) { return operator=(format(v)); }
|
||||
|
||||
std::ostream & display(std::ostream & out, sexpr const & s);
|
||||
friend std::ostream & operator<<(std::ostream & out, format const & f);
|
||||
|
||||
friend format compose(format const & f1, format const & f2) {
|
||||
return format(f1, f2);
|
||||
static bool is_fnil(format const & f) {
|
||||
return to_int(car(f.m_value)) == format_kind::NIL;
|
||||
}
|
||||
static bool is_compose(format const & f) {
|
||||
return to_int(car(f.m_value)) == format_kind::COMPOSE;
|
||||
}
|
||||
static bool is_nest(format const & f) {
|
||||
return to_int(car(f.m_value)) == format_kind::NEST;
|
||||
}
|
||||
static bool is_text(format const & f) {
|
||||
return to_int(car(f.m_value)) == format_kind::TEXT;
|
||||
}
|
||||
static bool is_line(format const & f) {
|
||||
return to_int(car(f.m_value)) == format_kind::LINE;
|
||||
}
|
||||
static bool is_choice(format const & f) {
|
||||
return to_int(car(f.m_value)) == format_kind::CHOICE;
|
||||
}
|
||||
friend format choice(format const & f1, format const & f2) {
|
||||
return format(sexpr(sexpr(CHOICE), sexpr(f1.m_value, f2.m_value)));
|
||||
}
|
||||
friend format nest(int i, format const & f) {
|
||||
return format(sexpr(sexpr(NEST), sexpr(sexpr(i), f.m_value)));
|
||||
return format(sexpr_choice(f1.m_value, f2.m_value));
|
||||
}
|
||||
|
||||
friend bool is_compose(format const & f) {
|
||||
return is_cons(f.m_value) && to_int(car(f.m_value)) == format_kind::COMPOSE;
|
||||
}
|
||||
friend bool is_nest(format const & f) {
|
||||
return is_cons(f.m_value) && to_int(car(f.m_value)) == format_kind::NEST;
|
||||
}
|
||||
friend bool is_text(format const & f) {
|
||||
return !is_cons(f.m_value);
|
||||
}
|
||||
friend bool is_line(format const & f) {
|
||||
return is_cons(f.m_value) && to_int(car(f.m_value)) == format_kind::LINE;
|
||||
}
|
||||
friend bool is_choice(format const & f) {
|
||||
return is_cons(f.m_value) && to_int(car(f.m_value)) == format_kind::CHOICE;
|
||||
public:
|
||||
// Constructors
|
||||
format():m_value(sexpr_nil()) {}
|
||||
explicit format(sexpr const & v):m_value(v) {}
|
||||
explicit format(char const * v):m_value(sexpr_text(sexpr(v))) {}
|
||||
explicit format(std::string const & v):m_value(sexpr_text(sexpr(v))) {}
|
||||
explicit format(int v):m_value(sexpr_text(sexpr(std::to_string(v)))) {}
|
||||
explicit format(double v):m_value(sexpr_text(sexpr(std::to_string(v)))) {}
|
||||
explicit format(name const & v):m_value(sexpr_text(sexpr(v))) {}
|
||||
|
||||
// TODO: need to convert mpz and mpq to string, and then pass to sexpr
|
||||
explicit format(mpz const & v):m_value(sexpr_text(sexpr(v))) {}
|
||||
explicit format(mpq const & v):m_value(sexpr_text(sexpr(v))) {}
|
||||
format(format const & f1, format const & f2):m_value(sexpr_compose({f1.m_value, f2.m_value})) {}
|
||||
format(format const & f):m_value(f.m_value) {}
|
||||
format(std::initializer_list<format> const & l):format() {
|
||||
lean_assert(l.size() >= 2);
|
||||
auto it = l.begin();
|
||||
sexpr const & s1 = (it++)->m_value;
|
||||
sexpr const & s2 = (it++)->m_value;
|
||||
m_value = sexpr_compose({s1, s2});
|
||||
|
||||
m_value = std::accumulate(it, l.end(), m_value,
|
||||
[](sexpr const & result, const format f) {
|
||||
return sexpr_compose({result, f.m_value});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
friend format flatten(format const & f);
|
||||
format_kind kind() const {
|
||||
return sexpr_kind(m_value);
|
||||
}
|
||||
unsigned hash() const { return m_value.hash(); }
|
||||
|
||||
friend format compose(format const & f1, format const & f2);
|
||||
friend format nest(int i, format const & f);
|
||||
friend format highlight(format const & f, format::format_color const c = RED);
|
||||
friend format line();
|
||||
|
||||
friend format group(format const & f);
|
||||
friend format above(format const & f1, format const & f2);
|
||||
friend format bracket(std::string const l, format const & x, std::string const r);
|
||||
friend format wrap(format const & f1, format const & f2);
|
||||
|
||||
format & operator+=(format const & f) {
|
||||
*this = format{*this, format(" "), f};
|
||||
return *this;
|
||||
}
|
||||
friend std::ostream & operator<<(std::ostream & out, format const & f);
|
||||
// x <+> y = x <> text " " <> y
|
||||
friend format operator+(format const & f1, format const & f2);
|
||||
friend std::ostream & layout(std::ostream & out, sexpr const & s);
|
||||
friend std::ostream & pretty(std::ostream & out, unsigned w, format const & f);
|
||||
};
|
||||
|
||||
inline format line() {
|
||||
return format(sexpr(format::format_kind::LINE));
|
||||
}
|
||||
format wrap(format const & f1, format const & f2);
|
||||
format compose(format const & f1, format const & f2);
|
||||
format nest(int i, format const & f);
|
||||
format highlight(format const & f, format::format_color const c);
|
||||
format line();
|
||||
format group(format const & f);
|
||||
format above(format const & f1, format const & f2);
|
||||
format bracket(std::string const l, format const & x, std::string const r);
|
||||
format wrap(format const & f1, format const & f2);
|
||||
|
||||
template <class InputIterator, typename F>
|
||||
format folddoc(InputIterator first, InputIterator last, F f) {
|
||||
auto first_elem = *first;
|
||||
return std::accumulate(++first, last, first_elem, f);
|
||||
}
|
||||
template <class InputIterator>
|
||||
format spread(InputIterator first, InputIterator last) {
|
||||
return folddoc(first, last, compose);
|
||||
}
|
||||
template <class InputIterator>
|
||||
format stack(InputIterator first, InputIterator last) {
|
||||
return folddoc(first, last, above);
|
||||
}
|
||||
template <typename InputIterator>
|
||||
format fill(InputIterator first, InputIterator last) {
|
||||
return folddoc(first, last, wrap);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue