pervasive type constraints
[scpubgit/DX.git] / lib / DX / TraceFormatter.pm
CommitLineData
1444edde 1package DX::TraceFormatter;
381e8dad 2
c25fbf05 3use Scalar::Util qw(blessed);
1444edde 4use List::Util qw(min);
381e8dad 5use DX::Class;
6
6162b001 7our $WS;
8our $Extra = 0;
9
1444edde 10has ambient_indent_level => (
2548ce61 11 is => 'rwp', lazy => 1, clearer => 1, default => 0, isa => Int
1444edde 12);
13
381e8dad 14sub indent_by { ' ' }
15
6162b001 16sub max_width { 78 }
17
c25fbf05 18sub format {
381e8dad 19 my ($self, $thing) = @_;
1444edde 20 local our $Indent_Level = $self->ambient_indent_level;
21 my $unindented = $self->_format($thing);
22 my $indent_level = min($Indent_Level, $self->ambient_indent_level);
23 (my $indented = $unindented)
24 =~ s/^/${\($self->indent_by x $indent_level)}/mg;
25 return $indented;
7f385fb2 26}
27
c25fbf05 28sub _format {
29 my ($self, $thing) = @_;
30 my ($as, $data) = @{blessed($thing) ? $thing->for_deparse : $thing};
6162b001 31 local $WS = ' ';
32 my $spaced = $self->${\"_format_as_${as}"}($data);#
33 if ($spaced =~ /\n/
34 or (length($spaced)
35 > ($self->max_width -
36 ((length($self->indent_by) * our $Indent_Level) + $Extra)))
37 ) {
38 local $WS = "\n";
39 local $Extra = 0;
40 return $self->${\"_format_as_${as}"}($data);
41 }
42 return $spaced;
43}
44
45sub _format_as_word_and_body {
46 my ($self, $wb) = @_;
47 my ($word, $body) = @$wb;
48 my $word_f = $self->_format_as_maybe_bareword($word).' ';
49 local $Extra = length($word_f);
50 return $word_f.$self->_format($body);
381e8dad 51}
52
c25fbf05 53sub _format_indented {
f69aaaff 54 my ($self, $thing) = @_;
55 return $self->_format($thing) if $WS eq ' ';
c25fbf05 56 our $Indent_Level;
57 local $Indent_Level = $Indent_Level + 1;
f69aaaff 58 my $unindented = $self->_format($thing);
c25fbf05 59 (my $indented = $unindented) =~ s/^/${\$self->indent_by}/mg;
60 return $indented;
1e812b19 61}
62
c25fbf05 63sub _format_as_string {
64 my ($self, $val) = @_;
1e812b19 65 # TODO: multiline handling
381e8dad 66 if ($val =~ /^\w+$/) {
67 qq{'${val}'}
68 } else {
69 qq{{'${val}'}}
70 }
71}
72
c25fbf05 73sub _format_as_symbol { $_[1] }
1e812b19 74
c25fbf05 75sub _format_as_maybe_bareword {
76 my ($self, $maybe_bareword) = @_;
77 # should stringify if required
78 return $maybe_bareword;
39351e10 79}
80
c25fbf05 81sub _format_as_number { $_[1] }
1e812b19 82
c25fbf05 83sub _format_as_boolean { $_[1] ? 'true' : 'false' }
1e812b19 84
c25fbf05 85sub _format_as_unset { 'unset' }
e442aff8 86
c25fbf05 87sub _format_as_array {
88 my ($self, $members) = @_;
6162b001 89 join $WS,
90 '{[',
f69aaaff 91 (map $self->_format_indented($_), @$members)
6162b001 92 , ']}';
1e812b19 93}
94
c25fbf05 95sub _format_as_dict {
96 my ($self, $members) = @_;
6162b001 97 join $WS, '{{', (
f69aaaff 98 map $self->_format_indented(
6162b001 99 [ word_and_body => [ $_, $members->{$_} ] ],
f69aaaff 100 ), sort keys %$members
c25fbf05 101 ), '}}';
693f2d6d 102}
103
c25fbf05 104sub _format_as_statement {
105 my ($self, $parts) = @_;
106 join ' ', map $self->_format($_), @$parts;
061f9d55 107}
108
c25fbf05 109sub _format_as_value_path {
110 my ($self, $parts) = @_;
111 join '.', map $self->_format_as_maybe_bareword($_), @$parts;
693f2d6d 112}
1e812b19 113
c25fbf05 114sub _format_as_list {
115 my ($self, $members) = @_;
6162b001 116 join $WS, '{', (
f69aaaff 117 map $self->_format_indented($_), @$members
c25fbf05 118 ), '}';
1e812b19 119}
120
c25fbf05 121sub _format_as_pairs {
122 my ($self, $members) = @_;
6162b001 123 join $WS, '{', (
f69aaaff 124 map $self->_format_indented(
6162b001 125 [ word_and_body => $_ ]
f69aaaff 126 ), @$members
c25fbf05 127 ), '}';
1e812b19 128}
381e8dad 129
c25fbf05 130sub _format_as_block {
131 my ($self, $members) = @_;
6162b001 132 join $WS, '{', (
133 join +($WS eq ' ' ? '; ' : $WS),
f69aaaff 134 map $self->_format_indented($_), @$members
c25fbf05 135 ), '}';
56f90161 136}
137
1444edde 138sub _format_as_enter_block {
139 my ($self) = @_;
140 $self->_set_ambient_indent_level($self->ambient_indent_level + 1);
141 '{'
142}
143
144sub _format_as_leave_block {
145 my ($self) = @_;
146 $self->_set_ambient_indent_level($self->ambient_indent_level - 1);
147 '}'
148}
149
381e8dad 1501;