Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 238 lines (210 sloc) 9.033 kB
0d6faf3 @rvirding Add first version of match specification generator
authored
1 %% Copyright (c) 2008-2011 Robert Virding. All rights reserved.
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
2 %%
3 %% Redistribution and use in source and binary forms, with or without
4 %% modification, are permitted provided that the following conditions
5 %% are met:
6 %%
7 %% 1. Redistributions of source code must retain the above copyright
8 %% notice, this list of conditions and the following disclaimer.
9 %% 2. Redistributions in binary form must reproduce the above copyright
10 %% notice, this list of conditions and the following disclaimer in the
11 %% documentation and/or other materials provided with the distribution.
12 %%
13 %% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14 %% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15 %% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
16 %% FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
17 %% COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
18 %% INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 %% BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 %% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 %% CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 %% LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
23 %% ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 %% POSSIBILITY OF SUCH DAMAGE.
25
26 %% File : lfe_io_pretty.erl
2670b6a @rvirding Added formatted output. Very like the erlang versions but they do
authored
27 %% Author : Robert Virding
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
28 %% Purpose : Pretty printer for Lisp Flavoured Erlang.
29
30 -module(lfe_io_pretty).
31
32 -export([print1/1,print1/2,print1/3,print1/4]).
33
4a44ac1 @rvirding More efficient pretty printing on the rest of the line.
authored
34 -compile(export_all).
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
35
2b2e1db @rvirding Mixed small improvements.
authored
36 -import(lists, [reverse/1,reverse/2,flatlength/1]).
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
37
38 %% print1(Sexpr) -> [char()].
39 %% print1(Sexpr, Depth) -> [char()].
40 %% print1(Sexpr, Depth, Indentation, LineLength) -> [char()].
4a44ac1 @rvirding More efficient pretty printing on the rest of the line.
authored
41 %% A relatively simple pretty print function, but with some
6538b03 @rvirding A maze of twisty patches, all alike.
authored
42 %% customisation. N.B. We know about the standard character macros
43 %% and use them instead of their expanded forms.
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
44
45 print1(S) -> print1(S, -1, 0, 80).
46
47 print1(S, D) -> print1(S, D, 0, 80).
48
49 print1(S, D, I) -> print1(S, D, I, 80).
50
51 print1(_, 0, _, _) -> "...";
52 print1(Symb, _, _, _) when is_atom(Symb) -> lfe_io:print1_symb(Symb);
53 print1(Numb, _, _, _) when is_integer(Numb) -> integer_to_list(Numb);
2670b6a @rvirding Added formatted output. Very like the erlang versions but they do
authored
54 print1(Numb, _, _, _) when is_float(Numb) -> io_lib_format:fwrite_g(Numb);
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
55 %% Handle some default special cases, standard character macros. These
56 %% don't increase depth as they really should.
57 print1([quote,E], D, I, L) -> ["'",print1(E, D, I+1, L)];
58 print1([backquote,E], D, I, L) -> ["`",print1(E, D, I+1, L)];
59 print1([unquote,E], D, I, L) -> [",",print1(E, D, I+1, L)];
60 print1(['unquote-splicing',E], D, I, L) -> [",@",print1(E, D, I+2, L)];
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
61 print1([Car|_]=List, D, I, L) ->
8f9832e @rvirding Improve prettyprinting of lists.
authored
62 %% Handle printable lists specially.
63 case io_lib:printable_list(List) of
4a44ac1 @rvirding More efficient pretty printing on the rest of the line.
authored
64 true -> lfe_io:print1_string(List, $"); %"
8f9832e @rvirding Improve prettyprinting of lists.
authored
65 false ->
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
66 case print1_list_max(List, D-1, I+2, L) of
4a44ac1 @rvirding More efficient pretty printing on the rest of the line.
authored
67 {yes,Print} -> ["(",Print,")"];
68 no ->
8f9832e @rvirding Improve prettyprinting of lists.
authored
69 %% Customise printing of lists.
70 case indent_type(Car) of
6538b03 @rvirding A maze of twisty patches, all alike.
authored
71 none -> %Normal lists.
8f9832e @rvirding Improve prettyprinting of lists.
authored
72 ["(",print1_list(List, D-1, I+1, L),")"];
6538b03 @rvirding A maze of twisty patches, all alike.
authored
73 defun -> %Special case for defuns
74 print1_defun(List, D, I, L);
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
75 N when is_integer(N) -> %Special N first elements
76 print1_type(List, D, I, L, N)
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
77 end
8f9832e @rvirding Improve prettyprinting of lists.
authored
78 end
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
79 end;
80 print1([], _, _, _) -> "()";
81 print1({}, _, _, _) -> "#()";
82 print1(Tup, D, I, L) when is_tuple(Tup) ->
4a44ac1 @rvirding More efficient pretty printing on the rest of the line.
authored
83 Es = tuple_to_list(Tup),
2b2e1db @rvirding Mixed small improvements.
authored
84 case print1_list_max(Es, D-1, I+3, L) of
4a44ac1 @rvirding More efficient pretty printing on the rest of the line.
authored
85 {yes,Print} -> ["#(",Print,")"];
86 no -> ["#(",print1_list(Es, D-1, I+2, L),")"]
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
87 end;
88 print1(Bit, _, _, _) when is_bitstring(Bit) ->
89 ["#B(",lfe_io:print1_bits(Bit, 30),$)]; %First 30 bytes
8f9832e @rvirding Improve prettyprinting of lists.
authored
90 print1(Other, _, _, _) ->
91 lfe_io:print1(Other). %Use standard LFE for rest
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
92
6538b03 @rvirding A maze of twisty patches, all alike.
authored
93 %% print1_defun(List, Depth, Indentation, LineLength) -> [char()].
94 %% Print a defun depending on whether it is traditional or matching.
95
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
96 print1_defun([Def,Name,Args|Rest], D, I, L) when is_atom(Name), D > 3 ->
6538b03 @rvirding A maze of twisty patches, all alike.
authored
97 Dcs = atom_to_list(Def), %Might not actually be defun
98 Ncs = atom_to_list(Name),
99 case lfe_lib:is_symb_list(Args) of
100 true -> %Traditional
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
101 Acs = print1(Args, D-2, I + length(Dcs) + length(Ncs) + 3, L),
102 Tcs = print1_tail(Rest, D-3, I+2, L),
6538b03 @rvirding A maze of twisty patches, all alike.
authored
103 ["(",Dcs," ",Ncs," ",Acs,Tcs,")"];
104 false -> %Matching
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
105 Tcs = print1_tail([Args|Rest], D-2, I+2, L),
6538b03 @rvirding A maze of twisty patches, all alike.
authored
106 ["(",Dcs," ",Ncs,Tcs,")"]
107 end;
108 print1_defun(List, D, I, L) ->
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
109 %% Too short to get worked up about, or not a "proper" defun or
110 %% not enough depth.
6538b03 @rvirding A maze of twisty patches, all alike.
authored
111 ["(",print1_list(List, D-1, I+1, L),")"].
112
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
113 %% print1_type(List, Depth, Indentation, LineLength, TypeCount) -> [char()].
114 %% Print a special type form indenting first TypeCount elements afer
115 %% type and rest indented 2 steps.
116
117 print1_type([Car|Cdr], D, I, L, N) when D > 2 ->
118 %% Handle special lists, we KNOW Car is an atom.
119 Cs = atom_to_list(Car),
120 NewI = I + length(Cs) + 2,
121 {Spec,Rest} = split(N, Cdr),
122 Tcs = [print1_list(Spec, D-1, NewI, L),
123 print1_tail(Rest, D-2, I+2, L)],
124 ["(" ++ Cs," ",Tcs,")"];
125 print1_type(List, D, I, L, _) ->
126 %% Too short to get worked up about or not enough depth.
127 [$(,print1_list(List, D-1, I+1, L),$)].
128
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
129 %% split(N, List) -> {List1,List2}.
130 %% Split a list into two lists, the first containing the first N
131 %% elements and the second the rest. Be tolerant of too few elements.
132
133 split(0, L) -> {[],L};
134 split(_, []) -> {[],[]};
135 split(N, [H|T]) ->
136 {H1,T1} = split(N-1, T),
137 {[H|H1],T1}.
138
4a44ac1 @rvirding More efficient pretty printing on the rest of the line.
authored
139 %% print1_list_max(List, Depth, Indentation, LineLength) -> {yes,Chars} | no.
140 %% Maybe print a list on one line, but abort if it goes past
141 %% LineLength.
142
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
143 print1_list_max([], _, _, _) -> {yes,[]};
2b2e1db @rvirding Mixed small improvements.
authored
144 print1_list_max(_, 0, _, _) -> {yes,"..."};
4a44ac1 @rvirding More efficient pretty printing on the rest of the line.
authored
145 print1_list_max([Car|Cdr], D, I, L) ->
146 Cs = print1(Car, D, 0, 99999), %Never break the line
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
147 print1_tail_max(Cdr, D-1, I + flatlength(Cs), L, [Cs]).
4a44ac1 @rvirding More efficient pretty printing on the rest of the line.
authored
148
149 %% print1_tail_max(Tail, Depth, Indentation, LineLength) -> {yes,Chars} | no.
150 %% Maybe print the tail of a list on one line, but abort if it goes
5ee43a7 @rvirding Lambda args can now have don't care variables, plus small cleanups.
authored
151 %% past LineLength. We know about dotted pairs. When we reach depth 0
152 %% we just quit as we know necessary "..." will have come from an
153 %% earlier print1 at same depth.
4a44ac1 @rvirding More efficient pretty printing on the rest of the line.
authored
154
155 print1_tail_max(_, _, I, L, _) when I >= L -> no; %No more room
5ee43a7 @rvirding Lambda args can now have don't care variables, plus small cleanups.
authored
156 print1_tail_max([], _, _, _, Acc) -> {yes,reverse(Acc)};
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
157 print1_tail_max(_, 0, _, _, Acc) -> {yes,reverse(Acc, [" ..."])};
4a44ac1 @rvirding More efficient pretty printing on the rest of the line.
authored
158 print1_tail_max([Car|Cdr], D, I, L, Acc) ->
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
159 Cs = print1(Car, D, 0, 99999), %Never break the line
2b2e1db @rvirding Mixed small improvements.
authored
160 print1_tail_max(Cdr, D-1, I + flatlength(Cs) + 1, L, [Cs," "|Acc]);
4a44ac1 @rvirding More efficient pretty printing on the rest of the line.
authored
161 print1_tail_max(S, D, I, L, Acc) ->
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
162 Cs = print1(S, D, 0, 99999), %Never break the line
163 print1_tail_max([], D-1, I + flatlength(Cs) + 3, L, [Cs," . "|Acc]).
4a44ac1 @rvirding More efficient pretty printing on the rest of the line.
authored
164
8f9832e @rvirding Improve prettyprinting of lists.
authored
165 %% print1_list(List, Depth, Indentation, LineLength)
166 %% Print a list, one element per line. No leading/trailing ().
167
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
168 print1_list([], _, _, _) -> [];
2b2e1db @rvirding Mixed small improvements.
authored
169 print1_list(_, 0, _, _) -> "...";
8f9832e @rvirding Improve prettyprinting of lists.
authored
170 print1_list([Car|Cdr], D, I, L) ->
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
171 [print1(Car, D, I, L),print1_tail(Cdr, D-1, I, L)].
8f9832e @rvirding Improve prettyprinting of lists.
authored
172
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
173 %% print1_tail(Tail, Depth, Indentation, LineLength)
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
174 %% Print the tail of a list decreasing the depth for each element. We
175 %% know about dotted pairs.
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
176
5ee43a7 @rvirding Lambda args can now have don't care variables, plus small cleanups.
authored
177 print1_tail([], _, _, _) -> "";
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
178 print1_tail(_, 0, _, _) -> "...";
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
179 print1_tail([Car|Cdr], D, I, L) ->
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
180 ["\n",blanks(I, []),print1(Car, D, I, L),print1_tail(Cdr, D-1, I, L)];
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
181 print1_tail(S, D, I, L) ->
12dbb04 @rvirding Clean up handling of print depth and make it consistent.
authored
182 [" .\n",blanks(I, print1(S, D, I, L))].
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
183
184 blanks(N, Tail) -> string:chars($\s, N, Tail).
185
186 %% indent_type(Form) -> N | none.
187 %% Defines special indentation. None means default, N is number of
188 %% sexprs in list which are indented *after* Form while all following
189 %% that end up at indent+2.
190
191 %% Old style forms.
192 indent_type('define') -> 1;
193 indent_type('define-module') -> 1;
194 indent_type('define-syntax') -> 1;
195 indent_type('define-record') -> 1;
196 indent_type('begin') -> 0;
197 indent_type('let-syntax') -> 1;
198 indent_type('syntax-rules') -> 0;
199 indent_type('macro') -> 0;
200 %% New style forms.
201 indent_type('defmodule') -> 1;
6538b03 @rvirding A maze of twisty patches, all alike.
authored
202 indent_type('defun') -> defun;
203 indent_type('defmacro') -> defun;
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
204 indent_type('defsyntax') -> 1;
205 indent_type('defrecord') -> 1;
206 %% Core forms.
207 indent_type('progn') -> 0;
208 indent_type('lambda') -> 1;
209 indent_type('match-lambda') -> 0;
210 indent_type('let') -> 1;
211 indent_type('let-function') -> 1;
212 indent_type('letrec-function') -> 1;
213 indent_type('let-macro') -> 1;
214 indent_type('if') -> 1;
215 indent_type('case') -> 1;
216 indent_type('receive') -> 0;
217 indent_type('catch') -> 0;
218 indent_type('try') -> 1;
52d5499 @rvirding Add access to macro environment inside macros, first version
authored
219 indent_type('funcall') -> 1;
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
220 indent_type('call') -> 2;
221 indent_type('define-function') -> 1;
222 indent_type('define-macro') -> 1;
223 indent_type('eval-when-compile') -> 0;
224 %% Core macros.
225 indent_type(':') -> 2;
226 indent_type('cond') -> 999; %All following forms
227 indent_type('let*') -> 1;
228 indent_type('flet') -> 1;
229 indent_type('flet*') -> 1;
230 indent_type('fletrec') -> 1;
231 indent_type(macrolet) -> 1;
232 indent_type(syntaxlet) -> 1;
233 indent_type('do') -> 2;
234 indent_type('lc') -> 1; %List comprehensions
235 indent_type('bc') -> 1; %Binary comprehensions
0d6faf3 @rvirding Add first version of match specification generator
authored
236 indent_type('match-spec') -> 0;
2fe8ef3 @rvirding Moved prettyprinting to separate file and added max depth to
authored
237 indent_type(_) -> none.
Something went wrong with that request. Please try again.