1:- encoding(utf8).
2:- module(clitable, [
3 clitable/1,
4 clitable/2
5 ]). 6
7clitable(Rows) :-
8 clitable(Rows, []).
9
10clitable(Rows, Options) :-
11 transpose(Rows, Cols),
12 add_headers_to_cols(Options, Cols, Cols_),
13 maplist(get_col_width, Cols_, ColWidths),
14 default_options(Default_Options),
15 merge_options(Options, Default_Options, Options_),
16 clitable(Rows, Options_, ColWidths).
17
18clitable(Rows, Options, ColWidths) :-
19 print_header(Options, ColWidths),
20 forall(
21 member(Row, Rows),
22 print_row(Options, Row, ColWidths)
23 ),
24 print_footer(Options, ColWidths).
25
26default_options(Default_Options) :-
27 Default_Options = [
28 top('â'), top_left('â'), top_mid('â¤'), top_right('â'),
29 bottom('â'), bottom_left('â'), bottom_mid('â§'), bottom_right('â'),
30 space(' '), left('â'), mid('â'), right('â'),
31 mid_space('â'), mid_left('â'), mid_mid('â¼'), mid_right('â¢')
32 ].
33
(Options, Cols, Cols_With_Headers) :-
35 ( option(head(Header), Options) ->
36 maplist(add_header_to_col, Cols, Header, Cols_With_Headers)
37 ; Cols_With_Headers = Cols ).
38
(Col, Header, [Header|Col]).
40
(Options, ColWidths) :-
42 print_char_row(Options, ColWidths, [top, top_left, top_mid, top_right]),
43 ( option(head(Header), Options) ->
44 print_row(Options, Header, ColWidths),
45 print_char_row(Options, ColWidths, [mid_space, mid_left, mid_mid, mid_right])
46 ; true ).
47
(Options, ColWidths) :-
49 print_char_row(Options, ColWidths, [bottom, bottom_left, bottom_mid, bottom_right]).
50
51print_char_row(Options, ColWidths, Identifiers) :-
52 maplist(option_char(Options), Identifiers, [Space, Left, Mid, Right]),
53 option(space(OriginalSpace), Options),
54 atom_length(OriginalSpace, OriginalSpace_Length),
55 apply_length(OriginalSpace_Length, Space, Space_),
56 merge_options([space(Space_), left(Left), mid(Mid), right(Right)], Options, Char_Row_Options),
57 maplist(mock_cell(Space), ColWidths, CellMocks),
58 print_row(Char_Row_Options, CellMocks, ColWidths).
59
60apply_length(Length, Space, Space_With_Length) :-
61 atom_length(Space, 0), !,
62 apply_length(Length, ' ', Space_With_Length).
63apply_length(Length, Space, Space_With_Length) :-
64 atomic_list_concat(['~`', Space, 't~', Length, '|'], Format),
65 format(atom(Space_With_Length), Format, []).
66
67option_char(Options, Option, Char) :-
68 KV =.. [Option, Char],
69 option(KV, Options).
70
71print_row(Options, [First|Cells], [FirstWidth|ColWidths]) :-
72 print_first_cell(Options, First, FirstWidth),
73 maplist(print_cell(Options), Cells, ColWidths),
74 option(right(Char), Options),
75 write(Char),
76 nl.
77
78print_first_cell(Options, Cell, ColWidth) :-
79 option(left(Char), Options),
80 merge_options([mid(Char)], Options, Options_For_First),
81 print_cell(Options_For_First, Cell, ColWidth).
82
83print_cell(Options, Cell, ColWidth) :-
84 option(space(Space), Options),
85 option(mid(Middle), Options),
86 Width is ColWidth,
87 Center = '~t~w~t',
88 atomic_list_concat([Center, '~', Width, '|'], Format),
89 format(atom(Entry), Format, [ Cell ]),
90 atomic_list_concat([Middle, Space, Entry, Space], Result),
91 write(Result).
92
93get_col_width(Cells, MaxWidth) :-
94 maplist(get_cell_width, Cells, CellWidths),
95 max_list(CellWidths, MaxWidth).
96
97get_cell_width(Cell, Width) :-
98 atom_length(Cell, Width).
99
100mock_cell(_Char, 0, '') :- !.
101mock_cell(Char, N, A) :-
102 N_ is N-1,
103 mock_cell(Char, N_, A_),
104 atomic_concat(Char, A_, A).
105
106transpose([], []).
107transpose([L|Ls], Ts) :-
108 maplist(same_length(L), Ls),
109 foldl(transpose_, L, Ts, [L|Ls], _).
110
111transpose_(_, Fs, Lists0, Lists) :-
112 maplist(list_first_rest, Lists0, Fs, Lists).
113
114list_first_rest([L|Ls], L, Ls)