Skip to content

Commit 4584aa3

Browse files
committed
Improve naming, comments, add some -specs
1 parent efff43b commit 4584aa3

File tree

1 file changed

+44
-26
lines changed

1 file changed

+44
-26
lines changed

src/clique_table.erl

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ print(Header, Spec, Rows) ->
5858
autosize_create_table(Schema, Rows) ->
5959
autosize_create_table(Schema, Rows, []).
6060

61+
%% Currently the only constraint supported in the proplist is
62+
%% `fixed_width' with a list of columns that *must not* be shrunk
63+
%% (e.g., integer values). First column is 0.
6164
-spec autosize_create_table([any()], [[any()]], [tuple()]) -> iolist().
6265
autosize_create_table(Schema, Rows, Constraints) ->
6366
BorderSize = 1 + length(hd(Rows)),
@@ -94,31 +97,40 @@ create_table(Spec, [], _Length, IoList) ->
9497
create_table(Spec, [Row | Rows], Length, IoList) ->
9598
create_table(Spec, Rows, Length, [row(Spec, Row) | IoList]).
9699

100+
%% Measure and shrink table width as necessary to fit the console
97101
-spec get_field_widths(pos_integer(), [term()], [non_neg_integer()]) -> [non_neg_integer()].
98102
get_field_widths(MaxLineLen, Rows, Unshrinkable) ->
99103
Widths = max_widths(Rows),
100-
strip_fields(MaxLineLen, Widths, Unshrinkable).
104+
fit_widths_to_terminal(MaxLineLen, Widths, Unshrinkable).
101105

102-
strip_fields(MaxWidth, Widths, Unshrinkable) ->
106+
fit_widths_to_terminal(MaxWidth, Widths, Unshrinkable) ->
103107
Sum = lists:sum(Widths),
104108
Weights = calculate_field_weights(Sum, Widths, Unshrinkable),
105109
MustRemove = Sum - MaxWidth,
106-
new_widths(MaxWidth, MustRemove, Widths, Weights).
107-
110+
calculate_new_widths(MaxWidth, MustRemove, Widths, Weights).
111+
112+
%% Determine field weighting as proportion of total width of the
113+
%% table. Fields which were flagged as unshrinkable will be given a
114+
%% weight of 0.
115+
-spec calculate_field_weights(pos_integer(), list(pos_integer()),
116+
list(non_neg_integer())) ->
117+
list(number()).
108118
calculate_field_weights(Sum, Widths, []) ->
119+
%% If no fields are constrained as unshrinkable, simply divide
120+
%% each width by the sum of all widths for our proportions
109121
lists:map(fun(X) -> X / Sum end, Widths);
110122
calculate_field_weights(_Sum, Widths, Unshrinkable) ->
111-
%% Any column numbers represented in `Unshrinkable' will be given
112-
%% a weight of 0 and all other weights will be correspondingly
113-
%% higher
114-
NewWidths = flag_unshrinkable_widths(Widths, Unshrinkable),
115-
NewSum = lists:sum(lists:filter(fun({_X, noshrink}) -> false;
116-
(_X) -> true end,
117-
NewWidths)),
123+
TaggedWidths = flag_unshrinkable_widths(Widths, Unshrinkable),
124+
ShrinkableWidth = lists:sum(lists:filter(fun({_X, noshrink}) -> false;
125+
(_X) -> true end,
126+
TaggedWidths)),
118127
lists:map(fun({_X, noshrink}) -> 0;
119-
(X) -> X / NewSum end,
120-
NewWidths).
128+
(X) -> X / ShrinkableWidth end,
129+
TaggedWidths).
121130

131+
%% Takes a list of column widths and a list of (zero-based) index
132+
%% values of the columns that must not shrink. Returns a mixed list of
133+
%% widths and `noshrink' tuples.
122134
flag_unshrinkable_widths(Widths, NoShrink) ->
123135
{_, NewWidths} =
124136
lists:foldl(fun(X, {Idx, Mapped}) ->
@@ -131,6 +143,8 @@ flag_unshrinkable_widths(Widths, NoShrink) ->
131143
end, {0, []}, Widths),
132144
lists:reverse(NewWidths).
133145

146+
%% Calculate the proportional weight for each column for shrinking.
147+
%% Zip the results into a `{Width, Weight, Index}' tuple list.
134148
column_zip(Widths, Weights, ToNarrow) ->
135149
column_zip(Widths, Weights, ToNarrow, 0, []).
136150

@@ -141,36 +155,38 @@ column_zip([Width|Widths], [Weight|Weights], ToNarrow, Index, Accum) ->
141155
column_zip(Widths, Weights, ToNarrow, Index+1,
142156
[{NewWidth, Weight, Index}] ++ Accum).
143157

144-
new_widths(_Max, ToNarrow, Widths, _Weights) when ToNarrow =< 0 ->
158+
%% Given the widths based on data to be displayed, return widths
159+
%% necessary to narrow the table to fit the console.
160+
calculate_new_widths(_Max, ToNarrow, Widths, _Weights) when ToNarrow =< 0 ->
161+
%% Console is wide enough, no need to narrow
145162
Widths;
146-
new_widths(MaxWidth, ToNarrow, Widths, Weights) ->
147-
tweak_widths(MaxWidth, column_zip(Widths, Weights, ToNarrow)).
163+
calculate_new_widths(MaxWidth, ToNarrow, Widths, Weights) ->
164+
fix_rounding(MaxWidth, column_zip(Widths, Weights, ToNarrow)).
148165

149166
%% Rounding may introduce an error. If so, remove the requisite number
150167
%% of spaces from the widest field
151-
tweak_widths(Target, Cols) ->
168+
fix_rounding(Target, Cols) ->
152169
Widths = lists:map(fun({Width, _Weight, _Idx}) -> Width end,
153170
Cols),
154171
SumWidths = lists:sum(Widths),
155172
shrink_widest(Target, SumWidths, Widths, Cols).
156173

157-
%% If our target table width is narrower than our calculated width,
158-
%% look for the widest column with a non-zero weight (zero weights are
159-
%% constrained to not be narrowed) and shrink it by the necessary
160-
%% value.
174+
%% Determine whether our target table width is wider than the terminal
175+
%% due to any rounding error and find columns eligible to be shrunk.
161176
shrink_widest(Target, Current, Widths, _Cols) when Target =< Current ->
162177
Widths;
163178
shrink_widest(Target, Current, Widths, Cols) ->
164179
Gap = Current - Target,
165180
NonZeroWeighted = lists:dropwhile(fun({_Width, 0, _Idx}) -> true;
166181
(_) -> false end,
167182
Cols),
168-
shrink_nonzero_widest(Gap, NonZeroWeighted, Widths).
169-
183+
shrink_widest_weighted(Gap, NonZeroWeighted, Widths).
170184

171-
shrink_nonzero_widest(_Gap, [], Widths) ->
185+
%% Take the widest column with a non-zero weight and reduce it by the
186+
%% amount necessary to compensate for any rounding error.
187+
shrink_widest_weighted(_Gap, [], Widths) ->
172188
Widths; %% All columns constrained to fixed widths, nothing we can do
173-
shrink_nonzero_widest(Gap, Cols, Widths) ->
189+
shrink_widest_weighted(Gap, Cols, Widths) ->
174190
SortedCols = lists:sort(
175191
fun({WidthA, _WeightA, _IdxA}, {WidthB, _WeightB, _IdxB}) ->
176192
WidthA > WidthB
@@ -179,7 +195,9 @@ shrink_nonzero_widest(Gap, Cols, Widths) ->
179195
NewWidth = ?MINWIDTH(OldWidth - Gap),
180196
replace_list_element(Idx, NewWidth, Widths).
181197

182-
%% Zero-based indexing. Deal with it
198+
%% Replace the item at `Index' in `List' with `Element'.
199+
%% Zero-based indexing.
200+
-spec replace_list_element(non_neg_integer(), term(), list()) -> list().
183201
replace_list_element(Index, Element, List) ->
184202
{Prefix, Suffix} = lists:split(Index, List),
185203
Prefix ++ [Element] ++ tl(Suffix).

0 commit comments

Comments
 (0)