Skip to content
Browse files

Add gproc:i()

  • Loading branch information...
1 parent fec8cba commit b1589f6a2b3907e663c93799751891bc3c249930 Ulf Wiger committed Aug 10, 2011
Showing with 234 additions and 6 deletions.
  1. +1 −0 README.md
  2. +1 −0 doc/README.md
  3. +2 −1 doc/edoc-info
  4. +18 −2 doc/gproc.md
  5. +40 −0 doc/gproc_info.md
  6. +9 −3 src/gproc.erl
  7. +163 −0 src/gproc_info.erl
View
1 README.md
@@ -133,6 +133,7 @@ Freiburg 2007 ([Paper available here](http://github.com/esl/gproc/blob/master/do
<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc.md" class="module">gproc</a></td></tr>
<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_app.md" class="module">gproc_app</a></td></tr>
<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_dist.md" class="module">gproc_dist</a></td></tr>
+<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_info.md" class="module">gproc_info</a></td></tr>
<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_init.md" class="module">gproc_init</a></td></tr>
<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_lib.md" class="module">gproc_lib</a></td></tr>
<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_sup.md" class="module">gproc_sup</a></td></tr></table>
View
1 doc/README.md
@@ -133,6 +133,7 @@ Freiburg 2007 ([Paper available here](erlang07-wiger.pdf)).
<tr><td><a href="gproc.md" class="module">gproc</a></td></tr>
<tr><td><a href="gproc_app.md" class="module">gproc_app</a></td></tr>
<tr><td><a href="gproc_dist.md" class="module">gproc_dist</a></td></tr>
+<tr><td><a href="gproc_info.md" class="module">gproc_info</a></td></tr>
<tr><td><a href="gproc_init.md" class="module">gproc_init</a></td></tr>
<tr><td><a href="gproc_lib.md" class="module">gproc_lib</a></td></tr>
<tr><td><a href="gproc_sup.md" class="module">gproc_sup</a></td></tr></table>
View
3 doc/edoc-info
@@ -1,3 +1,4 @@
{application,gproc}.
{packages,[]}.
-{modules,[gproc,gproc_app,gproc_dist,gproc_init,gproc_lib,gproc_sup]}.
+{modules,[gproc,gproc_app,gproc_dist,gproc_info,gproc_init,gproc_lib,
+ gproc_sup]}.
View
20 doc/gproc.md
@@ -181,7 +181,8 @@ a = aggregate_counter
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#add_global_aggr_counter-1">add_global_aggr_counter/1</a></td><td>Registers a global (unique) aggregated counter.</td></tr><tr><td valign="top"><a href="#add_global_counter-2">add_global_counter/2</a></td><td>Registers a global (non-unique) counter.</td></tr><tr><td valign="top"><a href="#add_global_name-1">add_global_name/1</a></td><td>Registers a global (unique) name.</td></tr><tr><td valign="top"><a href="#add_global_property-2">add_global_property/2</a></td><td>Registers a global (non-unique) property.</td></tr><tr><td valign="top"><a href="#add_local_aggr_counter-1">add_local_aggr_counter/1</a></td><td>Registers a local (unique) aggregated counter.</td></tr><tr><td valign="top"><a href="#add_local_counter-2">add_local_counter/2</a></td><td>Registers a local (non-unique) counter.</td></tr><tr><td valign="top"><a href="#add_local_name-1">add_local_name/1</a></td><td>Registers a local (unique) name.</td></tr><tr><td valign="top"><a href="#add_local_property-2">add_local_property/2</a></td><td>Registers a local (non-unique) property.</td></tr><tr><td valign="top"><a href="#audit_process-1">audit_process/1</a></td><td></td></tr><tr><td valign="top"><a href="#await-1">await/1</a></td><td>Equivalent to <a href="#await-2"><tt>await(Key, infinity)</tt></a>.</td></tr><tr><td valign="top"><a href="#await-2">await/2</a></td><td>Wait for a local name to be registered.</td></tr><tr><td valign="top"><a href="#cancel_wait-2">cancel_wait/2</a></td><td></td></tr><tr><td valign="top"><a href="#default-1">default/1</a></td><td></td></tr><tr><td valign="top"><a href="#first-1">first/1</a></td><td>Behaves as ets:first(Tab) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#get_env-3">get_env/3</a></td><td>Equivalent to <a href="#get_env-4"><tt>get_env(Scope, App, Key, [app_env])</tt></a>.</td></tr><tr><td valign="top"><a href="#get_env-4">get_env/4</a></td><td>Read an environment value, potentially cached as a <code>gproc_env</code> property.</td></tr><tr><td valign="top"><a href="#get_set_env-3">get_set_env/3</a></td><td>Equivalent to <a href="#get_set_env-4"><tt>get_set_env(Scope, App, Key, [app_env])</tt></a>.</td></tr><tr><td valign="top"><a href="#get_set_env-4">get_set_env/4</a></td><td>Fetch and cache an environment value, if not already cached.</td></tr><tr><td valign="top"><a href="#get_value-1">get_value/1</a></td><td>Read the value stored with a key registered to the current process.</td></tr><tr><td valign="top"><a href="#give_away-2">give_away/2</a></td><td>Atomically transfers the key <code>From</code> to the process identified by <code>To</code>.</td></tr><tr><td valign="top"><a href="#goodbye-0">goodbye/0</a></td><td>Unregister all items of the calling process and inform gproc
-to forget about the calling process.</td></tr><tr><td valign="top"><a href="#info-1">info/1</a></td><td>Similar to <code>process_info(Pid)</code> but with additional gproc info.</td></tr><tr><td valign="top"><a href="#info-2">info/2</a></td><td>Similar to process_info(Pid, Item), but with additional gproc info.</td></tr><tr><td valign="top"><a href="#last-1">last/1</a></td><td>Behaves as ets:last(Tab) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#lookup_global_aggr_counter-1">lookup_global_aggr_counter/1</a></td><td>Lookup a global (unique) aggregated counter and returns its value.</td></tr><tr><td valign="top"><a href="#lookup_global_counters-1">lookup_global_counters/1</a></td><td>Look up all global (non-unique) instances of a given Counter.</td></tr><tr><td valign="top"><a href="#lookup_global_name-1">lookup_global_name/1</a></td><td>Lookup a global unique name.</td></tr><tr><td valign="top"><a href="#lookup_global_properties-1">lookup_global_properties/1</a></td><td>Look up all global (non-unique) instances of a given Property.</td></tr><tr><td valign="top"><a href="#lookup_local_aggr_counter-1">lookup_local_aggr_counter/1</a></td><td>Lookup a local (unique) aggregated counter and returns its value.</td></tr><tr><td valign="top"><a href="#lookup_local_counters-1">lookup_local_counters/1</a></td><td>Look up all local (non-unique) instances of a given Counter.</td></tr><tr><td valign="top"><a href="#lookup_local_name-1">lookup_local_name/1</a></td><td>Lookup a local unique name.</td></tr><tr><td valign="top"><a href="#lookup_local_properties-1">lookup_local_properties/1</a></td><td>Look up all local (non-unique) instances of a given Property.</td></tr><tr><td valign="top"><a href="#lookup_pid-1">lookup_pid/1</a></td><td>Lookup the Pid stored with a key.</td></tr><tr><td valign="top"><a href="#lookup_pids-1">lookup_pids/1</a></td><td>Returns a list of pids with the published key Key.</td></tr><tr><td valign="top"><a href="#lookup_value-1">lookup_value/1</a></td><td>Lookup the value stored with a key.</td></tr><tr><td valign="top"><a href="#lookup_values-1">lookup_values/1</a></td><td>Retrieve the <code>{Pid,Value}</code> pairs corresponding to Key.</td></tr><tr><td valign="top"><a href="#mreg-3">mreg/3</a></td><td>Register multiple {Key,Value} pairs of a given type and scope.</td></tr><tr><td valign="top"><a href="#munreg-3">munreg/3</a></td><td>Unregister multiple Key items of a given type and scope.</td></tr><tr><td valign="top"><a href="#nb_wait-1">nb_wait/1</a></td><td>Wait for a local name to be registered.</td></tr><tr><td valign="top"><a href="#next-2">next/2</a></td><td>Behaves as ets:next(Tab,Key) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#prev-2">prev/2</a></td><td>Behaves as ets:prev(Tab,Key) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#reg-1">reg/1</a></td><td>Equivalent to <a href="#reg-2"><tt>reg(Key, default(Key))</tt></a>.</td></tr><tr><td valign="top"><a href="#reg-2">reg/2</a></td><td>Register a name or property for the current process.</td></tr><tr><td valign="top"><a href="#select-1">select/1</a></td><td>Equivalent to <a href="#select-2"><tt>select(all, Pat)</tt></a>.</td></tr><tr><td valign="top"><a href="#select-2">select/2</a></td><td>Perform a select operation on the process registry.</td></tr><tr><td valign="top"><a href="#select-3">select/3</a></td><td>Like <a href="#select-2"><code>select/2</code></a> but returns Limit objects at a time.</td></tr><tr><td valign="top"><a href="#select_count-1">select_count/1</a></td><td>Equivalent to <a href="#select_count-2"><tt>select_count(all, Pat)</tt></a>.</td></tr><tr><td valign="top"><a href="#select_count-2">select_count/2</a></td><td>Perform a select_count operation on the process registry.</td></tr><tr><td valign="top"><a href="#send-2">send/2</a></td><td>Sends a message to the process, or processes, corresponding to Key.</td></tr><tr><td valign="top"><a href="#set_env-5">set_env/5</a></td><td>Updates the cached value as well as underlying environment.</td></tr><tr><td valign="top"><a href="#set_value-2">set_value/2</a></td><td>Sets the value of the registeration entry given by Key.</td></tr><tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td>Starts the gproc server.</td></tr><tr><td valign="top"><a href="#table-0">table/0</a></td><td>Equivalent to <a href="#table-1"><tt>table({all, all})</tt></a>.</td></tr><tr><td valign="top"><a href="#table-1">table/1</a></td><td>Equivalent to <a href="#table-2"><tt>table(Context, [])</tt></a>.</td></tr><tr><td valign="top"><a href="#table-2">table/2</a></td><td>QLC table generator for the gproc registry.</td></tr><tr><td valign="top"><a href="#unreg-1">unreg/1</a></td><td>Unregister a name or property.</td></tr><tr><td valign="top"><a href="#unregister_name-1">unregister_name/1</a></td><td>Equivalent to <tt>unreg / 1</tt>.</td></tr><tr><td valign="top"><a href="#update_counter-2">update_counter/2</a></td><td>Updates the counter registered as Key for the current process.</td></tr><tr><td valign="top"><a href="#where-1">where/1</a></td><td>Returns the pid registered as Key.</td></tr><tr><td valign="top"><a href="#whereis_name-1">whereis_name/1</a></td><td>Equivalent to <tt>where / 1</tt>.</td></tr></table>
+to forget about the calling process.</td></tr><tr><td valign="top"><a href="#i-0">i/0</a></td><td>Similar to the built-in shell command <code>i()</code> but inserts information
+about names and properties registered in Gproc, where applicable.</td></tr><tr><td valign="top"><a href="#info-1">info/1</a></td><td>Similar to <code>process_info(Pid)</code> but with additional gproc info.</td></tr><tr><td valign="top"><a href="#info-2">info/2</a></td><td>Similar to process_info(Pid, Item), but with additional gproc info.</td></tr><tr><td valign="top"><a href="#last-1">last/1</a></td><td>Behaves as ets:last(Tab) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#lookup_global_aggr_counter-1">lookup_global_aggr_counter/1</a></td><td>Lookup a global (unique) aggregated counter and returns its value.</td></tr><tr><td valign="top"><a href="#lookup_global_counters-1">lookup_global_counters/1</a></td><td>Look up all global (non-unique) instances of a given Counter.</td></tr><tr><td valign="top"><a href="#lookup_global_name-1">lookup_global_name/1</a></td><td>Lookup a global unique name.</td></tr><tr><td valign="top"><a href="#lookup_global_properties-1">lookup_global_properties/1</a></td><td>Look up all global (non-unique) instances of a given Property.</td></tr><tr><td valign="top"><a href="#lookup_local_aggr_counter-1">lookup_local_aggr_counter/1</a></td><td>Lookup a local (unique) aggregated counter and returns its value.</td></tr><tr><td valign="top"><a href="#lookup_local_counters-1">lookup_local_counters/1</a></td><td>Look up all local (non-unique) instances of a given Counter.</td></tr><tr><td valign="top"><a href="#lookup_local_name-1">lookup_local_name/1</a></td><td>Lookup a local unique name.</td></tr><tr><td valign="top"><a href="#lookup_local_properties-1">lookup_local_properties/1</a></td><td>Look up all local (non-unique) instances of a given Property.</td></tr><tr><td valign="top"><a href="#lookup_pid-1">lookup_pid/1</a></td><td>Lookup the Pid stored with a key.</td></tr><tr><td valign="top"><a href="#lookup_pids-1">lookup_pids/1</a></td><td>Returns a list of pids with the published key Key.</td></tr><tr><td valign="top"><a href="#lookup_value-1">lookup_value/1</a></td><td>Lookup the value stored with a key.</td></tr><tr><td valign="top"><a href="#lookup_values-1">lookup_values/1</a></td><td>Retrieve the <code>{Pid,Value}</code> pairs corresponding to Key.</td></tr><tr><td valign="top"><a href="#mreg-3">mreg/3</a></td><td>Register multiple {Key,Value} pairs of a given type and scope.</td></tr><tr><td valign="top"><a href="#munreg-3">munreg/3</a></td><td>Unregister multiple Key items of a given type and scope.</td></tr><tr><td valign="top"><a href="#nb_wait-1">nb_wait/1</a></td><td>Wait for a local name to be registered.</td></tr><tr><td valign="top"><a href="#next-2">next/2</a></td><td>Behaves as ets:next(Tab,Key) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#prev-2">prev/2</a></td><td>Behaves as ets:prev(Tab,Key) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#reg-1">reg/1</a></td><td>Equivalent to <a href="#reg-2"><tt>reg(Key, default(Key))</tt></a>.</td></tr><tr><td valign="top"><a href="#reg-2">reg/2</a></td><td>Register a name or property for the current process.</td></tr><tr><td valign="top"><a href="#select-1">select/1</a></td><td>Equivalent to <a href="#select-2"><tt>select(all, Pat)</tt></a>.</td></tr><tr><td valign="top"><a href="#select-2">select/2</a></td><td>Perform a select operation on the process registry.</td></tr><tr><td valign="top"><a href="#select-3">select/3</a></td><td>Like <a href="#select-2"><code>select/2</code></a> but returns Limit objects at a time.</td></tr><tr><td valign="top"><a href="#select_count-1">select_count/1</a></td><td>Equivalent to <a href="#select_count-2"><tt>select_count(all, Pat)</tt></a>.</td></tr><tr><td valign="top"><a href="#select_count-2">select_count/2</a></td><td>Perform a select_count operation on the process registry.</td></tr><tr><td valign="top"><a href="#send-2">send/2</a></td><td>Sends a message to the process, or processes, corresponding to Key.</td></tr><tr><td valign="top"><a href="#set_env-5">set_env/5</a></td><td>Updates the cached value as well as underlying environment.</td></tr><tr><td valign="top"><a href="#set_value-2">set_value/2</a></td><td>Sets the value of the registeration entry given by Key.</td></tr><tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td>Starts the gproc server.</td></tr><tr><td valign="top"><a href="#table-0">table/0</a></td><td>Equivalent to <a href="#table-1"><tt>table({all, all})</tt></a>.</td></tr><tr><td valign="top"><a href="#table-1">table/1</a></td><td>Equivalent to <a href="#table-2"><tt>table(Context, [])</tt></a>.</td></tr><tr><td valign="top"><a href="#table-2">table/2</a></td><td>QLC table generator for the gproc registry.</td></tr><tr><td valign="top"><a href="#unreg-1">unreg/1</a></td><td>Unregister a name or property.</td></tr><tr><td valign="top"><a href="#unregister_name-1">unregister_name/1</a></td><td>Equivalent to <tt>unreg / 1</tt>.</td></tr><tr><td valign="top"><a href="#update_counter-2">update_counter/2</a></td><td>Updates the counter registered as Key for the current process.</td></tr><tr><td valign="top"><a href="#where-1">where/1</a></td><td>Returns the pid registered as Key.</td></tr><tr><td valign="top"><a href="#whereis_name-1">whereis_name/1</a></td><td>Equivalent to <tt>where / 1</tt>.</td></tr></table>
@@ -559,7 +560,22 @@ Unregister all items of the calling process and inform gproc
to forget about the calling process.
This function is more efficient than letting gproc perform these
-cleanup operations.<a name="info-1"></a>
+cleanup operations.<a name="i-0"></a>
+
+<h3>i/0</h3>
+
+
+
+
+
+<pre>i() -> ok</pre>
+<br></br>
+
+
+
+
+Similar to the built-in shell command `i()` but inserts information
+about names and properties registered in Gproc, where applicable.<a name="info-1"></a>
<h3>info/1</h3>
View
40 doc/gproc_info.md
@@ -0,0 +1,40 @@
+Module gproc_info
+=================
+
+
+<h1>Module gproc_info</h1>
+
+* [Function Index](#index)
+* [Function Details](#functions)
+
+
+
+
+
+
+__Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)).
+
+<h2><a name="index">Function Index</a></h2>
+
+
+
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#i-0">i/0</a></td><td></td></tr></table>
+
+
+
+
+<h2><a name="functions">Function Details</a></h2>
+
+
+<a name="i-0"></a>
+
+<h3>i/0</h3>
+
+
+
+
+
+<pre>i() -> ok</pre>
+<br></br>
+
+
View
12 src/gproc.erl
@@ -81,6 +81,7 @@
goodbye/0,
send/2,
info/1, info/2,
+ i/0,
select/1, select/2, select/3,
select_count/1, select_count/2,
first/1,
@@ -1153,7 +1154,7 @@ info(Pid, ?MODULE) ->
{?MODULE, lists:zf(
fun(K) ->
try V = get_value(K, Pid),
- {true, {K,V}}
+ {true, {K,V}}
catch
error:_ ->
false
@@ -1162,8 +1163,13 @@ info(Pid, ?MODULE) ->
info(Pid, I) ->
process_info(Pid, I).
-
-
+%% @spec () -> ok
+%%
+%% @doc Similar to the built-in shell command `i()' but inserts information
+%% about names and properties registered in Gproc, where applicable.
+%% @end
+i() ->
+ gproc_info:i().
%%% ==========================================================
View
163 src/gproc_info.erl
@@ -0,0 +1,163 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% @author Ulf Wiger <ulf.wiger@erlang-solutions.com>
+%%
+-module(gproc_info).
+
+-export([i/0]).
+
+-import(lists, [foldl/3]).
+-import(io, [format/2]).
+
+%% c:i() extended with gproc info
+-spec i() -> 'ok'.
+
+i() -> i(processes()).
+
+-spec i([pid()]) -> 'ok'.
+
+i(Ps) ->
+ i(Ps, length(Ps)).
+
+-spec i([pid()], non_neg_integer()) -> 'ok'.
+
+i(Ps, N) when N =< 100 ->
+ iformat("Pid", "Initial Call", "Heap", "Reds",
+ "Msgs"),
+ iformat("Registered", "Current Function", "Stack", "",
+ ""),
+ {R,M,H,S} = foldl(fun(Pid, {R0,M0,H0,S0}) ->
+ {A,B,C,D} = display_info(Pid),
+ {R0+A,M0+B,H0+C,S0+D}
+ end, {0,0,0,0}, Ps),
+ iformat("Total", "", w(H), w(R), w(M)),
+ iformat("", "", w(S), "", "");
+i(Ps, N) ->
+ iformat("Pid", "Initial Call", "Heap", "Reds",
+ "Msgs"),
+ iformat("Registered", "Current Function", "Stack", "",
+ ""),
+ paged_i(Ps, {0,0,0,0}, N, 50).
+
+paged_i([], {R,M,H,S}, _, _) ->
+ iformat("Total", "", w(H), w(R), w(M)),
+ iformat("", "", w(S), "", "");
+paged_i(Ps, Acc, N, Page) ->
+ {Pids, Rest, N1} =
+ if N > Page ->
+ {L1,L2} = lists:split(Page, Ps),
+ {L1,L2,N-Page};
+ true ->
+ {Ps, [], 0}
+ end,
+ NewAcc = foldl(fun(Pid, {R,M,H,S}) ->
+ {A,B,C,D} = display_info(Pid),
+ {R+A,M+B,H+C,S+D}
+ end, Acc, Pids),
+ case Rest of
+ [_|_] ->
+ choice(fun() -> paged_i(Rest, NewAcc, N1, Page) end);
+ [] ->
+ paged_i([], NewAcc, 0, Page)
+ end.
+
+choice(F) ->
+ case get_line('(c)ontinue (q)uit -->', "c\n") of
+ "c\n" ->
+ F();
+ "q\n" ->
+ quit;
+ _ ->
+ choice(F)
+ end.
+
+
+iformat(A1, A2, A3, A4, A5) ->
+ format("~-21s ~-33s ~8s ~8s ~4s~n", [A1,A2,A3,A4,A5]).
+
+get_line(P, Default) ->
+ case io:get_line(P) of
+ "\n" ->
+ Default;
+ L ->
+ L
+ end.
+
+w(X) ->
+ io_lib:write(X).
+
+w(X, L) ->
+ S = lists:flatten(io_lib:format("~w", [X])),
+ case length(S) of
+ Len when Len > L ->
+ lists:sublist(S, 1, L-3) ++ "...";
+ _ ->
+ S
+ end.
+
+display_info(Pid) ->
+ Res = c:display_info(Pid),
+ {gproc, GI} = gproc:info(Pid, gproc),
+ case GI of
+ [] ->
+ skip;
+ _ ->
+ display_gproc_info("Gproc: ", [{n, N,S,V} || {{n,S,N},V} <- GI]),
+ display_gproc_info(" ", [{p, N,S,V} || {{p,S,N},V} <- GI])
+ end,
+ Res.
+
+display_gproc_info(_, []) ->
+ skip;
+display_gproc_info(Hdr, [H|T] = Entries) ->
+ L = 3 + length(Hdr),
+ Max = 78 - L - 8,
+ {Ck, Cv} = info_cols(Entries, Max),
+ Fmt = fun(I, {Type, K, Sc, V}) ->
+ if Cv == 0 ->
+ io_lib:format(
+ I ++ "~w,~w: ~-" ++ i2l(Ck)
+ ++ "s ~n", [Type, Sc, w(K, Ck)]);
+ true ->
+ io_lib:format(
+ I ++ "~w,~w: ~-" ++ i2l(Ck)
+ ++ "s | ~-" ++ i2l(Cv) ++ "s~n",
+ [Type, Sc, w(K, Ck), w(V, Cv)])
+ end
+ end,
+ format(" ~s~s", [Hdr, Fmt("", H)]),
+ Indent = lists:duplicate(L, $\s),
+ lists:foreach(
+ fun(X) ->
+ io:format(Fmt(Indent, X))
+ end, T).
+
+info_cols(L, Max) ->
+ case [V || {_,_,_,V} <- L, V =/= undefined] of
+ [] ->
+ {Max, 0};
+ _ ->
+ KMax = lists:max([w_length(K) || {_,K,_,_} <- L]),
+ Ck = erlang:min(KMax, round(Max*2/3)),
+ {Ck, Max - Ck}
+ end.
+
+w_length(Term) ->
+ lists:flatlength(io_lib:format("~w", [Term])).
+
+
+i2l(I) ->
+ integer_to_list(I).

0 comments on commit b1589f6

Please sign in to comment.
Something went wrong with that request. Please try again.